Pages

Thursday, May 24, 2012

Preserving state of Checkboxes while paging in ASP.Net GridView Control


n my previous article Using JavaScript with ASP.Net GridView Control, I explained how to check all checkboxes using JavaScript and also how to change the row color when the checkbox is checked.
But many people asked me how to preserve the state of checkboxes while pagination since when they visited some other page and returned back, the selections was gone. Hence I decided to write on the same and here is what I came up with.
Here I will explain how to preserve selections on all pages while paginating.
To start with I have a GridView as below
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns = "false" Font-Names = "Arial"
Font-Size = "11pt" AlternatingRowStyle-BackColor = "#C2D69B" 
HeaderStyle-BackColor = "green" AllowPaging ="true"  
OnPageIndexChanging = "OnPaging" OnRowDataBound = "RowDataBound"  PageSize="10">
<Columns>
<asp:TemplateField>
    <HeaderTemplate>
        <asp:CheckBox ID="chkAll" runat="server"
            onclick = "checkAll(this);" />
    </HeaderTemplate>
    <ItemTemplate>
        <asp:CheckBox ID="CheckBox1" runat="server"
            onclick = "Check_Click(this)"/>
    </ItemTemplate>
</asp:TemplateField>
<asp:BoundField ItemStyle-Width = "150px"
    DataField = "CustomerID" HeaderText = "CustomerID" />
<asp:BoundField ItemStyle-Width = "150px"
    DataField = "City" HeaderText = "City"/>
<asp:BoundField ItemStyle-Width = "150px"
    DataField = "Country" HeaderText = "Country"/>
<asp:BoundField ItemStyle-Width = "150px"
    DataField = "PostalCode" HeaderText = "PostalCode"/>
</Columns>
</asp:GridView>

Note you will notice I am calling JavaScript functions on the checkbox click these are the same which I discussed in my previous article.
The GridView is pulling Data from the customers table in the NorthWind Database.

Namespaces
You will need to import the following namespace since I am using ArrayList to store the checked checkboxes
  
C#
using System.Collections;

VB.Net
Imports System.Collections

The following code checks if the ViewState has ArrayList Stored in it if yes it gets it from the ViewState else creates a new ArrayList which will store the selected checkboxes.
  C#
ArrayList CheckBoxArray;
if (ViewState["CheckBoxArray"] != null)
{
    CheckBoxArray = (ArrayList)ViewState["CheckBoxArray"];
}
else
{
    CheckBoxArray = new ArrayList();
}

