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 :
The full source code is available here
Enjoy !