|
|
Sorting GridView Using IComparer
AzamSharp
Published Date: 9/29/2006 2:45:22 PM
Views: 20259
Abstract:
Sorting in a GridView is a common scenario required by most of the web applications. In my previous articles I discussed GridView Sorting Using Bound Columns and Sorting GridView with Autogenerated Columns. In both of my previous articles I used the help of DataView object to sort the container. Most of the enterprise applications take advantage of the entity classes which allow the basis for object oriented programming. In this article I will explain how you can sort the GridView control which uses a generic list as its data source.
Introduction: Sorting in a GridView is a common scenario
required by most of the web applications. In my previous articles I discussed
GridView Sorting Using Bound Columns and Sorting GridView with Autogenerated
Columns. In both of my previous articles I used the help of DataView object to
sort the container. Most of the enterprise applications take advantage of the
entity classes which allow the basis for object oriented programming. In this
article I will explain how you can sort the GridView control which uses a
generic list as its data source. Creating a
GridView Control: Let's first create a GridView control. The GridView will contain two
bound columns and two template columns. Take a look at the code below:
<asp:GridView EnableSortingAndPagingCallbacks="false" AllowSorting="true" ID="gvUsers" runat="server" AutoGenerateColumns="false" OnSorting="gvUsers_Sorting" > <Columns> <asp:BoundField DataField="FirstName" HeaderText="First Name" SortExpression="FirstName" /> <asp:BoundField DataField = "LastName" HeaderText= "Last Name" SortExpression="LastName" /> <asp:TemplateField HeaderText="Class Code" SortExpression="ClassCode"> <ItemTemplate> <asp:Label ID="lblClassCode" runat="server" Text='<%# Eval("ClassCode") %>' /> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> | Notice that I have also included the SortExpression for
all the columns of the GridView control. The SortExpression denotes the field
which is used for sorting the GridView.
Creating an
Entity Class
I will create a very simple User entity
class. Once, the class is created I will fill the generic List with
the objects and send it back to the client where they are displayed in the
GridView.
Take a look at the code below which creates a very simple
entity class User.cs: public class User { private string firstName; private string lastName; private string classCode;
public string FirstName { get { return this.firstName; } set { this.firstName = value; } }
public string LastName { get { return this.lastName; } set { this.lastName = value; } }
public string ClassCode { get { return this.classCode; } set { this.classCode = value; } }
public User() {
} }
|
Implementing GetAllUsers Method
The GetAllUsers
method is responsible for fetching the list of users and sending the list
back to the client. In the code below I am using a generic list which can
contain objects of type User.
public List GetAllUsers() { List users = new List();
string connectionString = @"Server=localhost;Database=School;Trusted_Connection=true"; SqlConnection myConnection = new SqlConnection(connectionString);
SqlCommand myCommand = new SqlCommand("SELECT * FROM Users", myConnection);
myConnection.Open(); SqlDataReader reader = myCommand.ExecuteReader(); while (reader.Read()) { User user = new User(); user.FirstName = reader["FirstName"] as String; user.LastName = reader["LastName"] as String; user.ClassCode = reader["ClassCode"] as String;
users.Add(user); }
myConnection.Close(); myCommand.Dispose();
return users;
}
|
Binding Data Source to GridView Control
Now, that
we have filled the list with User objects we can bind the list to the GridView.
Take a look at the code below which binds the list of users to the GridView
control.
private void BindData() { User user = new User(); gvUsers.DataSource = user.GetAllUsers(); gvUsers.DataBind();
}
|
Although
you have bind the list to the GridView, the sorting mechanism is not yet
enabled. In order to deal with sorting which is dependent on the list of objects
you will need to create a Comparer which implements the IComparer
interface. The IComparer interface contains a method name CompareTo, which
you can implement to compare the objects.
Implementing the IComparer Interface
We will
create a class called GenericComparer which will implement the IComparer
interface. The GenericComparer class contains bunch of stuff so let's check it
out in detail.
SortDirection : The sort direction indicates
the direction of the sort. This can be ascending or descending.
public SortDirection SortDirection { get { return this.sortDirection; } set { this.sortDirection = value; } } |
GenericComparer
Constructor : The contructor takes two arguments namely, sortExpression and
sortDirection. The sortExpression is the name of the GridView column to sort and
sortDirection denotes the direction in which the column has to be sorted. The
sortDirection can be ascending or descending.
public GenericComparer(string sortExpression, SortDirection sortDirection) { this.sortExpression = sortExpression; this.sortDirection = sortDirection; }
|
CompareTo Method: The CompareTo method is the place where all the
fun happens. The CompareTo method takes a generic T as an argument which means
it can accept any type of object. Then it uses the sortExpression to extract the
property out of the type and finally it performs the comparison on the
properties.
public int Compare(T x, T y) { PropertyInfo propertyInfo = typeof(T).GetProperty(sortExpression); IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null); IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
if (SortDirection == SortDirection.Ascending) { return obj1.CompareTo(obj2); } else return obj2.CompareTo(obj1);
}
|
Using the Code
An ideal place to call the sorting
method is inside the GridView_Sorting event which is fired when you clicked the
column header of the GridView control. Take a look at the code below:
protected void gvUsers_Sorting(object sender, GridViewSortEventArgs e) { User user = new User(); List users = user.GetAllUsers();
users.Sort(new GenericComparer(e.SortExpression, GridViewSortDirection));
gvUsers.DataSource = users; gvUsers.DataBind(); }
|
Now,
if you click on the GridView header it will be sorted based on what column you
clicked on.
I hope you liked the article, happy coding!
Enter Comment/Feedback
Comments/Feedbacks
|
|
|
|
Subject: Many Thanks
Name: Steck
Date: 2/15/2007 8:12:29 AM
Comment: Fantastic !!!
Thanks to you, i how you a lot of developpement time ! |
|
|
|
|
|
Subject: Awesome Work
Name: Rodney
Date: 2/22/2007 1:25:00 PM
Comment: I did have one question. How do you deal with items that are null? When I apply this technique to my data, I get errors on columns that have null values. Column that have values (string, int, etc) for every record sort just fine. |
|
|
|
|
|
Subject: Use DBNull.Value
Name: AzamSharp
Date: 2/22/2007 6:43:26 PM
Comment: You can use DBNull.Value to check against NULL values. |
|
|
|
|
|
Subject: Thanks for this wonderful artcile.
Name: Gaurav Rawat
Date: 4/23/2007 3:43:47 AM
Comment: Hi Azam,
Thanks for this wonderful article. |
|
|
|
|
|
Subject: gridview
Name: ravi
Date: 6/27/2007 2:57:45 AM
Comment: great
|
|
|
|
|
|
Subject: Good
Name: harish
Date: 6/29/2007 12:21:13 PM
Comment: Nice. Thank you. |
|
|
|
|
|
Subject: Great!
Name: Ahmad Abu-Raddad
Date: 7/19/2007 2:15:23 AM
Comment: Awesome, thank you very much.
I was doing the same sort mechanism but was wondering how to do a generic class that works for any business entity.
Cheers |
|
|
|
|
|
Subject: Sorting in opposite direction
Name: San,
Date: 9/27/2007 5:03:45 PM
Comment: Great!! Good article,
Is there any generic way way to do 2 direction (asc/desc) sorting?
Regards
|
|
|
|
|
|
Subject: convert to VB.NET
Name: Tolga
Date: 12/17/2007 2:59:00 AM
Comment: Great Job.
But I have a problem if I use this code with vb.net. I got the following error:
Error 1 Class 'GenericComparer' must implement 'Function Compare(x As T, y As T) As Integer' for interface 'System.Collections.Generic.IComparer(Of T)'.
the vb.net code like this:
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection
Public Class GenericComparer(Of T)
Implements IComparer(Of T)
Private m_sortDirection As SortDirection
Private sortExpression As String
Public Property SortDirection() As SortDirection
Get
Return Me.m_sortDirection
End Get
Set(ByVal value As SortDirection)
Me.m_sortDirection = value
End Set
End Property
Public Sub New(ByVal sortExpression As String, ByVal sortDirection As SortDirection)
Me.sortExpression = sortExpression
Me.m_sortDirection = sortDirection
End Sub
Public Function Compare(ByVal x As T, ByVal y As T) As Integer
Dim propertyInfo As PropertyInfo = GetType(T).GetProperty(sortExpression)
Dim obj1 As IComparable = DirectCast(propertyInfo.GetValue(x, Nothing), IComparable)
Dim obj2 As IComparable = DirectCast(propertyInfo.GetValue(y, Nothing), IComparable)
If SortDirection = SortDirection.Ascending Then
Return obj1.CompareTo(obj2)
Else
Return obj2.CompareTo(obj1)
End If
End Function
End Class |
|
|
|
|
|
Subject: My Hero.
Name: Al.
Date: 1/29/2008 6:46:16 AM
Comment: Thanks Dude, You saved the day! |
|
|
|
|
|
Subject: re: convert to VB.NET
Name: Michael
Date: 2/12/2008 1:08:12 PM
Comment: Tolga,
Public Function Compare(ByVal x As T, ByVal y As T) As Integer Implements IComparer(Of T).Compare
Fixed the problem for me. |
|
|
|
|
|
Subject: Superb Article
Name: siva
Date: 3/8/2008 5:43:48 AM
Comment: Wow article |
|
|
|
|
|
Subject: source incomplete
Name: Allan Mikaya
Date: 3/8/2008 5:04:09 PM
Comment: I didnt see "BasePage" in the source. |
|
|
|
|
|
Subject: RE: Source Incomplete
Name: AzamSharp
Date: 3/8/2008 8:12:50 PM
Comment: Hi,
Hmmm thats strange! You can add a cs file and inherit from System.Web.UI.Page and name it the BasePage.cs. Now, all your pages will inherit from this BasePage instead of the System.Web.UI.Page. |
|
|
|
|
|
Subject: sorting problem with referenced objedts
Name: kirsh
Date: 4/3/2008 12:08:01 AM
Comment: Hi thanks 4 ur nice article... but the problem is that when iam genrating list lst hav hospital list ,, that references patients...
While sorting
case 1:hospital.hospital id-- working fine
case 2: hospital.patiend.patienid-- not working ...
can u plzz help me to solve tis problemmmmm
Thanks.. |
|
|
|
|
|
Subject: problem with referedclasses
Name: raj
Date: 4/4/2008 4:33:17 AM
Comment: refernces problem
Like:MASTER AND STUDENT Classess
InCase:MASTER.masterID--Working fine
InCase:MASTER.STUDENT.studentID--Problem
ERROR:Object Refence is not set to an instance of object
Waitng for ur replyy..
Thnks. |
|
|
|
|
|
Subject: Thanks i got solution
Name: raj
Date: 4/8/2008 12:17:52 AM
Comment: Hi i got solution
thanku.......... |
|
|
|
|
|
Subject: Simply... Great solution
Name: Luis Canales
Date: 4/27/2008 7:14:21 PM
Comment: I searching for something like this for my enterprise aaplication... and you give the light... thanx.. |
|
|
|
|
|
Subject: Getting it to work with ObjectDataSource?
Name: David C
Date: 4/29/2008 11:56:39 AM
Comment: Is it possible to get it to work with ObjectDataSource? I get the "The data source 'odsFacilities' does not support sorting with IEnumerable data. Automatic sorting is only supported with DataView, DataTable, and DataSet" error |
|
|
|
|
|
Subject: Getting it to work with ObjectDataSource?
Name: David C
Date: 4/29/2008 11:58:37 AM
Comment:
Thank you for the wonderful article, but I can't get the code to work, and it is probably because I am new to Generics.
I am seeing that you are skipping the type argument for T (in this case User). |
|
|
|
|
|
Subject: Sorting null
Name: Peter
Date: 5/22/2008 8:26:52 PM
Comment: Hi Thanks for this solution.
I also had the Null problem mentioned in an earlier comment. I added the following lines in the generic compare to get is working:
if (SortDirection == SortDirection.Ascending)
{
if (obj1 == null)
return (obj2 == null) ? 0 : -1;
return obj1.CompareTo(obj2);
}
if (obj2 == null)
return (obj1 == null) ? 0 : -1;
return obj2.CompareTo(obj1);
cheers |
|
|
|
|
|
Subject: Descending Sort
Name: Andrew
Date: 6/5/2008 5:36:33 AM
Comment: Nice article. It seems that without an ObjectDataSource, the SortExpression and SortDirection properties on the GridView control are not set. As a result, the sorts are always ascending. Do you know of a solution to this problem?
Cheers,
Andrew |
|
|
|
|
|
Subject: re: Descending Sort
Name: AzamSharp
Date: 6/8/2008 8:16:41 AM
Comment: Hi Andrew,
Not sure if I understand your question. But the SortExpression and the SortDirection are the GridView properties and they have no dependency on the ObjectDataSource control. |
|
|
|
|
|
Subject: reference problem
Name: Joe
Date: 7/14/2008 2:43:19 PM
Comment: First off I just want to say awesome article and I would be lost without it.
I saw that kirsh and raj had the same problem as me with referenced code but I didn't see the solution. For example customer.customerName works fine but not customer.account.accountID.
Another question I had was regarding the name "GridViewSortDirection" in the code. Where is that value supposed to come from? I used e.SortDirection but its always ascending, is this a value I need to change myself?
Thanks,
Joe |
|
|
|
|
|
Subject: RE: reference problem
Name: AzamSharp
Date: 7/17/2008 12:10:08 PM
Comment: Hi Joe,
GridViewSortDirection is a property which stores the state of the sort direction which can be ascending or descending. You can download the code which is at the end of the article.
I will check out the second issue. Just send me an email to remind me!! |
|
|
|
|
|
Subject: Owsome Article
Name: rachna Singh
Date: 7/25/2008 2:59:20 AM
Comment: Thanks alot |
|
|
|
|
|
Subject: I can't see GridViewSortDirection property.
Name: chuti
Date: 8/4/2008 2:34:41 AM
Comment: Hi ,
I have read your comment that sent back to Joe. But i have not seen your code.
Thanks
Chuti |
|
|
|
|
|
Subject: I cant see the GridViewSortDirection too
Name: Solo
Date: 11/6/2008 12:01:07 PM
Comment: The article is wondeful though. Thanks |
|
|
|
|
|
Subject: Re: GridViewSortDirection
Name: AzamSharp
Date: 11/10/2008 7:55:04 AM
Comment: Hi,
I think GridViewSortDirection is a typo. It should be SortDirection.
Thanks,
|
|
|
|
|
|
Subject: Overloaded Gridview not behaving well
Name: Carl Sadlier
Date: 11/13/2008 7:16:09 AM
Comment: We have an overloaded gridview with sorting, and paging functionality. The datasource is a generic List. We have a Linkbutton for editing the data in the grid. When we sort, the first page gives us a different order than the database; however, when we page to the second page and then page back we have a different recordset. |
|
|
|
|
|
Subject: Great article !
Name: Dmitry Zorin
Date: 11/3/2009 8:49:44 PM
Comment: Exactly wat I was looking for. I am anew fan of highoncoding.com |
|
|
|
|
|
Subject: Sorting
Name: Fardin
Date: 3/9/2010 9:32:31 PM
Comment: What does this line means " Then it uses the sortExpression to extract the property out of the type and finally it performs the comparison on the properties. " in the "Compare to method section" ? |
|
|
|