Ascending and Descending Sorting of Columns in an ASP.NET DataGrid...
The DataGrid allows ascending sorting very easily. But we've all gotten used to applications like Outlook which allow two way sorting. Click a column header once and you get ascending sorting, click again and you get descending sorting. We'll see one way to implement it with the datagrid.
I think the introductory remarks above pretty well state what we are going to cover in this article. We will build a DataGrid which allows sorting, but unlike the usual ascending order only sort we will allow both ascending and descending sorts. The first click on a column header will result in an ascending sort. The next click will result in a descending sort. Another click and we are back to an ascending sort, etc. Anytime we switch to a new column we will get an ascending sort by default. We could have designed different behavior, but this is what we chose for demonstration purposes. You can change the logic if you choose very easily.
There is no magic in the .aspx page so let's show it and get to the code behind page where all the logic resides. The only two things you need to notice is that we have set the AllowSorting property to True, and have set up an OnSortCommand event handler named SortCommand_Click. We need to do this for any datagrid which is to implement sorting.
|
<%@ Page Language="vb" Src="SortAscDesc.aspx.vb" Inherits="SortAscDesc" %> <html> <head> <title>Ascending and Descending Sorting in a DataGrid</title> <meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"> <meta name="CODE_LANGUAGE" content="Visual Basic 7.0"> <meta name=vs_defaultClientScript content="JavaScript"> <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body> <h3><font face="Verdana">Ascending and Descending Sorting in a DataGrid</font></h3> <form ID="form1" runat="server"> <asp:DataGrid id="dtgCusts" Width="700" Cellpadding="2" Cellspacing="0" Gridlines="Horizontal" HeaderStyle-BackColor="IndianRed" HeaderStyle-Font-Bold="True" HeaderStyle-Font-Name="Verdana" HeaderStyle-Font-Size="12px" HeaderStyle-ForeColor="White" ItemStyle-BackColor="Gainsboro" ItemStyle-Font-Name="verdana" ItemStyle-Font-Size="12px" AllowSorting="True" OnSortCommand="SortCommand_Click" runat="server" /> </form> </body> </html> |
The code behind page is not overly complicated or long but we will cover it in three sections for ease of discussion. In this first section notice the Page_Load subroutine. The variable strOrderBy is really just e.SortExpression that we will see later on, but with either " ASC" or " DESC" added to it to get the intended sort order. You will also see two Session variables. "Column" contains the name of the column last clicked on. "Order" contains either "ASC" or "DESC" so that we know the sort that was last performed. Knowing which sort order was used on the last click on the same column allows us to reverse the order on the next click. With these settings in Page_Load the grid will load the first time with the CompanyName column sorted in ascending order.
|
Imports System Imports System.Web.UI.WebControls Imports System.Data Imports System.Data.SqlClient Imports System.Configuration Public Class SortAscDesc : Inherits System.Web.UI.Page Protected WithEvents dtgCusts As DataGrid Protected lblOrderBy As Label Protected strOrderBy As String Protected strSql As String = "SELECT Top 15 CompanyName, ContactName, ContactTitle, Phone FROM Customers" Sub Page_Load(sender As Object, e As EventArgs) If Not Page.IsPostBack Then strOrderBy = "CompanyName ASC" Session("Column") = "CompanyName" Session("Order") = "ASC" BindTheData() End If End Sub |
In the BindTheData() subroutine we create a DataSet and then a DataView. We then use the Sort method of the DataView to do the sorting. I usually prefer to use DataReaders unless I really need a DataSet for something, but decided to do it this way this time to get some more experience with DataViews. Notice that we set dv.Sort = strOrderBy. As we will see in the next section of code strOrderBy is really e.SortExpression (a column name), but with " ASC" or " DESC" tacked onto the end.
|
Sub BindTheData() Dim strConn As String StrConn = ConfigurationSettings.AppSettings("NorthwindConnection") Dim ds As DataSet = new DataSet() Dim da As SqlDataAdapter = new SqlDataAdapter(strSql, strConn) da.Fill(ds, "Customers") Dim dtCustomers As DataTable = ds.Tables("Customers") Dim dv As New DataView(dtCustomers) dv.Sort = strOrderBy dtgCusts.Datasource = dv dtgCusts.DataBind() End Sub |
Sub SortCommand_Click is where we handle the sort order. Normally this subroutine is only a couple lines long. e.SortExpression returns the column name that was clicked on in the datagrid. This is then passed back to the DataView's Sort method to do the sorting. Since, normally, just the column name is passed back, ascending sort is assumed by default. We need a way to add " ASC" or " DESC" to the column name to achieve the effect we want.
At the top of the routine we check to see if e.SortExpression matches the session variable containing the last column clicked on. If they are the same, then we need to reverse the order. We then check the Order session variable. If it is "ASC" we reverse it and append " DESC" to e.SortExpression and vice-versa. If a different column was clicked on we set the order to " ASC" and pass that back to the DataView's Sort method instead. At the end of the routine we update the "Column" session variable so that we are ready for the next column click.
|
Sub SortCommand_Click(sender As Object, e As DataGridSortCommandEventArgs) Handles dtgCusts.SortCommand 'Check to see if same column clicked again If e.SortExpression.ToString() = Session("Column") Then 'Reverse the sort order If Session("Order") = "ASC" Then strOrderBy = e.SortExpression.ToString() & " DESC" Session("Order") = "DESC" Else strOrderBy = e.SortExpression.ToString() & " ASC" Session("Order") = "ASC" End If Else 'Different column selected, so default to ascending order strOrderBy = e.SortExpression.ToString() & " ASC" Session("Order") = "ASC" End If Session("Column") = e.SortExpression.ToString() BindTheData() End Sub End Class |
I hope this has given you another trick for your programming bag. You may find it useful sometime. There may be more elegant ways of accomplishing two-way sorting, but this way is simple and works for me.
You may download the code here.