ASP.NET VERSIONS: ALL
Sort a Grid on More than One Column
By Brad McCabe
The ASP.NET DataGrid provides developers with a rich set of functionality right out of the box. However, end users often desire more features in their applications. One heavily requested feature from users is the ability to sort a grid on more than one column. With the DataGrid, you can only set the AllowSorting property and enable sorting on a single column. In this article we ll look at extending this functionality to allow for multiple column sorting.
To start, we ll drop a DataGrid onto a new Web Form and set its AllowSorting property to true. After creating a few columns and loading the grid with data we have a functioning grid that allows users to click on any column header and sort by that column. This is no different than you would create any grid.
To extend this functionality we are going make a few changes to the way we data bind and use a DataView to obtain our multi-column sorting.
For more information on the DataView see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDataDataViewClassTopic.asp.
Add the following function to your code behind page:
Private Sub GetData(ByVal SortBy As String)
Dim dataSet As DataSet = New DataSet
Dim dataView As DataView = New DataView(dataSet.Tables(0))
If (SortBy.Length > 0) Then
dataView.Sort = SortBy
DataGrid1.DataSource = dataView
Before we start to look at this function in detail, notice this function is loading its data from a basic XML file. In a production environment you would have more complex code here to fetch your data from a database or some form of cache. This has been replaced with loading from an XML file each time to make the code easier to follow.
The first thing the function does is create a new DataView from the correct table in the DataSet. The DataView object allows us to sort the contents by passing in a sort by clause. This is how we will multi-sort our results; after we sort the DataView object we bind the grid to this view.
To initially load our data we will call this function and space in an empty string for the SortBy parameter. This will cause our raw, unsorted data to be displayed in the grid.
Every time a column header is clicked and the grid is resorted we will receive a SortCommand event. It is in this event that we will update the header text and the sort expressions. Inside of this event we create a simple for next loop to iterate through the columns for the grid and use the following code inside the loop:
If column.SortExpression.Equals(e.SortExpression) Then
column.HeaderText = _
column.HeaderText.Replace(" (Asc)", "").Replace(" (Desc)", "")
Select Case True
Case e.SortExpression.IndexOf(" Asc") > 1
column.SortExpression = e.SortExpression.Replace(" Asc", " Desc")
column.HeaderText += " (Desc)"
Case e.SortExpression.IndexOf(" Desc") > 1
column.SortExpression = e.SortExpression.Replace(" Desc", "")
column.SortExpression = e.SortExpression + " Asc"
column.HeaderText += " (Asc)"
This block of code is designed to locate the column that the user has just clicked on. Once it finds the column it will update an ascending sort order to be descending on this column, or if it is already sorted descending it will cycle it to be not sorted.
Here we also add the words (Asc) or (Desc) to the column header to visually notify the user of the columns that they have sorted. Instead of text you can get more creative here and insert up and down arrows, images, or other text if needed.
After we have updated the correct columns header text and sort expression we can continue building up the sort by string with the following code:
If column.SortExpression.IndexOf(" Asc") > 1 OrElse _
column.SortExpression.IndexOf(" Desc") > 1 Then
If sortBy.Length > 0 Then
With this code we build up the order by clause to pass to the DataView object. The code in this example simply loops the columns and builds the order by clause in order of the columns in the grid, not in the order that the user clicked on the columns. This might or might not be acceptable in all applications.
If you want to maintain the sort by in order of the column header clicks you would need to store this information in an external location, such as the session, cookie, or hidden field on the form. Instead of building the order by, as we do here, in order of the columns, you would replace this code with a function to fetch the order for your external location.
Once we have created our order by clause we simply call GetData to sort and rebind our DataGrid:
With the addition of our extra code to the DataGrid s SortCommand function we have taken the standard single column sorting grid and used the power of the DataView to enable multi-sort capability. Although the code in this article was shown inline with the event handler, you could easily add this code to your standard ASP.NET libraries and call it from any DataGrid.
Figure 1: With a bit of extra code the ASP.NET DataGrid can easily be made to sort by multiple columns.
The sample code in this article is available for download.
Brad McCabe is a consultant with Ajilon Consulting, a leading solutions provider. Brad also has been a systems architect and consultant for several Fortune 500 companies and has been a featured speaker at numerous Microsoft events around the world. His primary interests include ASP.NET, Tablet PC, .NET Compact Framework, and Microsoft s networking technologies. E-mail him at [email protected].