Selecting, Confirming & Deleting Multiple Checkbox Items In A DataGrid/GridView - Part 2: Maintaining CheckBox State Acr

ASP.NET 2.0 GridView Version

With .NET 2.0 now being official it was only a given for me to convert the code for .NET 2.0's Gridview. Before I present the updated code, I'll now discuss the changes that have occurred in converting the code from a DataGrid to a GridView.

First off, the code-behind model has changed. In the @Page directive, accessing your code behind is accomplish via the CodeFile attribute instead of the Codebehind or Src attribute. Also much of the used to DataGrid properties have changed, as seen below:

.NET 1.1 DataGrid
 
.NET 2.0 GridView
CurrentPageIndex
-->
PageIndex
OnPageIndexChanged
-->
OnPageIndexChanging
OnSortCommand
-->
OnSorting
DataKeyField
-->
DataKeyNames
SelectedItemStyle
-->
SelectedRowStyle
ItemStyle
-->
RowStyle
TemplateColumn
-->
TemplateField
BoundColumn
-->
BoundField
DataGrid.Items
-->
GridView.Rows
DataGridItem
-->
GridViewRow
DataGridItem (ItemIndex)
-->
GridViewRow (RowIndex).Value
DataGridPageChangedEventArgs
-->
GridViewPageEventArgs
DataGridSortCommandEventArgs
-->
GridViewSortEventArgs

The CurrentPageIndex which gets or sets the index of the currently displayed page is now simply PageIndex. Setting up paging and sorting in the Gridview has changed from the OnPageIndexChanged and OnSortCommand methods to OnPageIndexChanging and OnSorting, respectively. The primary key field for the items displayed in the GridView has also changed from DataKeyField to DataKeyNames property.

Setting up row colors on the grid is no more SelectedItemStyle or ItemStyle but rather SelectedRowStyle and RowStyle. I guess this makes more sense since it is a row, anyway. The TemplateColumn class that displays custom content in a data-bound control is now TemplateField, and its partner the BoundColumn which represents a field that is displayed as text in a data-bound control is now called BoundField.

Next, in our code-behind, .NET 2.0 utilizes a new language feature known as a Partial. A Partial class is just that, a partial, incomplete definition of the class or structure. So all that is included in the partial class in only the code needed, such as event handlers and the like. .NET infers the control instances and it derives the events bound from the .aspx file during compilation. Notice in the codebehind I didn't have to declare the GridView or the OutputMsg controls there, as I did in the DataGrid version, neither did I need to include most of the Imports statements that were there before!

Another change in the framework went to the RegisterClientScriptBlock method, this now obsolete method needs to be ClientScript.RegisterClientScriptBlock (Type type, string key, string script) or in our code ClientScript.RegisterClientScriptBlock (Me.GetType(),"clientScript", jsScript.ToString()).

As for implementing custom paging, this also has changed its class wording from DataGridPageChangedEventArgs to GridViewPageEventArgs.

Also, when we retrieve the key value of each record based on DataGrids DataKeyField property we set up the loop like so:

  

For Each dgItem In MyDataGrid.Items

'Retrieve key value of each record based on DataGrids DataKeyField property
ChkBxIndex = MyDataGrid.DataKeys(dgItem.ItemIndex)

Next

Accomplishing the same now needs to use the GridView's DataKeyNames property and the DataGridItem's ItemIndex is now the GridViewRow's RowIndex Value:

  

'Loop through GridView Items
For Each dgItem In MyGridView.Rows

'Retrieve key value of each record based on GridViews DataKeyNames property
ChkBxIndex = MyGridView.DataKeys(dgItem.RowIndex).Value

Next

And aside from changing every instance of the word DataGrid to GridView, as for this article that's about it. So here's the code in its .NET 2.0 entirety, with row color state. Enjoy!

Main Page

<%@ Page Language="VB" Strict="True" Explicit="True" Buffer="True"
    Debug="False" Trace="False" CodeFile="mGridView.aspx.vb"
    Inherits="MultiDeleteDG.WebForm" AutoEventWireup="True"
    EnableSessionState="True" %>
<html>
<head></head>
<body>
<form runat="server">
<h3>Selecting, Confirming & Deleting Multiple Checkbox Items In A GridView (i.e. HotMail & Yahoo) -<br>
Part 2: Maintaining CheckBox State Across Pages with Sorting </h3>
<br />
 Current Page: <%=MyGridView.PageIndex +1%> <br /> 
