There are 2 parts to my question. Please bear with me… just learning this stuff.
I have a GridView that allows editing, which will update a database table. Issue #1 is that I cannot seem to get the values from the GridView in my code behind. I keep getting an error. I’ve tried it several different ways and I’m at a total roadblock.
Here is the ASP.NET markup:
<asp:GridView ID="ItemView" runat="server"
AutoGenerateColumns="false" AllowPaging="true"
HorizontalAlign="Center"
PageSize="10" HeaderStyle-BackColor="#6f263d"
HeaderStyle-ForeColor="White" CellPadding="7" CellSpacing="0"
DataKeyNames="orderItemId" AllowSorting="True"
AlternatingRowStyle-BorderStyle="Solid" AlternatingRowStyle-BackColor="White"
AlternatingRowStyle-ForeColor="#6f263d" AlternatingRowStyle-CssClass="fancylink"
Font-Size="Small" RowStyle-BackColor="#63666A"
RowStyle-BorderStyle="None" RowStyle-ForeColor="White"
SelectedRowStyle-BackColor="#D3D0C8" SelectedRowStyle-ForeColor="Black"
Width="100%"
OnSelectedIndexChanged="ItemView_SelectedIndexChanged"
ShowHeaderWhenEmpty="false" PagerStyle-CssClass="fancylink"
PagerStyle-BackColor="#6f263d" PagerStyle-ForeColor="White"
PagerSettings-FirstPageText="First Page "
PagerSettings-Mode="NextPrevious" PagerSettings-NextPageText="Next Page"
PagerSettings-LastPageText="End" PagerSettings-PreviousPageText="Previous Page"
PagerStyle-HorizontalAlign="Center" PagerStyle-Width="20%"
OnPageIndexChanging="OnPageIndexChanging"
OnRowDataBound="ItemView_RowDataBound"
OnRowEditing="ItemView_EditRow"
OnRowUpdating ="ItemView_OnRowUpdating"
BorderStyle="None"
OnRowCancelingEdit ="ItemView_RowCancelingEdit"
OnRowDeleting="ItemView_DeleteRow"
OnSelectedIndexChanging="ItemView_OnSelectedIndexChanging"
AutoGenerateSelectButton="False">
<Columns>
<asp:TemplateField HeaderText="ID">
<ItemTemplate>
<asp:Label ID="lbl_itemId" runat="server" Text='<%#Eval("orderItemId") %>' ReadOnly="True"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item Description">
<ItemTemplate>
<div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;">
<asp:LinkButton ID="btn_Select" runat="server" Text='<%#Eval("item") %>' ToolTip='<%# Eval("item") %>' CommandName="Select" ItemStyle-HorizontalAlign="Center" />
</div>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="PO Num">
<ItemTemplate>
<asp:Label ID="lbl_poNum" runat="server" Text='<%#Eval("poNum") %>' NullDisplayText="--"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_poNum" runat="server" Text='<%#Eval("poNum") %>' Width="75px"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Item Amount">
<ItemTemplate>
<asp:Label ID="lbl_amount" runat="server" Text='<%#Eval("amount") %>' NullDisplayText="--"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_amount" runat="server" Text='<%#Eval("amount") %>' Width="60px"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity">
<ItemTemplate>
<asp:Label ID="lbl_quantity" runat="server" Text='<%#Eval("quantity") %>' NullDisplayText="--" ReadOnly="True"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Date Ordered">
<ItemTemplate>
<asp:Label ID="lbl_ordered" runat="server" Text='<%#Eval("ordered") %>' NullDisplayText="--"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_ordered" runat="server" Text='<%#Eval("ordered") %>' Width="75px"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Date Received">
<ItemTemplate>
<asp:Label ID="lbl_received" runat="server" Text='<%#Eval("received") %>' NullDisplayText="--"></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_received" runat="server" Text='<%#Eval("received") %>' Width="75px"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Tech Notes">
<ItemTemplate>
<div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 500px;">
<asp:Label ID="lbl_techNotes" runat="server" Text='<%#Eval("techNotes") %>' ToolTip='<%# Eval("techNotes") %>' NullDisplayText="--"></asp:Label>
</div>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txt_techNotes" runat="server" Text='<%#Eval("techNotes") %>' Width="380px"></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btn_Edit" runat="server" Text="Edit" CommandName="Edit" ItemStyle-HorizontalAlign="Center"/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="btn_Update" runat="server" Text="Update" CommandName="Update" ItemStyle-HorizontalAlign="Center" />
<asp:LinkButton ID="btn_Cancel" runat="server" Text="Cancel" CommandName="Cancel" ItemStyle-HorizontalAlign="Center" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And in my code behind:
protected void ItemView_OnRowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = ItemView.SelectedRow;
int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);
string poNum = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_poNum")).Text;
string amount = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_amount")).Text;
string quantity = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_quantity")).Text;
string ordered = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_ordered")).Text;
string received = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_received")).Text;
string techNotes = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_techNotes")).Text;
string updateQuery = "UPDATE OrderItems SET ";
bool firstField = true;
if (!string.IsNullOrEmpty(poNum))
{
updateQuery += "purchaseOrderNum = @OrderNum";
firstField = false;
}
if (!string.IsNullOrEmpty(amount))
{
if (!firstField) updateQuery += ", ";
updateQuery += "itemAmt = @Amount";
firstField = false;
}
if (!string.IsNullOrEmpty(quantity))
{
if (!firstField) updateQuery += ", ";
updateQuery += "quantity = @Quantity";
firstField = false;
}
if (!string.IsNullOrEmpty(ordered))
{
if (!firstField) updateQuery += ", ";
updateQuery += "dateOrdered = @Ordered";
firstField = false;
}
if (!string.IsNullOrEmpty(received))
{
if (!firstField) updateQuery += ", ";
updateQuery += "dateReceived = @Received";
firstField = false;
}
if (!string.IsNullOrEmpty(techNotes))
{
if (!firstField) updateQuery += ", ";
updateQuery += "techNotes = @TechNotes";
}
updateQuery += "WHERE orderItemId = @ID";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ForCustomWebApps"]))
{
using (SqlCommand cmd = new SqlCommand(updateQuery, conn))
{
cmd.Parameters.AddWithValue("@ID", id);
if (!string.IsNullOrEmpty(poNum))
cmd.Parameters.AddWithValue("@OrderNum", poNum);
if (!string.IsNullOrEmpty(amount))
cmd.Parameters.AddWithValue("@Amount", amount);
if (!string.IsNullOrEmpty(quantity))
cmd.Parameters.AddWithValue("@Quantity", quantity);
if (!string.IsNullOrEmpty(ordered))
cmd.Parameters.AddWithValue("@Ordered", ordered);
if (!string.IsNullOrEmpty(received))
cmd.Parameters.AddWithValue("@Received", received);
if (!string.IsNullOrEmpty(techNotes))
cmd.Parameters.AddWithValue("@TechNotes", techNotes);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
ItemView.EditIndex = -1;
BindGrid();
}
I have confirmed that the first 2 lines are indeed getting me the correct row (itemNum
):
GridViewRow row = ItemView.SelectedRow;
int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);
But then it just breaks. When I run it I get:
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 116: int itemNum = Convert.ToInt16(ItemView.DataKeys[e.RowIndex].Values[0]);
Line 117:
Line 118: string poNum = ((System.Web.UI.WebControls.TextBox)row.FindControl("txt_poNum")).Text;
So that’s the first problem.
The second issue is that someone can edit multiple fills in the gridview row, but they don’t HAVE to edit them all. They might enter a PONumber and an amount, but no techNotes or Received Date. I need an elegant way to check for empty fields for building my update statement. You can see what I’ve done, which is modeled off something I found on the web. Is there a better way I can do this a loop?
Thank you in advance for any help you can give me. I’m pulling my hair out!
2
Answers
The following shows one of the ways one can use a GridView in an ASP.NET Web Application (.NET Framework) project to display and update data.
Try the following:
VS 2022:
Create a new
ASP.NET Web Application (.NET Framework)
Select
ASP.NET Web Application (.NET Framework)
Click Next
Enter desired project name (ex: GridViewTestA)
Select desired framework (ex: .NET Framework 4.8)
Click Create
On the "Create a new ASP.NET Web Application" form, select Empty.
If you’re using "http" instead of "https", under "Advance", uncheck "Configure for HTTPS".
Click Create
Add Web Form to project
Open Solution Explorer
default.aspx:
Default.aspx.cs:
Resources
The following shows how one can use GridView with SqlDataSource in an ASP.NET Web Application (.NET Framework) project to display and update data.
VS 2022:
Add Web Form to project
Open Solution Explorer
detail.aspx:
detail.aspx.cs
Web.config
The following tables and data were used for testing. The table design isn’t optimal, but is sufficient for demonstration of the code in this post. If unfamiliar with database table design, read about database normalization.
Table: ItemDetail
Insert Test Data: ItemDetail
Table: OrderItems
Insert Test Data: OrderItems
Resources: