I'm going to suggest you simply persist the data table.
The advantages are many with this approach.
First up, when you are finally done, you can save all changes with one update command.
And, you can cancel (not save) the changes if you wish.
It not clear if you check all is to check all rows (in every page), or check all rows in the current page of data. I'll assume you want all rows.
One bit of information is how many rows in total do you have?
So, in my case we have some hotels, and your check box, and some text
So, our markup:
<asp:GridView ID="GVHotels" runat="server" class="table"
AutoGenerateColumns="false" DataKeyNames="ID"
CssClass="table table-hover borderhide"
width="40%"
AllowPaging="True"
OnPageIndexChanging="GVHotels_PageIndexChanging"
>
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel" />
<asp:TemplateField HeaderText="Feedback">
<ItemTemplate>
<asp:TextBox ID="txtCustFeedback" runat="server"
Text='<%# Eval("CustFeedback")%>'
style="width:100%" >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<HeaderTemplate >
<div style="text-align:center">
Check All <br />
<asp:CheckBox ID="chkAll" runat="server"
OnCheckedChanged="chkAll_CheckedChanged"
AutoPostBack="true" />
</div>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="ChkBox1" runat="server"
Checked='<%# Eval("Checked") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle CssClass="GridPager" VerticalAlign="Bottom" BorderWidth="2" />
</asp:GridView>
<br />
<asp:Button ID="cmdSave" runat="server" Text="Save Edits"
CssClass="btn" OnClick="cmdSave_Click" />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel"
CssClass="btn"
style="margin-left:20px"
OnClick="cmdCancel_Click"
/>
And now our code to load the GridView:
Note close how we pull the data into a data table, and then persist that table into session.
(this is why I asked how many rows). For say up to 200 rows or so, then this works without delay. If you have 1000's of rows, then we will require a different approach.
DataTable rstData = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadGrid();
Session["rstData"] = rstData;
}
else
rstData = Session["rstData"] as DataTable;
}
void LoadGrid()
{
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
string strSQL = "SELECT * FROM tblHotels ORDER BY HotelName";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
{
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
GVHotels.DataSource = rstData;
GVHotels.DataBind();
}
}
}
So, how this works is that before we page, we have a routine to take the current page of data, and send it back to the persisted table - not back to the live database.
First, our check all button - as noted, I assume all rows on all pages.
Hence, this code:
protected void chkAll_CheckedChanged(object sender, EventArgs e)
{
foreach (DataRow dRow in rstData.Rows)
dRow["Checked"] = true;
GVHotels.DataSource = rstData;
GVHotels.DataBind();
}
Note how I operate against the data table. So, the approch here was to think in terms of data - not really the UI.
And our data pager code is this:
protected void GVHotels_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
// send data to table before page
GridToTable();
GVHotels.PageIndex = e.NewPageIndex;
GVHotels.DataSource = rstData;
GVHotels.DataBind();
}
So, all we do is "always" send the grid back to the persisted table with this code:
void GridToTable()
{
// send grid rows back to table.
foreach (GridViewRow rRow in GVHotels.Rows)
{
int RecordPtr = rRow.DataItemIndex;
DataRow OneDataRow;
OneDataRow = rstData.Rows[RecordPtr];
OneDataRow["CustFeedBack"] = ((TextBox)rRow.FindControl("txtCustFeedBack")).Text;
OneDataRow["Checked"] = ((CheckBox)rRow.FindControl("ChkBox1")).Checked;
}
}
So, that's about it. Our cancel button at the bottom can simply navagate back to some other page.
Our save button will first save (send) the changes back to the database.
That code is this:
protected void cmdSave_Click(object sender, EventArgs e)
{
// send grid back to rstData
GridToTable();
// now send table back to database with updates
string strSQL = "SELECT * from tblHotels";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);
daupdate.Update(rstData);
}
}
I should point out that the datatable in .net is rather smart, and with above, if you only modify 2 rows, then it will only generate 2 rows of update code back to sql server.
Of course, after the above save, I would assume you then navigate to another page.
I would suggest that the session that persisted the table be removed, but as above shows, the code is not all that complex. Note how the GridView row has 2 types of indexing into the data.
RowIndex = row index of current page.
DataItemIndex = index to the data source used for the GridView. So, this feature is quite much the Rossetta stone that makes all of this work.