Master CheckBox in GridView header

{23 Comments}

{ Updated for ASP.Net 4.0 on 6.Aug.2012 }
Introduction

Its common to show records from database table with GridView in ASP.Net. Once we disply records, we need to do some actions which will be applied to one, many or all records,lets say “Bulk Actions”. So we need to have a way to select records ( one or many or all ), and perform required action.

For example I am going to show all products from NorthWind database and then I will select some of them to delete or modify. The best solution in this case would be nice to have a column with CheckBox in the GridView. But if I will have 100 records in my table and I want to select all, it would be a big work for me to go and select them one by one. So lets have a master CheckBox in the header of CheckBox column.

So I am going to add a CheckBox column, with a CheckBox in header, And then use jQuery to check/un-check all of them

Setting jQuery in an ASP.NET web site

Its quite easy to set jQuery to use in ASP.NET. Put the latest Scripts in your project and reference them on your page or Master page. Doing that in Master Page is a very good option. Check the attached code for it. I am going to use ScriptManager to reference jQuery script file.

Lets Implement It!

First of all I need to show all the products in an GridView. That will be very simple. And I coded this -

[html]

<asp:SqlDataSource ID="mySqlDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT [ProductID], [ProductName], [SupplierID], [CategoryID], [UnitPrice], [UnitsInStock],
[UnitsOnOrder], [CategoryName] FROM [Alphabetical list of products]"></asp:SqlDataSource>
<asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="False" DataSourceID="mySqlDataSource"
DataKeyNames="ProductID">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<input id="masterCheck" type="checkbox" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkSelect" ClientIDMode="Auto" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="CategoryName" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
</Columns>
</asp:GridView>
[/html]

I am using SQLDataSource and a GridView to Display Records.
Note that first column is a template column. In header of this column, I am using a normal HTML checkbox with an id “masterCheck”. And then an asp.net CheckBox in itemplate, with an id “chkSelect” .

[html]

<asp:TemplateField>
<HeaderTemplate>
<input id="masterCheck" type="checkbox" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox runat="server" ID="chkSelect" ClientIDMode="Static" />
</ItemTemplate>
</asp:TemplateField>
[/html]

So outcome will be a GridView with product list.

Execute the page and check its HTML source. You will notice that id of master checkbox is same as what we have given i.e “masterCheck”. But the checkboxes in ItemTemplate will have ids like “ctl00_myBody_myGridView_ctl02_chkSelect”. This is ASP.NET name mangling. It is going to decide how I will use jQuery selector expression.

Now we need to write jQuery code, which will Check/Un-Check all checkboxes. So I will following things
1. Find my master checkbox in gridview.
2. Attach handler for click event of master checkbox.
3. I will find all the checkboxes with id ending with “chkSelect” and assign checked state of master checkbox to them.

So this will be jQuery code produced -

[html]

