Search code examples
c#asp.netgridviewwebformsviewstate

Viewstate list loses data on click row edit in GridView


I am new to using Viewstate in asp Web forms. I have a description drop down menu that I use to show a Gridview.

However, when I click on the edit row button, the Gridview clears all data. From this:

enter image description here

to this:

enter image description here

My code is:

public partial class Default : System.Web.UI.Page
    {
        private List<PRAssembly> assemblyPR = null;

......

protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                SBOConnection.Connect();            

                if (Request.QueryString["message"] == "success")
                    AlertSuccess.Visible = true;
            }
        }

   private void bindPRGridView()
        { 
            // Create Data Table
            DataTable dt = new DataTable();
            dt.Columns.Add("LineNum", typeof(int));
            dt.Columns.Add("ItemCode", typeof(string));
            dt.Columns.Add("ItemDescription", typeof(string));
            dt.Columns.Add("Quantity", typeof(int));          

            if (assemblyPR != null)
            {     
                foreach (var item in assemblyPR)
                {
                    dt.Rows.Add(item.LineNum, item.ItemCode, item.ItemDesc, item.Quantity);
                }

                pRGridView.DataSource = dt;
                pRGridView.DataBind();

                if (pRGridView.Rows.Count > 0)
                {
                    pRGridView.UseAccessibleHeader = true;
                    pRGridView.HeaderRow.TableSection = TableRowSection.TableHeader;
                }

                pRGridView.Columns[4].Visible = true;
            }
            else
            {
                dt.Rows.Add(dt.NewRow());
                pRGridView.DataSource = dt;
                pRGridView.DataBind();

                pRGridView.Columns[4].Visible = false;

                foreach (GridViewRow row in pRGridView.Rows)
                {
                    if (row.RowType == DataControlRowType.DataRow)
                    {
                        LinkButton lb = ((LinkButton)row.FindControl("lnkRemove"));
                        lb.Visible = false;
                    }
                }
            }
        }

 protected void AddRowPurchaseRequisition(object sender, EventArgs e)
        {          
            string itemCode = ((DropDownList)pRGridView.FooterRow.FindControl("ddlItemCode")).SelectedValue;
            string itemDesc = ((DropDownList)pRGridView.FooterRow.FindControl("ddlItemDescription")).SelectedValue;
            int quantity = Int32.Parse(((TextBox)pRGridView.FooterRow.FindControl("txtQuantity")).Text);

            assemblyPR = ViewState["PRList"] as List<PRAssembly>;

            if (assemblyPR == null)
            {
                assemblyPR = new List<PRAssembly>();
                ViewState["PRList"] = assemblyPR;
            }

            // Transform data to PRAssembly Class object
            assemblyPR.Add(new PRAssembly
            {               
                ItemCode = itemCode,
                ItemDesc = itemDesc,
                Quantity = quantity
            });

            // Rebind Grid view
            bindPRGridView();
        }

 protected void pRGridView_RowEditing(object sender, GridViewEditEventArgs e)
        {      
            pRGridView.EditIndex = e.NewEditIndex;
            bindPRGridView();
        }

After the edit button click, I notice that assemblyPR is null when it comes to rebinding the gridview. How do I allow editing without losing the data?

Below is some Gridview markup

