Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

GridView CheckBox Selection with a Twist

4.30/5 (9 votes)
27 Jan 2007CPOL4 min read 1   1.8K  
How to implement GridView Checkbox selection

Introduction

In one of my articles, I discussed how to select checkboxes inside the GridView control. You can view the article here. This is an extension to that article in which, I will discuss some additional features. These features include using regular expression to limit the checkbox selection on a particular GridView and de-selecting the parent checkbox when all child checkboxes are un-checked.

Creating the GridView Control

The first task is to create a simple GridView control using template fields. I strongly recommend using template fields instead of bound fields for the following reasons:

  • Template fields allow embedding the ASP.NET controls.
  • You don’t have to reorganize the appearance of the GridView after a new template field is added. This is because template field does not depend on the index number like the bound fields.
  • Template fields allow access to ASP.NET controls even if the fields are not visible.

Finally, here is the code for the GridView control.

ASP.NET
<asp:GridView ID="GridView1" runat="server" 
        AutoGenerateColumns="false">
    <Columns>
    <asp:TemplateField>
    <HeaderTemplate>
    <input type="checkbox" id="chkAll" name="chkAll" 
        onclick="Check(this)" />
    </HeaderTemplate>

    <ItemTemplate>
    <asp:CheckBox ID="chkSelect" runat="server" />
    </ItemTemplate>

    </asp:TemplateField>
    <asp:TemplateField>
    <ItemTemplate>

    <asp:Label ID="lblCategoryName" runat="server" 
        Text = '<%# Eval("CategoryName") %>' />
    </ItemTemplate>
    </asp:TemplateField>

    </Columns>
</asp:GridView>

The HeaderTemplate contains the HTML checkbox and serves as the parent checkbox. The ItemTemplate contains the ASP.NET checkboxes.

Populating the GridView Control

I have used DataSet to populate the GridView control, but you can use any type of container object to complete the task.

C#
private void BindData()
{
    string connectionString = "Server=localhost;
            Database=Northwind;Trusted_Connection=true";

    SqlConnection myConnection = new SqlConnection(
                                        connectionString);

    SqlDataAdapter ad = new SqlDataAdapter("SELECT 
            CategoryID, CategoryName FROM Categories", 
            myConnection);

    DataSet ds = new DataSet();

    ad.Fill(ds);

    GridView1.DataSource = ds;

    GridView1.DataBind();
}

Now, if you run the application, you will see the GridView displayed on the page.

Image 1

NOTE: I have added styles to make the GridView look pretty!

Selecting and Deselecting CheckBoxes

At this point, your GridView control is displayed on the page and we need to implement the functionality to select and deselect all the child checkboxes when the parent checkbox is checked.

If you take a look at the GridView HTML code, you will notice that the parent checkbox (chkAll) fires the Check function when clicked. Let’s see the Check function implementation.

JavaScript
function Check(parentChk)
{
    var elements =  document.getElementsByTagName("INPUT");

    for(i=0; i<elements.length;i++)
    {
        if(parentChk.checked == true)
        { 
            if( IsCheckBox(elements[i]) && 
                IsMatch(elements[i].id))
            {
                elements[i].checked = true;
            }        
        }
        else
        {
            elements[i].checked = false;
        }      
    }   
}

The Check function is responsible for selecting and deselecting all the child checkboxes. First, I retrieve all the objects whose tag name is “INPUT”. Inside the loop, I check whether the parent checkbox is checked or not. If it is checked, then I find the correct checkbox element and mark it checked. The functions, IsCheckBox and IsMatch are responsible for finding the child checkboxes.

Before I explain the working of the two methods, let’s see your little regular expression which separates the GridView checkboxes from other checkboxes on the page and even from the checkboxes inside other GridView controls.

Here is our little regular expression:

C#
var pattern = '^GridView1';

The expression says that select every string whose name starts with “GridView1”. You might be wondering how this expression can help to find the correct child checkboxes. In order to understand it, let’s take a look at the HTML code that is generated when the GridView is rendered on the page.