<ASP:GridView id="MyGridView" runat="server"
Width="700"
BackColor="white"
BorderColor="black"
CellPadding="3"
CellSpacing="0"
Font-Size="9pt"
AutoGenerateColumns="False"
HeaderStyle-BackColor="darkred"
HeaderStyle-ForeColor="white"
AllowPaging="True"
AllowCustomPaging="False"
AllowSorting="True"
OnPageIndexChanging="MyGridView_Page"
OnSorting="MyGridView_Sort"
PageSize="10"
PagerStyle-Mode="NumericPages"
PagerStyle-HorizontalAlign="Right"
DataKeyNames="ID"> <SelectedRowStyle BackColor="#F5EDED" ForeColor="Black" />
<RowStyle BackColor="White" ForeColor="Black" />
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="CheckAll" OnClick="javascript: highlightChkBxRow(this); return select_deselectAll (this.checked, this.id);" runat="server" />
<font face="Webdings" color="white" size="4">a</font> </HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="DeleteThis" OnClick="javascript: highlightChkBxRow(this); return select_deselectAll (this.checked, this.id);" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="StoreID" SortExpression="ID asc" Datafield="ID" runat="server" />
<asp:BoundField HeaderText="Store" SortExpression="Company asc" Datafield="Company" runat="server" />
<asp:BoundField HeaderText="Address" SortExpression="Address asc" Datafield="Address" runat="server" />
<asp:BoundField HeaderText="City" SortExpression="City asc" Datafield="City" runat="server" />
<asp:BoundField HeaderText="State" SortExpression="State asc" Datafield="State" runat="server" />
<asp:BoundField HeaderText="Zip" SortExpression="Zip asc" Datafield="Zip" runat="server" />
</Columns>
</ASP:GridView>
<br />
<asp:Button id="Confirm" onclick="DeleteAllIds" runat="server" Text="Delete Items" />
<asp:Button id="ClearAll" onclick="ClearGridView" runat="server" Text="Clear All" />
<span id="OutputMsg" runat="server" EnableViewState="false" />
</form>
</body>
</html>

The Code-Behind

