Click here to Skip to main content
Click here to Skip to main content

Sortable GridView using jQuery's TableSorter

By , 8 Oct 2008
 

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

Client Side Sort in GridView using jQuery - Table Sorter

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, //provides debugging information
sortList: [[0, 1]], //sorts 0th column by descending order
dateFormat: "uk", //sets the date format to dd/MM/yyyy 
});

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.

//define a parser
$.tablesorter.addParser(
{
// set a unique id 
id: 'formattedNumbers',
is: function(s) 
{
// return false so this parser is not auto detected 
return false;
},
format: function(s) 
{
// format your data for normalization
return s.replace(/,/g, '');
//removes comma separator from formatted numbers
},
// set type, either numeric or text 
type: 'numeric'
});
//initialize table for sorting
$("#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:

//define a function for extracting text from node
function extractValue(node)
{ 
    var children = node.childNodes[0].childNodes.length
    if (children == 0) //boundTextField or a templateColumn
    {
        if (node.childNodes[0].nodeType == 3)//boundTextField
        {
            return node.childNodes[0].data;
        }
        else //template column
        {
            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 //boundCheckboxColumn or a templateLabelColumn
    {
        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.

License

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

About the Author

Ponnurangam D
Software Developer GMS Ltd.
United Kingdom United Kingdom
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionLive Demo does not workmemberMember 891123014 Nov '12 - 21:10 
I went to http://ponnu.net/TableSorter/[^]
 
and it seems like the example is not working.
There are no sorting buttons next to the column headers, and when I click on the titles themselves nothing happens.
 
Any idea what is causing this?
 
thanks.
Questionupdatepanelmemberssanp19 Apr '12 - 11:10 
your comment
"If you are using an UpdatePanel, you need to consider using the PageLoad function (JavaScript):"
how would you write the javascript, i am struggling with it.Any help will be great!
 
Thanks.
GeneralTemplate Columns with hyperlinks and they don't parse correctly in FirefoxmemberMember 223319511 Dec '09 - 8:29 
This works great! Thanks for the post.
 
What I was able to figure out so far is that the extractText function always executes as a boundTextField, it never makes it to the else statement for the template column in firefox and the text doesn't get parsed so the sort doesn't work on those columns.
 
if (children == 0) //boundTextField or a templateColumn
{
if (node.childNodes[0].nodeType == 3)//boundTextField
{
return node.childNodes[0].data;
}
else //template column
{
var type = node.childNodes[0].type
 

Works fine in IE 8.
GeneralRe: Template Columns with hyperlinks and they don't parse correctly in FirefoxmemberMember 223319511 Dec '09 - 8:52 
You could replace the function with a bit of jQuery...this example is for hyperlinks only, but could by modified.
 
<script type="text/javascript">
//define a function for extracting text from node
function extractValue(node) {
var jQueryNode = $(node);
 
if ($('a', jQueryNode)) {
return $('a', jQueryNode).text();
}
 
return jQueryNode.html();
}
$(document).ready(function() {
 
$(".sort").each(function() {
$(this).tablesorter(
{
textExtraction: extractValue
});
}); //end document.ready
 
// Add a parser for numbers
});
</script>
GeneralJQuery Tablesorter does not seem to work with Master Pagesmembersvrevm13 Sep '09 - 16:34 
I tried this in an application that has Master Pages and it did not work. All the JQuery files are referenced in the <head></head> section of the Master Page.
 
Then I tried referenceing the JQuery files directly in the content page and the tablesorter still did not work.
 
In one of the files, I directly referenced the JQuery files, removed reference to the Master Page and then the tablesorter worked.
 
Could you provide an example of how to make it work in an application with Master Pages?
 
Thanks much.
GeneralRe: JQuery Tablesorter does not seem to work with Master PagesmemberPriyanka Kalra17 Sep '09 - 6:09 
I have the same problem with getting the sorting to work with Master Page. Can someone please help with solution.
GeneralRe: JQuery Tablesorter does not seem to work with Master PagesmemberPonnurangam D17 Sep '09 - 6:11 
Sorry about the delay, been little busy at work. Will post a sample that works with Master pages tonight.
 
Thanks & Regards
Ponnu

GeneralRe: JQuery Tablesorter does not seem to work with Master PagesmemberPonnurangam D18 Sep '09 - 0:34 
Download the sample using masterpage from here,
http://ponnu.net/Samples/TableSorterMasterPage.zip
 
When using gridview in masterpages or usercontrols, use the ClientID like this,
 
$(document).ready(function() 
{
$("#<% =gvRoles.ClientID %>").tablesorter(); 
});

 
Thanks & Regards
Ponnu

GeneralRe: JQuery Tablesorter does not seem to work with Master Pagesmembersvrevm17 Sep '09 - 15:09 
I got it.
 
To refer a gridview that's in a content page, the gridview must be qualified with the content placeholder id. After the content page gets loaded, do viewsource to get the full name of the gridview.
 
example: if the gridview id is Grid1, then this is how it must be written:
 
$("#ctl00_ContentPlaceHolder1_Grid1").tablesorter(
{
debug: false,
widgets: ["zebra"]
});
 
Hope this helps. This resolved this issue for me. I was able to refer to all the controls on my content page this way.
AnswerThousand Separator in GridView with IsNumeric function of C#memberNitish.11274 Nov '08 - 22:17 
Hello
this is for Thousand Separator in gridview with isNumeric()

//isNumeric()
public bool isNumeric(string val,System.Globalization.NumberStyles NumberStyle)
{
Double result;
return Double.TryParse(val, NumberStyle, System.Globalization.CultureInfo.CurrentCulture, out result);
 
}
 

//GridviewRowDataBound
protected void gvTable_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowIndex > 0)
{
for (int i = 0; i < gvTable.Rows.Count; i++)
{
for (int j = 0; j <gvTable.Rows[i].Cells.Count; j++)
{
if(isNumeric(e.Row.Cells[j].Text, System.Globalization.NumberStyles.Integer))
{
int temp = Convert.ToInt32(e.Row.Cells[j].Text);
e.Row.Cells[j].Text = string.Format("{0:#,0}", temp);
}
}
}
}
Hopfully it will help
Blush | :O

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 8 Oct 2008
Article Copyright 2008 by Ponnurangam D
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid