Introduction
This article explains how to use jQuery's plug-in Tablesorter to implement client-side sorting in an ASP.NET GridView
. This comes in handy especially when an ObjectDataSource
is used with a GridView
as GridView
does not provide sorting out of the box.
Implementation
To implement TableSorter, the rendered table should have THEAD
in the markup. GridView
does not provide this by default, but we could achieve it either by setting the appropriate properties or by using a CSS friendly control adapter. We will do it by using the former method.
Sample

You could have a look at it online here: http://ponnu.net/TableSorter.
Using the code
We should get a table with THEAD
tags for the GridView
to implement the sorting. So, let's do that:
protected void Page_Load(object sender, EventArgs e)
{
if (this.gvEmployees.Rows.Count > 0)
{
gvEmployees.UseAccessibleHeader = true;
gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
If you are using the GridView
in an UpdatePanel
and binding it in a callback, then it's better to put it in the GridView
's DataBound
event:
protected void gvEmployees_DataBound(object sender, EventArgs e)
{
if (this.gvEmployees.Rows.Count > 0)
{
gvEmployees.UseAccessibleHeader = true;
gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
}
}
Now, download and include the jQuery and TableSorter JavaScript files as follows:
<script type="text/javascript" src="scripts/jquery-latest.js"></script>
<script type="text/javascript" src="scripts/jquery.tablesorter.js"></script>
Initialize the table for sorting when the document is ready, using the code below:
$(document).ready(function()
{
$("#gvEmployees").tablesorter();
});
If you are using an UpdatePanel
, you need to consider using the PageLoad
function (JavaScript):
$("#gvEmployees").tablesorter();
At this point, the sorting should work on the client side. Now, you would want to set the ascending and descending icons for the grid headers. You could easily do this by defining these styles in your style sheet:
.headerSortUp
{
background-position:top;
background-repeat: no-repeat;
background-image: url(../images/icons/sort_up.gif);
background-color: #e9e7d7;
}
.headerSortDown
{
background-position:top;
background-repeat: no-repeat;
background-image: url(../images/icons/sort_down.gif);
background-color: #e9e7d7;
}
Or, you could use the styles that come with the Tablesorter as follows. Just set the GridView
CSS class name to Tablesorter and include the stylesheet as follows:
gvEmployees.CssClass = "tablesorter";
In the HTML:
<link rel="stylesheet" type="text/css" href="themes/green/style.css" />
Tablesorter provides lots of config options, here are a few important ones:
sortList
: [0, 1] -- This instructs to sort by the index 0 column in descending order.dateFormat
: "uk" -- if your format is dd/MM/yyyy, it does not seem to work by default for this format.debug
: true -- this options provides you information like how much time it took and how (what type) it considered the columns.
$("#gvEmployees").tablesorter(
{
debug: true,
sortList: [[0, 1]],
dateFormat: "uk",
});
Now, some interesting things. If you have columns that are formatted differently like having a thousand separator. We could use a custom parser in this scenario. Otherwise, the data would be considered a string and the sorting would not work as expected.
We should define a custom parser with an ID and then assign it to a column while initializing the Tablesorter.
$.tablesorter.addParser(
{
id: 'formattedNumbers',
is: function(s)
{
return false;
},
format: function(s)
{
return s.replace(/,/g, '');
},
type: 'numeric'
});
$("#gvEmployees").tablesorter(
{
headers:
{
6: { sorter: 'formattedNumbers' }
}
});
There might be templated columns and checkbox bound fields in the GridView
, and if we need to do sorting for those columns, we could do so by using text extraction. Text extraction is similar to custom parser, but this applies to the whole table and gets a node instead of a string for processing. Here is some code that will process templated text columns and checkbox bound columns:
function extractValue(node)
{
var children = node.childNodes[0].childNodes.length
if (children == 0)
{
if (node.childNodes[0].nodeType == 3)
{
return node.childNodes[0].data;
}
else
{
var type = node.childNodes[0].type
switch (type)
{
case "checkbox":
return node.childNodes[0].checked.toString()
case "radio":
return node.childNodes[0].checked.toString()
case "text":
return node.childNodes[0].value
default: return ""
}
}
}
else
{
if (node.childNodes[0].childNodes[0].nodeType == 3)
{
return node.childNodes[0].childNodes[0].data;
}
else
{
return node.childNodes[0].childNodes[0].checked.toString();
}
}
}
$("#gvEmployees").tablesorter(
{
textExtraction: extractValue
});
This covers most of things that one would do in a GridView
. The download contains all the above mentioned code.
Lastly, I would like to thank John Resig and Christian Bach for providing such a wonderful framework.
Points of interest
The Tablesorter is very good for the kind of functionality it provides with so much less code and effort. I am sure more and more people would be interested in this, and would be using this as Microsoft recently announced its support to jQuery.
It's very simple to create an extended GridView
control built with these functionalities. I will leave that to the user.
Feedback
This is my first article in CodeProject and I would appreciate everyone's feedback.