Losing GridView Textbox value after GridView Pagination Changes

Imoleayo Emmanuel 20 Reputation points
2024-06-16T01:03:18.18+00:00

Please help look into what i need to modify in my code. My textbox is losing values typed into its control after gridview pagination click. Thanks and code below

   <asp:GridView ID="GridView1" runat="server" Style="text-align: center;" ShowFooter="true" CssClass="table table-hover table-bordered mt-3" EmptyDataText="No record to display!"

                AutoGenerateColumns="False" AllowPaging="True" PageSize="4" DataKeyNames="student_id"

                BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px" OnPageIndexChanging="GridView1_PageIndexChanging">

                <Columns>

                    <asp:BoundField DataField="student_id" HeaderText="Student" ReadOnly="True" />

                    <asp:BoundField DataField="full_name" HeaderText="Student" ReadOnly="True" />

                    <asp:TemplateField>

                        <HeaderTemplate>

                            <asp:CheckBox ID="chkAll" runat="server" onclick="SelectAll(this);" />

                            Select All

                        </HeaderTemplate>

                        <ItemTemplate>

                            <asp:CheckBox ID="CheckBox1" runat="server" onclick="SelectOne(this)" />

                        </ItemTemplate>

                    </asp:TemplateField>

                    <asp:TemplateField HeaderText="Marks">

                        <ItemTemplate>

                            <asp:TextBox ID="txtMarks" CssClass="form-control" runat="server" EnableViewState="true"></asp:TextBox>

                        </ItemTemplate>

                        <FooterTemplate>

                            <asp:Button ID="Button1" runat="server" Text="Save" CssClass="btn btn-success" OnClick="Button1_Click" />

                            <asp:Button ID="Button2" runat="server" Text="Reset" CssClass="btn btn-danger" />

                        </FooterTemplate>

                    </asp:TemplateField>

                </Columns>

                <HeaderStyle BackColor="#5558C9" ForeColor="White" CssClass="bg-danger" />

            </asp:GridView>

private void StoreValuesInViewState(){
        Dictionary<int, string> feedbacks = new Dictionary<int, string>();

        foreach (GridViewRow row in GridView1.Rows)

        {

            if (row.RowType == DataControlRowType.DataRow)

            {

                TextBox txtFeedback = row.FindControl("txtMarks") as TextBox;

                if (txtFeedback != null)

                {

                    int customerId =

                    Convert.ToInt32(GridView1.DataKeys[row.RowIndex].Value);

                    feedbacks[customerId] = txtFeedback.Text;

                    //ViewState["Feedbacks"] = txtFeedback.Text;

                    ViewState["Feedbacks"] = feedbacks;

                }

            }

        }

}

private void LoadValuesFromViewState()

{

    if (ViewState["Feedbacks"] != null)

    {

        Dictionary<int, string> feedbacks =

            (Dictionary<int, string>)ViewState["Feedbacks"];



        

        foreach (GridViewRow row in GridView1.Rows)

        {

            if (row.RowType == DataControlRowType.DataRow)

            {

                TextBox txtFeedback = row.FindControl("txtMarks") as TextBox;

                if (txtFeedback != null)

                {

                    //TextBox txtM = (TextBox)sender;

                    //GridViewRow row = (GridViewRow)btn.NamingContainer;

                    //int id = Convert.ToInt32(gdvSearch.DataKeys[row.RowIndex].Value);

                    int customerId =

                    Convert.ToInt32(GridView1.DataKeys[row.RowIndex].Value);

                    if (feedbacks.ContainsKey(customerId))

                    {

                        txtFeedback.Text = feedbacks[customerId];

                        //txtFeedback.Text = ViewState["Feedbacks"].ToString();

                    }

                }

            }

        }

    }

}protected void 
GridView1_PageIndexChanging
(object sender, GridViewPageEventArgs e){
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,507 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,007 questions
0 comments No comments
{count} votes

Accepted answer
  1. Albert Kallal 5,256 Reputation points
    2024-06-16T21:26:50.73+00:00

    You don't show your GridView pager code, but keep in mind that when using a GV pager, then a full GV re-load occurs, and worse yet, a full page post-back occurs.

    And you also don't mention what you plan to do after writing all that code to "persist" the text box, then all all that extra work, you most likely will want to save that text box back to the database right? (I mean, you going to want to do something with those text boxes after all that amount of work, then, right?

    So, it turns out the amount of code to persist the text box is about the same to SAVE the text box values back into the database. Once we do that, then we achieve persisting of data for free efforts so to speak.

    There are 2 approaches I recommend. Which choice depends on how large your data set is you are feeding to the GV and data pager. So, for up to say maybe 300 rows, the following code will work quite nice. I note the 300 row max, since this solution involves "persisting" the GV datasource into session. So, that's why I noted this works for about 300 rows, since anything more, then we are loading and persisting too much data into session, and that going to result in performance and memory issues down the road.

    So, to persist the text box values, then we bind the textbox to the given database row and column/value that we want to use. If on paging of data, we always save the text box to the database row, then we can dump and eliminate all of the code you have trying to persist the text box, and trade that code for code that always sends/saves the text box data to the database when you page data.

    So, "some" code to send the text box back to the table is STILL MUCH LESS code then all that code that attempts to persist and save the text box into viewstate or other appropraches here.

    Worse yet? After you done all the above, then we can then send all updates to the persisted datatable back to the database WITH ONE simple operation.

    So, here is a working proof of concept of the above:.

    First, the markup with one description text box.

        <asp:GridView ID="GridView1" runat="server"
            AutoGenerateColumns="False" DataKeyNames="ID"
            CssClass="table table-hover" Width="50%"
            AllowPaging="true" PageSize="6" OnPageIndexChanging="GridView1_PageIndexChanging"
            >
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" />
                <asp:BoundField DataField="City" HeaderText="City" />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
                <asp:TemplateField HeaderText="Description">
                    <ItemTemplate>
                        <asp:TextBox ID="txtDescription"
                            runat="server" TextMode="MultiLine"
                            Text= '<%# Eval("Description") %>'
                            Height="100px" Width="330px"
                            >
                        </asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
            <PagerStyle CssClass="GridPager" />
        </asp:GridView>
        <br />
        <asp:Button ID="cmdSave" runat="server" Text="Save/Done"
            CssClass="btn btn-dark"
            OnClick="cmdSave_Click"/>
    
    

    And now the code behind is this:

           DataTable rstHotels = new DataTable();
           protected void Page_Load(object sender, EventArgs e)
           {
               if (!IsPostBack)
               {
                   LoadData();
                   Session["rstHotels"] = rstHotels;
               }
               else
               {
                   rstHotels = (DataTable)Session["rstHotels"];
               }
           }
           void LoadData()
           {
               string strSQL =
                   "SELECT * FROM tblHotelsA ORDER BY HotelName";
               rstHotels = General.MyRst(strSQL);
               GridView1.DataSource = rstHotels;
               GridView1.DataBind();
           }
           protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
           {
               GridToTable();
               GridView1.PageIndex = e.NewPageIndex;
               GridView1.DataSource = rstHotels;
               GridView1.DataBind();
           }
           void GridToTable()
           {
               // send grid rows back to table.
               foreach (GridViewRow rRow in GridView1.Rows)
               {
                   int RecordPtr = rRow.DataItemIndex; // note data index, not row index!!!
                   DataRow OneDataRow;
                   OneDataRow = rstHotels.Rows[RecordPtr];
                   OneDataRow["Description"] = ((TextBox)rRow.FindControl("txtDescription")).Text;
               }
           }
           protected void cmdSave_Click(object sender, EventArgs e)
           {
               using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
               {
                   string strSQL = "SELECT * FROM tblHotelsA";
                   using (SqlCommand cmd = new SqlCommand(strSQL, conn))
                   {
                       SqlDataAdapter da = new SqlDataAdapter(cmd);
                       SqlCommandBuilder daU = new SqlCommandBuilder(da);
                       conn.Open();
                       da.Update(rstHotels);
                   }
               }
               // code here no doubt will navagate to a different page
               // since we are done.
           }
     
    

    Note close, the above thus gives BOTH persisting of the text box when paging, but ALSO saves all the changes back to the database, and as you can see ,not a lot of code here at all.

    The result is thus this:

    Note close, I enter some text on the first page, go to 2nd page, and then return back - you see the text box maintains its value.

    gvtextbox

    And note how easy the final save button is to send all the changes on any page of data back to the database in one operation.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Lan Huang-MSFT 29,751 Reputation points Microsoft Vendor
    2024-06-17T06:42:25.82+00:00

    Hi @Imoleayo Emmanuel,

    If your database does not have this field, you can add a row manually.

    dt.Columns.Add(new DataColumn("Marks", typeof(string)));

    <asp:TextBox ID="txtMarks" CssClass="form-control" runat="server" Text= '<%# Eval("Marks") %>' ></asp:TextBox>

    Then save the data via ViewState. Below is a complete example.

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
        {
            this.BindGrid();
        }
    }
    private void BindGrid()
    {
        string constr = ConfigurationManager.ConnectionStrings["ConString"].ConnectionString;
        using (SqlConnection con = new SqlConnection(constr))
        {
            string query = "SELECT * FROM Customers";
            using (SqlDataAdapter sda = new SqlDataAdapter(query, con))
            {
                using (DataTable dt = new DataTable())
                {
                    sda.Fill(dt);                                       
                    dt.Columns.Add(new DataColumn("Marks", typeof(string)));                       
                    ViewState["dt"] = dt;
                    GridView1.DataSource = dt;
                    GridView1.DataBind();
                }
            }
        }
    }
    protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
    {
        StoreValuesInViewState();         
        GridView1.PageIndex = e.NewPageIndex;
        LoadValuesFromViewState();
    }
    private void StoreValuesInViewState()
    {
        List<Tuple<int, string>> mylist = this.StoreValues;
        foreach (GridViewRow row in GridView1.Rows)
        {
            if (row.RowType == DataControlRowType.DataRow)
            {
                var itemId = row.DataItemIndex;
                var itemValue = (row.FindControl("txtMarks") as TextBox).Text;
                if (itemValue != null)
                {
                    mylist.Add(new Tuple<int, string>(itemId, itemValue));
                }
                else
                {
                    mylist.Remove(new Tuple<int, string>(itemId, itemValue));
                }
            }
        }
        this.StoreValues = mylist;
    }
    private void LoadValuesFromViewState()
    {
        DataTable dt = (DataTable)ViewState["dt"];
        if (dt.Rows.Count > 0)
        {
            foreach (var item in this.StoreValues)
            {
                dt.Rows[item.Item1]["Marks"] = item.Item2;
            }
            GridView1.DataSource = dt;
            GridView1.DataBind();
        }
    }
    private List<Tuple<int, string>> StoreValues
    {
        get
        {
            if (ViewState["CheckArray"] != null)
            {
                return (List<Tuple<int, string>>)ViewState["CheckArray"];
            }
            return new List<Tuple<int, string>>();
        }
        set
        {
            ViewState["CheckArray"] = value;
        }
    }            
    
     <asp:GridView ID="GridView1" runat="server" Style="text-align: center;" ShowFooter="true" CssClass="table table-hover table-bordered mt-3" EmptyDataText="No record to display!"
         AutoGenerateColumns="False" AllowPaging="True" PageSize="4" DataKeyNames="student_id"
         BorderColor="#DEBA84" BorderStyle="None" BorderWidth="1px" OnPageIndexChanging="GridView1_PageIndexChanging">
         <Columns>
             <asp:BoundField DataField="student_id" HeaderText="Student" ReadOnly="True" />
             <asp:BoundField DataField="full_name" HeaderText="Student" ReadOnly="True" />
             <asp:TemplateField>
                 <HeaderTemplate>
                     <asp:CheckBox ID="chkAll" runat="server" onclick="SelectAll(this);" />
                     Select All
                 </HeaderTemplate>
                 <ItemTemplate>
                     <asp:CheckBox ID="CheckBox1" runat="server" onclick="SelectOne(this)" />
                 </ItemTemplate>
             </asp:TemplateField>
             <asp:TemplateField HeaderText="Marks">
                 <ItemTemplate>
                     <asp:TextBox ID="txtMarks" CssClass="form-control" runat="server" Text='<%# Eval("Marks") %>'></asp:TextBox>
                 </ItemTemplate>
                 <FooterTemplate>
                     <asp:Button ID="Button1" runat="server" Text="Save" CssClass="btn btn-success" />
                     <asp:Button ID="Button2" runat="server" Text="Reset" CssClass="btn btn-danger" />
                 </FooterTemplate>
             </asp:TemplateField>
         </Columns>
         <HeaderStyle BackColor="#5558C9" ForeColor="White" CssClass="bg-danger" />
     </asp:GridView>
    

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.