ASP.NET GridView Multi Select Using CheckBoxes and JQuery

Hi,

In this tutorial, I will show you how to implement a multiselect grid view using checkboxes and JQuery. The GridView is a fantastic component but lacks a very useful feature that allows the multiple row selection. Using JQuery, we’ll put a workaround to extend the grid.

First, let’s create an empty ASP.NET Web Application Project and install the JQuery package using the package manager console.

Then, let’s create a new webform called “Default.aspx”.

Let’s create a business class called “Check” and that represents a bank check :

public class Check
    {
      
 
        public DateTime IssueDate { get; set; }
 
        public string CheckNumber { get; set; }
        
    }

Now, let’s add a minimalistic repository class :

public class CheckRepository
    {
        public IEnumerable<Check> GetList()
        {
            var list = new List<Check>();
            for (int i = 0; i < 20; i++)
            {
                var cheque = new Check()
                {
                    CheckNumber = string.Format("{0:00000000}", i + 1),
                    IssueDate = DateTime.Now
                };
                list.Add(cheque);
            }
            return list;
        }
    }

In the default.aspx form, let’s add an object data source component and bind it to the “CheckRepository” class with the “GetList” method.

Let’s add a GridView bound to the object data source having two bound columns : “CheckNumber” and obviously “IssueDate”.

Our work starts here, we need an additional column that contains the selection checkbox. For this, let’s exploit the magic of template fields. The three gridview columns will look like this :

 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1">
                <Columns>
                    <asp:TemplateField>
                        <HeaderTemplate>
                            <input type="checkbox" id="cbSelectAll" />
                        </HeaderTemplate>
                        <ItemTemplate>

                            <input type="checkbox" name="ChequeSelected" class="cbSelectRow" value="<%# Eval("CheckNumber") %>" ></input>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField DataField="CheckNumber" HeaderText="Number" SortExpression="NumeroCheque" />
                    <asp:BoundField DataField="IssueDate" HeaderText="Issue Date" SortExpression="DateEmission" />
                </Columns>

            </asp:GridView>

The checkbox that will select all rows is called “cbSelectAll” and the select row check box will have the css class “cbSelectRow”. The first thing to notice is that for the row checkbox, I have used the “value” attribute that will save the check id in the row checkbox.

The idea is very simple, whenever a postback is triggered,, all the checkbox content will be sent with the form content. We’ll use the checkbox value to know which check have been selected by the user. Precisely, to trigger the postback, let’s add a simple asp.net button to the web form.

I’ll add a very simple effect : the selected rows will be colored in green. To accomplish this, let’s create the lightGreen css class :

 <style type="text/css">
        .lightGreen
        {
            background-color: lightgreen;
        }
    </style>

A little jquery right now: a simple script to transform the containing row of the checked checkbox in green and another one the the “select all checkbox” that will allow to check (or uncheck) the checkboxes :

 $(function () {
            $('.cbSelectRow').change(function () {
                // detect if the checkbox is checked
                var checked = $(this).prop('checked');
                // gets the table row indiect parent
                var trParent = $(this).parents('tr');
                // add or remove the css class according to the check state
                if (checked == true)
                    trParent.addClass('lightGreen')
                else
                    trParent.removeClass('lightGreen');
            });
            // select all click
            $("#cbSelectAll").change(function () {
                var checked = $(this).prop('checked');
                $('.cbSelectRow').prop('checked', checked).trigger('change');
            });
 
        });

The last thing to do is to intercept the postback in the web form and to display the selected checks by browsing the form data, quite simple, let’s modify the “Page_Load” method like this :

if (IsPostBack)
            {
                // create a string builder to create the displayed string
                var builder = new StringBuilder();
                builder.Append("Vous have selected the following checks :<br/>");
                // get the selected checkboxes from the form data
                var checkString = Request.Form["ChequeSelected"];
                if(checkString == null)
                    return;
                // we'll need a split to get the individual ids
                var values = checkString.Split(',');
                foreach(var value in values)
                {
                    builder.Append("<br/>");
                    builder.Append(value);
 
                }
                Response.Write(builder.ToString());
            }

Let’s test and you’ll see it, it works ! The “Reponse”  line displays all the selected checks. But we still have an issue, when a postback is performed, we lose the selected checkboxes in the grid because it have been redrawn and plain HTML string do not support view state.