Image 2

You can see that the checkboxes inside the GridView control are assigned unique ids. The first part contains the id of the GridView which, in this case is “GridView1”. The middle part contains the row number and the final part contains the original id of the checkbox as set by the developer.

Now, let’s take a look at the IsMatch function which, takes the id of the control as a parameter and returns true if matched, else returns false.

JavaScript
function IsMatch(id)
{
    var regularExpresssion = new RegExp(pattern);

    if(id.match(regularExpresssion)) return true;
    else return false;
}

The IsMatch function is not enough. Huh! The reason is that we are not checking for the type of the element. The element which has the “INPUT” tag can be a checkbox, radio, textbox, button, etc. For that reason, there is another small method called IsCheckBox which simply checks for type of the element.

JavaScript
function IsCheckBox(chk)
{
    if(chk.type == 'checkbox') return true;
    else return false;
}

All the code that we have discussed will allow you to check and uncheck all the checkboxes based on the parent checkbox. The code also checks for the particular GridView so, that other checkboxes on the page are not affected.

Attaching Listeners to the Child CheckBoxes

Listeners allow you to catch events generated by the controls and take action on those events by firing a function. Scott Andrew wrote an excellent piece of code that attaches the listeners to the object. The code is browser compatible (I have tested on Mozilla and IE).

JavaScript
function AddEvent(obj, evType, fn)
{
    if (obj.addEventListener)
    {
        obj.addEventListener(evType, fn, true);
        return true;
    }
    else if (obj.attachEvent)
    {
        var r = obj.attachEvent("on"+evType, fn);
        return r;
    }
    else
    {
        return false;
    }   
}

I won’t be explaining the insights of this function but if you are really interested, then you should check out this link. The AddEvent function is fired from the function AttachListener.

JavaScript
function AttachListener()
{
    var elements =  document.getElementsByTagName("INPUT");

    for(i=0; i < elements.length; i++)
    {      
        if( IsCheckBox(elements[i]) && 
            IsMatch(elements[i].id))
        {
            AddEvent(elements[i],'click',CheckChild);
        }
    }   
}

In the code above, I am registering the ‘click’ event of the checkboxes with a listener. Any time the click event is fired from the child checkboxes, the CheckChild function is fired. The AttachListener is fired on the following event:

HTML
<body onload="AttachListener()">

The CheckChild Function

The CheckChild function keeps track of how many child checkboxes are checked. When all the child checkboxes are checked, then the parent checkbox should also be checked.

JavaScript
function CheckChild(e)
{
    var evt = e || window.event;
    var obj = evt.target || evt.srcElement

    if(obj.checked)
    {
        if(counter < GetChildCheckBoxCount())
            { counter++; }       
    }   
    else
    {
       if(counter > 0) { counter--; }   
    }

    if(counter == GetChildCheckBoxCount())
    { document.getElementById("chkAll").checked = true; }
    else if(counter < GetChildCheckBoxCount()) 
            { document.getElementById("chkAll")
              .checked = false; 
    }   
}

The total of checked checkboxes is stored in the global variable called “counter”. Once, the counter reaches the total child checkboxes, then the parent checkbox is checked. With the global variable counter in-place, there is also a small change in the Check function. Take a look at the final Check function.

JavaScript
function Check(parentChk)
{
    var elements =  document.getElementsByTagName("INPUT");

    for(i=0; i<elements.length;i++)
    {
        if(parentChk.checked == true)
        { 
            if( IsCheckBox(elements[i]) && 
                IsMatch(elements[i].id))
            {
                elements[i].checked = true;
            }        
        }
        else
        {
            elements[i].checked = false;
            // reset the counter
            counter = 0;
        }      
    }
    if(parentChk.checked == true)
    {
        counter = GetChildCheckBoxCount();
    }  
}

Few, extra lines are added to reset the counter. The method GetChildCheckBoxCount() is pretty simple and you can view the source in the download.

Conclusion

I hope you liked the article, happy coding!

History

  • 27th January, 2007: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)