<asp:GridView ID="pRGridView"
                        runat="server"
                        AutoGenerateColumns="False"
                        AllowPaging="True"
                        AllowSorting="True"
                        ShowFooter="True"
                        OnRowEditing="pRGridView_RowEditing"
                        OnRowUpdating="pRGridView_RowUpdating"
                        OnPageIndexChanging="pRGridView_PageIndexChanging"
                        OnRowCancelingEdit="pRGridView_RowCancelingEdit"
                        PagerStyle-CssClass="bs-pagination"
                        ShowHeaderWhenEmpty="True"
                        EmptyDataText="No Records Found"
                        CssClass="table table-striped table-bordered table-hover table-condensed">
                        <Columns>
                            <asp:TemplateField ItemStyle-Width="30px" HeaderText="#">
                                <ItemTemplate>
                                    <%# Container.DataItemIndex + 1 %>
                                </ItemTemplate>
                                <%-- <FooterTemplate>
                                    <%# pRGridView.Rows.Count %>
                                </FooterTemplate>--%>
                            </asp:TemplateField>
                            <asp:TemplateField ItemStyle-Width="120px" HeaderText="Item No.">
                                <ItemTemplate>
                                    <asp:Label ID="lblItemCode" runat="server"
                                        Text='<%# Bind("ItemCode")%>'></asp:Label>
                                </ItemTemplate>
                                <EditItemTemplate>
                                    <asp:DropDownList ID="ddlItemCode" runat="server"
                                        AutoPostBack="True"
                                        SelectMethod="GetItemCodes"
                                        AppendDataBoundItems="True"
                                        OnSelectedIndexChanged="ddlItemCode_SelectedIndexChanged"
                                        Width="120px"
                                        DataTextField="Value" DataValueField="Key">
                                        <asp:ListItem Value="-1" Text="Select"></asp:ListItem>
                                    </asp:DropDownList>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="ddlItemCode" Display="Dynamic" ValidationGroup="Edit"
                                        CssClass="text-danger" ErrorMessage="The Item Code field is required." />
                                </EditItemTemplate>
                                <FooterTemplate>
                                    <asp:DropDownList ID="ddlItemCode" runat="server"
                                        AutoPostBack="True"
                                        SelectMethod="GetItemCodes"
                                        AppendDataBoundItems="True"
                                        OnSelectedIndexChanged="ddlItemCode_SelectedIndexChanged"
                                        Width="120px"
                                        DataTextField="Value" DataValueField="Key">
                                        <asp:ListItem Value="-1" Text="Select"></asp:ListItem>
                                    </asp:DropDownList>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="ddlItemCode" Display="Dynamic" ValidationGroup="Insert"
                                        CssClass="text-danger" InitialValue="-1" ErrorMessage="The Item Code field is required." />
                                </FooterTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField ItemStyle-Width="400px" HeaderText="Item Description">
                                <ItemTemplate>
                                    <asp:Label ID="lblItemDescription" runat="server" Width="120px"
                                        Text='<%# Bind("ItemDescription")%>'></asp:Label>
                                </ItemTemplate>
                                <EditItemTemplate>
                                    <asp:DropDownList ID="ddlItemDescription" runat="server"
                                        AutoPostBack="True"
                                        SelectMethod="GetItemDescriptions"
                                        AppendDataBoundItems="True"
                                        OnSelectedIndexChanged="ddlItemDescription_SelectedIndexChanged"
                                        Width="400px"
                                        DataTextField="Value" DataValueField="Value">
                                        <asp:ListItem Value="-1" Text="Select"></asp:ListItem>
                                    </asp:DropDownList>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="ddlItemDescription" Display="Dynamic" ValidationGroup="Edit"
                                        CssClass="text-danger" ErrorMessage="The Item Description field is required." />
                                </EditItemTemplate>
                                <FooterTemplate>
                                    <asp:DropDownList ID="ddlItemDescription" runat="server"
                                        AutoPostBack="True"
                                        SelectMethod="GetItemDescriptions"
                                        AppendDataBoundItems="True"
                                        OnSelectedIndexChanged="ddlItemDescription_SelectedIndexChanged"
                                        Width="400px"
                                        DataTextField="Value" DataValueField="Value">
                                        <asp:ListItem Value="-1" Text="Select"></asp:ListItem>
                                    </asp:DropDownList>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="ddlItemDescription" Display="Dynamic" ValidationGroup="Insert"
                                        CssClass="text-danger" InitialValue="-1" ErrorMessage="The Item Description field is required." />
                                </FooterTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField ItemStyle-Width="120px" HeaderText="Required Qty.">
                                <ItemTemplate>
                                    <asp:Label ID="lblAmount" runat="server"
                                        Text='<%# Bind("Quantity")%>'></asp:Label>
                                </ItemTemplate>
                                <EditItemTemplate>
                                    <asp:TextBox ID="txtQuantity" runat="server" Width="100px"
                                        Text='<%# Bind("Quantity")%>'></asp:TextBox>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="txtQuantity" Display="Dynamic" ValidationGroup="Edit"
                                        CssClass="text-danger" ErrorMessage="The Quantity field is required." />
                                    <asp:RegularExpressionValidator ControlToValidate="txtQuantity" runat="server" CssClass="text-danger" Display="Dynamic"
                                        ErrorMessage="Only numbers allowed." ValidationExpression="^[0-9]{0,6}(\.[0-9]{1,2})?$"
                                        ValidationGroup="Edit"></asp:RegularExpressionValidator>
                                </EditItemTemplate>
                                <FooterTemplate>
                                    <asp:TextBox ID="txtQuantity" runat="server" Width="100px"></asp:TextBox>
                                    <asp:RequiredFieldValidator runat="server" ControlToValidate="txtQuantity" Display="Dynamic" ValidationGroup="Insert"
                                        CssClass="text-danger" ErrorMessage="The Quantity field is required." />
                                    <asp:RegularExpressionValidator ControlToValidate="txtQuantity" runat="server" CssClass="text-danger" Display="Dynamic"
                                        ErrorMessage="Only numbers allowed." ValidationExpression="^[0-9]{0,6}(\.[0-9]{1,2})?$"
                                        ValidationGroup="Insert"></asp:RegularExpressionValidator>
                                </FooterTemplate>
                            </asp:TemplateField>
                            <asp:CommandField ShowEditButton="True" ValidationGroup="Edit" />
                            <asp:TemplateField>
                                <ItemTemplate>
                                    <asp:LinkButton ID="lnkRemove" runat="server"
                                        CommandArgument='<%# Bind("LineNum")%>'
                                        OnClientClick="return confirm('Are you sure you want to delete this row?')"
                                        Text="Delete" OnClick="DeleteRowPurchaseRequisition"></asp:LinkButton>
                                </ItemTemplate>
                                <FooterTemplate>
                                    <asp:Button ID="btnAdd" runat="server" Text="Add" ValidationGroup="Insert" CssClass="btn btn-primary btn-sm"
                                        OnClick="AddRowPurchaseRequisition" />
                                </FooterTemplate>
                            </asp:TemplateField>
                            </Columns>
                        </asp:GridView>
  </ContentTemplate>
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="pRGridView" />
                </Triggers>

Solution

  • Upon editing, assemblyPR is null because you're not assigning a value to it prior to calling bindPRGridView(). One way to fix it is by adding a line to pRGridView_RowEditing:

    protected void pRGridView_RowEditing(object sender, GridViewEditEventArgs e)
    {
        pRGridView.EditIndex = e.NewEditIndex;
        assemblyPR = ViewState["PRList"] as List<PRAssembly>;
        bindPRGridView();
    }