Imports System.Data
Imports System.Data.SQLClient Namespace MultiDeleteDG Partial Class WebForm Inherits System.Web.UI.Page Protected CheckBox As System.Web.UI.WebControls.CheckBox
Protected objConnect As SqlConnection
Protected myDataAdapter As SqlDataAdapter
Protected myCommand As SqlCommand
Protected DS as Dataset
Protected dgItem As GridViewRow Public deletedIds As String = "" Public ChkdItems As String = "" Public SortField As String = "" Public ChkBxIndex As String = "" Public BxChkd As Boolean = False Public CheckedItems As ArrayList Public Results() As String Sub Page_PreRender (ByVal Sender As Object, ByVal E As EventArgs) Dim nl As String = Environment.NewLine Dim jsScript As New StringBuilder () With jsScript .Append ("<script language=JavaScript>" & nl) .Append ("<!--" & nl & nl) .Append ("function confirmDelete (frm) {" & nl & nl) .Append (" // loop through all elements" & nl & nl) .Append (" for (i=0; i<frm.length; i++) {"& nl & nl) .Append (" // Look for our checkboxes only" & nl) .Append (" if (frm.elements[i].name.indexOf ('DeleteThis') !=-1) {" & nl & nl) .Append (" // If any are checked then confirm alert, otherwise nothing happens" & nl) .Append (" if(frm.elements[i].checked) {" & nl & nl) .Append (" return confirm ('Are you sure you want to delete your selection(s)?')" & nl & nl) .Append (" }" & nl) .Append (" }" & nl) .Append (" }" & nl) .Append (" }" & nl & nl) .Append ("/*Using modified select_deselectAll script function of my original one,") .Append (" from Developerfusion.com forum members - ketcapli & thombo") .Append (" Forum Post - [http://www.developerfusion.co.uk/forums/topic-22773]*/") .Append ("function select_deselectAll (chkVal, idVal) {" & nl) .Append (" var frm = document.forms[0];" & nl) .Append (" if (idVal.indexOf('DeleteThis') != -1 && chkVal == true){" & nl) .Append (" var AllAreSelected = true;" & nl) .Append(" for (i=0; i<frm.length; i++) {" & nl) .Append(" if (frm.elements[i].id.indexOf('DeleteThis') != -1 && frm.elements[i].checked == false){ " & nl) .Append (" AllAreSelected = false;" & nl) .Append (" break;" & nl) .Append (" } " & nl) .Append (" } " & nl) .Append (" if(AllAreSelected == true){" & nl) .Append (" for (j=0; j<frm.length; j++) {" & nl) .Append (" if (frm.elements[j].id.indexOf ('CheckAll') != -1) {" & nl) .Append (" frm.elements[j].checked = true;" & nl) .Append (" break;" & nl) .Append (" }" & nl) .Append (" }" & nl) .Append (" }" & nl) .Append (" } else {" & nl) .Append (" for (i=0; i<frm.length; i++) {" & nl) .Append (" if (idVal.indexOf ('CheckAll') != -1) {" & nl) .Append (" if(chkVal == true) {" & nl) .Append (" frm.elements[i].checked = true; " & nl) .Append (" } else {" & nl) .Append (" frm.elements[i].checked = false; " & nl) .Append (" }" & nl) .Append (" } else if (idVal.indexOf('DeleteThis') != -1 && frm.elements[i].checked == false) {" & nl) .Append (" for (j=0; j<frm.length; j++) {" & nl) .Append (" if (frm.elements[j].id.indexOf ('CheckAll') != -1) { " & nl) .Append (" frm.elements[j].checked = false;" & nl) .Append (" break; " & nl) .Append (" } " & nl) .Append (" } " & nl) .Append (" } " & nl) .Append (" } " & nl) .Append (" } " & nl) .Append (" } " & nl & nl) .Append ("function highlightChkBxRow(chkbx) {" & nl & nl) .Append (" if (chkbx.id.indexOf ('DeleteThis') != -1) {" & nl & nl) .Append (" if (chkbx.checked) {" & nl & nl) .Append (" chkbx.parentElement.parentElement.style.backgroundColor='#F5EDED';" & nl) .Append (" chkbx.parentElement.parentElement.style.color='#000000';" & nl) .Append (" } else {" & nl & nl) .Append (" chkbx.parentElement.parentElement.style.backgroundColor='#FFFFFF';" & nl) .Append (" chkbx.parentElement.parentElement.style.color='#000000';" & nl & nl) .Append (" }" & nl & nl) .Append (" } else {" & nl & nl) .Append (" var frm = document.forms[0];" & nl & nl) .Append (" for (h = 0; h < frm.length; h++) {" & nl & nl) .Append (" if (frm.elements[h].id.indexOf ('DeleteThis') != -1) {" & nl & nl) .Append (" if (chkbx.id.indexOf ('CheckAll') != -1 && chkbx.checked) {" & nl & nl) .Append (" frm.elements[h].parentElement.parentElement.style.backgroundColor='#F5EDED';" & nl) .Append (" frm.elements[h].parentElement.parentElement.style.color='#000000';" & nl & nl) .Append (" } else {" & nl & nl) .Append (" frm.elements[h].parentElement.parentElement.style.backgroundColor='#FFFFFF';" & nl) .Append (" frm.elements[h].parentElement.parentElement.style.color='#000000';" & nl & nl) .Append (" }" & nl) .Append (" }" & nl) .Append (" } //loop" & nl) .Append (" }" & nl) .Append ("}" & nl) .Append ("//--> " & nl & nl) .Append ("</scr" & "ipt>") End With ClientScript.RegisterClientScriptBlock (Me.GetType(),"clientScript",_ jsScript.ToString()) jsScript = Nothing Dim button As WebControl = CType(Page.FindControl("Confirm"), WebControl) button.Attributes.Add("onclick", "return confirmDelete (this.form);") End Sub Sub Page_Load (ByVal Sender As Object, ByVal E As EventArgs) objConnect = New SqlConnection("server=(local);database=Northwind;uid=sa;pwd=;") If Not IsPostBack Then Session.Clear() 'Set up default column sorting If IsNothing(Session ("SortOrder")) Then BindData ("ID asc") Else BindData (Session ("SortOrder")) End If End If End Sub Sub MyGridView_Page (sender As Object, e As GridViewPageEventArgs) 'Get CheckBoxValues before paging occurs GetCheckBoxValues() MyGridView.PageIndex = e.NewPageIndex BindData(Session ("SortOrder")) 'Populate current GridView page with the current page items from Session after databind RePopulateCheckBoxes () End Sub Sub GetCheckBoxValues() 'As paging occurs store checkbox values CheckedItems = New ArrayList 'Loop through GridView Items For Each dgItem In MyGridView.Rows 'Retrieve key value of each record based on GridViews DataKeyNames property ChkBxIndex = MyGridView.DataKeys(dgItem.RowIndex).Value CheckBox = dgItem.FindControl("DeleteThis") 'Add ArrayList to Session if it doesnt exist If Not IsNothing(Session ("CheckedItems")) Then CheckedItems = Session ("CheckedItems") End If If CheckBox.Checked Then BxChkd = True 'Add to Session if it doesnt already exist If Not CheckedItems.Contains(ChkBxIndex) Then CheckedItems.Add(ChkBxIndex.ToString()) End If Else 'Remove value from Session when unchecked CheckedItems.Remove(ChkBxIndex.ToString()) End If Next 'Update Session with the list of checked items Session ("CheckedItems") = CheckedItems End Sub Sub BindData (SortField As String) 'Setup Session Cache for different users Dim Source As DataView = Session ("dgCache") If (IsNothing (Source)) Then Dim sqlQuery As String = "Select OrderId As Id, ShipName As Company," _
& " ShipAddress As Address, ShipCity As City, _
ShipCountry As State, ShipPostalCode As Zip from Orders" myDataAdapter = New SqlDataAdapter(sqlQuery, objConnect) DS = New Dataset() myDataAdapter.Fill(DS, "MyGridView") 'Assign sort expression to Session Session ("SortOrder") = SortField 'Setup DataView for Sorting Source = DS.Tables(0).DefaultView 'Insert DataView into Session Session ("dgCache") = Source End If Source.Sort = SortField MyGridView.DataSource = Source MyGridView.DataBind () 'Close connection objConnect.Close End Sub Sub RePopulateCheckBoxes () CheckedItems = New ArrayList CheckedItems = Session ("CheckedItems") If Not IsNothing(CheckedItems) Then 'Loop through GridView Items For Each dgItem in MyGridView.Rows ChkBxIndex = MyGridView.DataKeys(dgItem.RowIndex).Value 'Repopulate GridView with items found in Session If CheckedItems.Contains(ChkBxIndex) Then CheckBox = CType(dgItem.FindControl("DeleteThis"), CheckBox) CheckBox.Checked = True dgItem.ForeColor = MyGridView.SelectedRowStyle.ForeColor dgItem.BackColor = MyGridView.SelectedRowStyle.BackColor Else dgItem.ForeColor = MyGridView.RowStyle.ForeColor dgItem.BackColor = MyGridView.RowStyle.BackColor End If Next End If 'Copy ArrayList to a new array Results = CheckedItems.ToArray(GetType(String)) 'Concatenate ArrayList with comma to properly send for deletion deletedIds = String.Join(",", Results) End Sub Sub DeleteAllIds (ByVal sender As Object, ByVal e As EventArgs) 'Regrab values in case the deletion occurs on the given page and any checkboxes were unchecked
'on the current page without any postback to correct the values in Session GetCheckBoxValues () If BxChkd = True Then RePopulateCheckBoxes () 'Delete the rows of data containing the checkbox values Dim deleteSQL As String = "DELETE from Orders WHERE OrderId IN (" + deletedIds + ");" myCommand = New SqlCommand (deleteSQL, objConnect) With myCommand .Connection.Open() .ExecuteNonQuery() End With 'Close connection objConnect.Close() OutputMsg.InnerHtml += "<font size=4><b>Store information has been deleted.</b></font>" OutputMsg.Style("color") = "green" 'Clear all Session values Session.Clear() 'Reset GridView to top MyGridView.PageIndex = 0 BindData (Session ("SortOrder")) End If End Sub Function SortOrder (Field As String) As String Dim so As String = Session ("SortOrder") If Field = so Then SortOrder = Replace (Field,"asc","desc") ElseIf Field <> so Then SortOrder = Replace (Field,"desc","asc") Else SortOrder = Replace (Field,"asc","desc") End If 'Maintain persistent sort order Session ("SortOrder") = SortOrder End Function Sub MyGridView_Sort (Sender As Object, E As GridViewSortEventArgs) 'To retain checkbox on sorting GetCheckBoxValues () MyGridView.PageIndex = 0 'To sort from top BindData (SortOrder (E.SortExpression).ToString()) 'Rebind our GridView 'To retain checkbox on sorting RePopulateCheckBoxes () End Sub Sub ClearGridView (ByVal sender As Object, ByVal e As EventArgs) 'Clear All Session Values Session.Clear() 'Reset GridView to top MyGridView.PageIndex = 0 BindData ("ID asc") 'Rebind our GridView End Sub End Class End Namespace

You might also like...

Comments

About the author

Dimitrios Markatos

Dimitrios Markatos United States

Dimitrios, or Jimmy as his friends call him, is a .NET developer/architect who specializes in Microsoft Technologies for creating high-performance and scalable data-driven enterprise Web and des...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.” - Alan Kay