<script language="javascript" type="text/javascript">
$(document).ready(function() {
$("#masterCheck").click(function() {
$("[id$=chkSelect]").attr(‘checked’, $(‘#masterCheck’).is(‘:checked’));
});
});
</script>

[/html]

Here is an explanation of line by line
1. Write code in document.ready event
2. Get the master checkbox and attach a function to its “click” event.
3. Find all checkboxes whoose ids are ending with “chkSelect”. I need to do this because of ASP.NET name mangling.
4. Assign checked state of master checkbox to selected checkbox.

And thats all. Once you have selected all or none, you press any button like edit, delete or hide to perform a postback. In your code behind you can loop through rows of GridView and get the values of checkbox. For example I am going to prepare a string of IDs separated by commas and display them. Check the event handler code for show button -

[csharp]

protected void btnShow_Click(object sender, EventArgs e)
{
StringBuilder IDs = new StringBuilder();
int count = gvProducts.Rows.Count;

for (int i = 0; i < count; i++)
{
CheckBox chkSelect = gvProducts.Rows[i].FindControl("chkSelect") as CheckBox;
if (chkSelect.Checked)
{
IDs.Append(gvProducts.DataKeys[i].Value);
IDs.Append(",");
}
}
}

[/csharp]

Conclusion

So I have used jQuery to check and un-check all the checkboxes in my GridView column. For this I am using a master checkbox with an id “masterCheck”,  and attached its click event to a function which will find all the CheckBoxes with id ending with “chkSelect”.  Once I have checkboxes, I will assign checked state of masterCheck to them. You can change master check box to ASP.NET control also, if you need to manipulate it from server side.

Happy Programming!

Update on 13-October-2009
After so many requests for both side check and un-check, I have updated the code. Now when you un-check a child checkbox, it will check or uncheck the master checkbox also ( if all are checked or un checked).
New code is

[csharp]

<script type="text/javascript" language="javascript">
// for master checkbox
$(document).ready(function () {
$("#masterCheck").click(function () {
isChecked = $(this).is(‘:checked’);
$("[id$=chkSelect]", $("#<%= myGridView.ClientID %>")).attr(‘checked’, isChecked);
});
});

// for checkboxes in GridView
$(document).ready(function () {
$("[id$=chkSelect]", $("#<%= myGridView.ClientID %>")).click(function () {
$("#masterCheck").attr(‘checked’, allAreChecked);
});
});

function allAreChecked() {
var allCheckBoxesCount = $("[id$=chkSelect]", $("#<%= myGridView.ClientID %>")).length;
var allCheckedCheckBoxesCount = $("[id$=chkSelect]:checked", $("#<%= myGridView.ClientID %>")).length;

return (allCheckBoxesCount == allCheckedCheckBoxesCount);
}
</script>

[/csharp]

23 comments on “Master CheckBox in GridView header

  1. Vb Reader on said:

    nice code with good explanation.

  2. Thanks for the simple & effective solution.

  3. Great job!! Thanks for such a neat explanation

  4. Nitin Sharma on said:

    That’s good one..

  5. Thanigiainathan on said:

    Hi,

    Very good article. But instead of checking for the Id names ending with chklist you can assign a class name and use class filter like $(.class) to fetch the control names.

    Thanks,
    Thani

  6. Umer Rasheed on said:

    nice article for beginners.

  7. How about:-

    $(this).is(‘:checked’)

    instead of

    $(‘#masterCheck’).is(‘:checked’)

    to save a little dom traversal seeing as we are already in the click event of the mastercheck we don’t need to go looking for it again.

  8. WebGrid on said:

    Thanks.

  9. @Thani
    That can also be used, but I used it because of two reasons
    1. Selection By IDs is faster.
    2. I can use same class outside GridView also. So I will get more items.
    Right now here, I am sure that I will use only chkSelect in my GridView. But then I can pass context also to my jQuery select method.

  10. @Brian,
    No that will not work. if you closely see it, the call $(this) will return the CheckBox with id ending with chkSelect, not the master checkbox. I have checked it.

    But yes I got your point. And I just added one more line and I hope now we are saving big work.
    $(document).ready(function() {
    $(“#masterCheck”).click(function() {
    isChecked = $(this).is(‘:Checked’);
    $(“[id$=chkSelect]“).attr(‘checked’, isChecked);
    });
    });

    Thanks

  11. @Shail,
    I think you misunderstood me as you did exactly as I suggested. I was not quoting the complete line of your code just the bit that gets the current state of the mastercheck checkbox which could be replace with $(this).

    One other point in terms of unobtrusiveness. It’s worth actually adding the mastercheck with jquery to the dom so it’s not just a useless button sitting there for users with script off.

  12. Thanks. I made my own code awhile back for this problem but was wondering how I could replace it with jQuery. Nice work!

  13. How can we do vice-versa, like, if after selecting master checkbox, now I want to uncheck one child checkbox and also want that my master checkbox should get unchecked automatically. Thanks in advance….

  14. Does this mess up your ViewState? I thought if you manipulated server controls via JavaScript, it would result in a ViewState exception when you do a postback.

  15. @TD
    ViewState is stored on client Side, but it is manipulated on server. Said this, if I check/ucheck checkboxes on client side. Nothing will go bad on server.

  16. Shahriar Hyder on said:

    Nice one mate. I have also added the link to your post in my Ultimate collection of top jQuery tutorials, tips-tricks and techniques to improve performance. Have a check below:

    http://technosiastic.wordpress.com/2009/09/24/collection-of-top-jquery-tutorials-tips-tricks-techniques-to-improve-performance/

  17. Thanks, meanwhile I found a way to do that. Here is an example for that:
    $(document).ready(function() {
    var formFields = { controls: [
    { identifier: \"chkssAll\", control: $(\'#\'), methods: [{ trigger: \"click\", functions: [selectSS]}] },
    { identifier: “chkss1″, control: $(‘#’), methods: [{ trigger: \"click\", functions: [check_uncheck_AllSSTypes]}] },
    { identifier: “chkss2″, control: $(‘#’), methods: [{ trigger: \"click\", functions: [check_uncheck_AllSSTypes]}] },
    { identifier: “chkss3″, control: $(‘#’), methods: [{ trigger: \"click\", functions: [check_uncheck_AllSSTypes]}] },

    ]
    };

    var formControls = new FormControls(formFields);

    //init on page load
    check_uncheck_AllSSTypes();

    });

    function selectSS() {
    $(“[id*=chkss]“).attr(‘checked’, $(‘[id$=chkssAll]‘).is(‘:checked’));

    }

    function check_uncheck_AllSSTypes() {
    $(“[id*=chkssAll]“).attr(‘checked’, ‘checked’);
    if ($(‘[id*=chkss]‘).is(‘:not(:checked)’)) {
    $(“[id*=chkssAll]“).attr(‘checked’, ”);
    }
    }

  18. @Shahriar,
    Thanks mate :)

  19. Sangam Uprety on said:

    Nice tutorial.
    Further, if all the child checkboxes are checked one by one, we have better check the master checkbox also. And if any child checkbox is unchecked, master should be unchecked.

    I guess this would require little more code but would give fantastic output!

    Thanks.

  20. @Sangam Updated. Also check the updated code

  21. Updated. Also check the updated code

  22. Abhishek Sharma on said:

    Great work Sir

  23. mercadee on said:

    select query based on multiple checkboxes just wiondering if there is a way I can do the following. I have a table (table 1) with 10 fields in it. I have a form with 6 of these field names displaying on it. I have a checkbox next to each of these fields. When the checkbox is selected I want to use that field as criteria in a select query. This means that I want the query to select records based on what checkboxes are selected, whether that be 1 checkbox or any combinatiion of the 6 checkboxes. Not completely great with the whole programming thing and would like to be able to do in in a query (design view) if possible.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

18,983 Spam Comments Blocked so far by Spam Free Wordpress

HTML tags are not allowed.