VB.Net
Dim CheckBoxArray As ArrayList
If ViewState("CheckBoxArray"IsNot Nothing Then
   CheckBoxArray = DirectCast(ViewState("CheckBoxArray"), ArrayList)
Else
   CheckBoxArray = New ArrayList()
End If

The next code snippet gets the reference of the header row check all checkbox and checks if the checkbox is checked or unchecked
If the checkbox is checked it adds its reference in the ArrayList in the format chkAll-0 where 0 is the page index of the GridView page.
If the checkbox is unchecked it checks whether its reference is present in the ArrayList or not if the reference is present it removes the reference from the ArrayList and sets the flag CheckAllWasChecked which is useful in the next snippet.
      
C#
    int CheckBoxIndex;
    bool CheckAllWasChecked=false;
    CheckBox chkAll =
     (CheckBox)GridView1.HeaderRow.Cells[0].FindControl("chkAll");
    string checkAllIndex = "chkAll-" + GridView1.PageIndex;
    if (chkAll.Checked)
    {
        if (CheckBoxArray.IndexOf(checkAllIndex) == -1)
        {
            CheckBoxArray.Add(checkAllIndex);
        }
    }
    else
    {
        if (CheckBoxArray.IndexOf(checkAllIndex) != -1)
        {
            CheckBoxArray.Remove(checkAllIndex);
            CheckAllWasChecked = true;
        }
    }

VB.Net
Dim CheckBoxIndex As Integer
Dim CheckAllWasChecked As Boolean = False
Dim chkAll As CheckBox = _
DirectCast(GridView1.HeaderRow.Cells(0).FindControl("chkAll"), CheckBox)

Dim checkAllIndex As String = "chkAll-" & GridView1.PageIndex

If chkAll.Checked Then
   If CheckBoxArray.IndexOf(checkAllIndex) = -1 Then
      CheckBoxArray.Add(checkAllIndex)
   End If
Else
   If CheckBoxArray.IndexOf(checkAllIndex) <> -1 Then
      CheckBoxArray.Remove(checkAllIndex)
      CheckAllWasChecked = True
   End If
End If

The next snippet loops through the GridView rows and checks if the checkbox for that corresponding row is checked. If the checkbox is checked its position is calculated using the following formula
CheckBoxIndex = GridView1.PageSize * GridView1.PageIndex + (RowIndex + 1)

The above formula gives the checkbox. RowIndex and PageIndex are zero based indexes i.e the first row or first page starts from 0.
If the checkbox is checked its CheckBoxIndex added to the ArrayList else if it is already present and the checkbox is not checked it is removed.

C#
for (int i = 0; i < GridView1.Rows.Count; i++)
{
    if (GridView1.Rows[i].RowType == DataControlRowType.DataRow)
    {
        CheckBox chk =
         (CheckBox)GridView1.Rows[i].Cells[0].FindControl("CheckBox1");
        CheckBoxIndex = GridView1.PageSize * GridView1.PageIndex + (i + 1);
        if (chk.Checked)
        {
            if (CheckBoxArray.IndexOf(CheckBoxIndex) == -1
                && !CheckAllWasChecked)
            {
                CheckBoxArray.Add(CheckBoxIndex);
            }
        }
        else
        {
            if (CheckBoxArray.IndexOf(CheckBoxIndex) != -1
                || CheckAllWasChecked)
            {
                CheckBoxArray.Remove(CheckBoxIndex);
            }
        }
    }
}

VB.Net
For i As Integer = 0 To GridView1.Rows.Count - 1
   If GridView1.Rows(i).RowType = DataControlRowType.DataRow Then
     Dim chk As CheckBox = _
     DirectCast(GridView1.Rows(i).Cells(0) _
     .FindControl("CheckBox1"), CheckBox)
     CheckBoxIndex = GridView1.PageSize * GridView1.PageIndex + (i + 1)
     If chk.Checked Then
       If CheckBoxArray.IndexOf(CheckBoxIndex) = -1 And _
       Not CheckAllWasChecked Then
          CheckBoxArray.Add(CheckBoxIndex)
       End If
       Else
         If CheckBoxArray.IndexOf(CheckBoxIndex) <> -1 Or _
          CheckAllWasChecked Then
          CheckBoxArray.Remove(CheckBoxIndex)
       End If
     End If
   End If
Next

 
The complete snippet is given below.
  
C#
if (IsPostBack)
{
    int CheckBoxIndex;
    bool CheckAllWasChecked=false;
    CheckBox chkAll =
     (CheckBox)GridView1.HeaderRow.Cells[0].FindControl("chkAll");
    string checkAllIndex = "chkAll-" + GridView1.PageIndex;
    if (chkAll.Checked)
    {
        if (CheckBoxArray.IndexOf(checkAllIndex) == -1)
        {
            CheckBoxArray.Add(checkAllIndex);
        }
    }
    else
    {
        if (CheckBoxArray.IndexOf(checkAllIndex) != -1)
        {
            CheckBoxArray.Remove(checkAllIndex);
            CheckAllWasChecked = true;
        }
    }
    for (int i = 0; i < GridView1.Rows.Count; i++)
    {
        if (GridView1.Rows[i].RowType == DataControlRowType.DataRow)
        {
          CheckBox chk =
          (CheckBox)GridView1.Rows[i].Cells[0].FindControl("CheckBox1");
           CheckBoxIndex=GridView1.PageSize*GridView1.PageIndex + (i + 1);
          if (chk.Checked)
          {
                if (CheckBoxArray.IndexOf(CheckBoxIndex) == -1
                    && !CheckAllWasChecked)
                {
                    CheckBoxArray.Add(CheckBoxIndex);
                }
          }
          else
          {
                if (CheckBoxArray.IndexOf(CheckBoxIndex) != -1
                    || CheckAllWasChecked)
                {
                    CheckBoxArray.Remove(CheckBoxIndex);
                }
          }
        }
    }
}

    
VB.Net
If IsPostBack Then
  Dim CheckBoxIndex As Integer
  Dim CheckAllWasChecked As Boolean = False
  Dim chkAll As CheckBox = _
   DirectCast(GridView1.HeaderRow.Cells(0).FindControl("chkAll"), CheckBox)

  Dim checkAllIndex As String = "chkAll-" & GridView1.PageIndex
  If chkAll.Checked Then
     If CheckBoxArray.IndexOf(checkAllIndex) = -1 Then
       CheckBoxArray.Add(checkAllIndex)
     End If
  Else
     If CheckBoxArray.IndexOf(checkAllIndex) <> -1 Then
       CheckBoxArray.Remove(checkAllIndex)
       CheckAllWasChecked = True
     End If
  End If
  For i As Integer = 0 To GridView1.Rows.Count - 1
   If GridView1.Rows(i).RowType = DataControlRowType.DataRow Then
     Dim chk As CheckBox = _
      DirectCast(GridView1.Rows(i).Cells(0) _
      .FindControl("CheckBox1"), CheckBox)
     CheckBoxIndex = GridView1.PageSize * GridView1.PageIndex + (i + 1)
     If chk.Checked Then
       If CheckBoxArray.IndexOf(CheckBoxIndex) = -1 And _
        Not CheckAllWasChecked Then
          CheckBoxArray.Add(CheckBoxIndex)
     End If
     Else
      If CheckBoxArray.IndexOf(CheckBoxIndex) <> -1 Or _
        CheckAllWasChecked Then
         CheckBoxArray.Remove(CheckBoxIndex)
       End If
     End If
   End If
  Next
End If

Once this is done the ArrayList is saved to the ViewState.
C#
ViewState["CheckBoxArray"] = CheckBoxArray;

VB.Net
ViewState("CheckBoxArray") = CheckBoxArray
  

Now in the GridView Paging Event you will need to recheck the checkboxes that are present in the ArrayList that we saved in the ViewState. If the Check All checkbox is checked for that page index it will check all the checkboxes. While checking through the checkboxes it also applies the background color to all checkboxes that are checked.
C#
ArrayList CheckBoxArray = (ArrayList)ViewState["CheckBoxArray"];
string checkAllIndex = "chkAll-" + GridView1.PageIndex;

if (CheckBoxArray.IndexOf(checkAllIndex) != -1)
{
    CheckBox chkAll =
     (CheckBox)GridView1.HeaderRow.Cells[0].FindControl("chkAll");
    chkAll.Checked = true;
}
for (int i = 0; i < GridView1.Rows.Count; i++)
{
if (GridView1.Rows[i].RowType == DataControlRowType.DataRow)
{
    if (CheckBoxArray.IndexOf(checkAllIndex) != -1)
    {
        CheckBox chk =
         (CheckBox)GridView1.Rows[i].Cells[0].FindControl("CheckBox1");
        chk.Checked = true;
        GridView1.Rows[i].Attributes.Add("style","background-color:aqua");     
    }
    else
    {
      int CheckBoxIndex =GridView1.PageSize*(GridView1.PageIndex)+(i + 1);
      if (CheckBoxArray.IndexOf(CheckBoxIndex) != -1)
      {
         CheckBox chk =
         (CheckBox)GridView1.Rows[i].Cells[0].FindControl("CheckBox1");
        chk.Checked = true;
        GridView1.Rows[i].Attributes.Add("style""background-color:aqua");
      }
    }
}
}

  
VB.Net
For i As Integer = 0 To GridView1.Rows.Count - 1
   If GridView1.Rows(i).RowType = DataControlRowType.DataRow Then
     If CheckBoxArray.IndexOf(checkAllIndex) <> -1 Then
       Dim chk As CheckBox = _
        DirectCast(GridView1.Rows(i).Cells(0) _
        .FindControl("CheckBox1"), CheckBox)
       chk.Checked = True
       GridView1.Rows(i).Attributes.Add("style""background-color:aqua")
     Else
       Dim CheckBoxIndex As Integer
           = GridView1.PageSize*(GridView1.PageIndex)+(i+1)
       If CheckBoxArray.IndexOf(CheckBoxIndex) <> -1 Then
        Dim chk As CheckBox = _
         DirectCast(GridView1.Rows(i).Cells(0) _
         .FindControl("CheckBox1"), CheckBox)
        chk.Checked = True
        GridView1.Rows(i).Attributes.Add("style""background-color:aqua")
       End If
     End If
   End If
Next


GridView that preserves the checked checkbox while paging

This completes this article. You view the live demo here.
The source code is available in C# and VB.Net through the link below.
GridViewCheckBoxes.zip (6.69 kb)

No comments:

Post a Comment