To get through this problem, the solution is simple too. We’ll save the checked ids in a list called “checkedIds” :

 /// <summary>
        /// this lists stores the ids that have been selected
        /// </summary>
        private List<string> checkedIds = new List<string>();

Let’s change the “Page_Load” method to fill the list :

 protected void Page_Load(object sender, EventArgs e)
        {
            if (IsPostBack)
            {
                // create a string builder to create the displayed string
                var builder = new StringBuilder();
                builder.Append("Vous have selected the following checks :<br/>");
                // get the selected checkboxes from the form data
                var checkString = Request.Form["ChequeSelected"];
                if(checkString == null)
                    return;
                // we'll need a split to get the individual ids
                var values = checkString.Split(',');
                foreach(var value in values)
                {
                    builder.Append("<br/>");
                    builder.Append(value);
                    checkedIds.Add(value);
                }
                Response.Write(builder.ToString());
                GridView1.DataBind();
            }
        }

The last line forces the gridview to “redraw”. This manipulation is still not sufficient to restore the display, we have to change the checkbox in order to reflect (or not) a previous selection :

  <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1">
                <Columns>
                    <asp:TemplateField>
                        <HeaderTemplate>
                            <input type="checkbox" id="cbSelectAll" />
                        </HeaderTemplate>
                        <ItemTemplate>
 
                            <input type="checkbox" name="ChequeSelected" class="cbSelectRow" value="<%# Eval("CheckNumber") %>" <%# NumeroChequeInclus(Eval("CheckNumber").ToString()) %>></input>
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField DataField="CheckNumber" HeaderText="Number" SortExpression="NumeroCheque" />
                    <asp:BoundField DataField="IssueDate" HeaderText="Issue Date" SortExpression="DateEmission" />
                </Columns>
 
            </asp:GridView>

Notice that the checkbox will render something that the method “CheckNumber” returns by passing the current check number as argument.

The method “CheckNumber” have to generate “"the “checked” attribute if the passed id is contained in the “checkedIds” list or an empty string otherwise.

 /// <summary>
        /// renders or not the checked attribute
        /// </summary>
        /// <param name="numero"></param>
        /// <returns></returns>
        public string NumeroChequeInclus(string numero)
        {
            if (checkedIds.Contains(numero))
                return "checked";
            return string.Empty;
        }

The last thing to do is to modify the jquery script to restore the green background after a postback, the full script would be like this :

 $(function () {
            $('.cbSelectRow').change(function () {
                // detect if the checkbox is checked
                var checked = $(this).prop('checked');
                // gets the table row indiect parent
                var trParent = $(this).parents('tr');
                // add or remove the css class according to the check state
                if (checked == true)
                    trParent.addClass('lightGreen')
                else
                    trParent.removeClass('lightGreen');
            })
            // the each is used when postback is triggered with checked rows
            .each(function (index, element) {
                var checked = $(element).prop('checked');
                if (checked == true)
                    $(element).parents('tr').addClass('lightGreen');
            });
            // select all click
            $("#cbSelectAll").change(function () {
                var checked = $(this).prop('checked');
                $('.cbSelectRow').prop('checked', checked).trigger('change');
            });
 
        });

 

A working version of the app would look like this :

capture

The full source code is available here

Enjoy !

Comments (8) -

  • hello  ,i think it is time to jump to ASP.NET MVC...
    • I've personnaly jumped into the ASP.NET MVC since the third version (with the introduction of razor).

      But I still provide assistance to many enterprise that still use ASP.NET and I recommand ASP.NET for the teams that are not very skilled in client technologies (CSS|HTML|JS)

      Thanks
  • First of all thank you.it's a good work.
    But if you deselect one checkBox from grid the checkbox cbSelectAll stile checked    
  • Does this work with multiple pages in the grid?
    • No,

      as JQuery works on the DOM so the selection works only on the currently displayed page of the grid

      If you want to select all the record including the other pages, you have to use AJAX and implement the selection on the server side.

      However, some JQuery grids use client pagination (ie records are loaded on the client but just hidden), in this approach, the selection could eventually work. Meanwhile, this is not a recommanded approach for performance.
  • PJ
    Thanks very much, extremely helpful. I think you have no idea how "très utile" this is, even now in 2016 ;)
    Just a few practical comments for others.
    - include a script tag with source pointing to your Jquery js (see source, the HTML Header tag in Default.aspx in the full source).
    - line 9 of the anonymous JS function should be really terminated with a semi-colon, but that's optional

Add comment

Loading