When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, June 15, 2005

An Extensive Examination of the DataGrid Web Control: Part 18

By Scott Mitchell


The 18th Part in a Multi-Part Series
This article is the eighteenth piece of a multi-part series on using the DataGrid Web control that will span several months. The ASP.NET DataGrid Web control, which displays database information in an HTML table, is highly versatile. The basics of the DataGrid were discussed in Part 1; information on specifying display properties of the DataGrid was discussed in Part 2. In Part 3 we examined how to associate custom events with the DataGrid. In Part 4 we looked at how to extend Part 3 to provide custom sorting on the results of a DataGrid. In Part 5 we examined how to use templates to further customize the DataGrid's appearance. Part 6 examined how to use the DataGrid's built-in editing capabilities, while Part 7 looked at customizing the editing interface using the EditItemTemplate. In Part 8 we looked at how to add client-side code to a ButtonColumn's client-side onclick event. In Part 9 we examined how to enhance the DataGrid's editing interface by having the editing interface's TextBox receive focus when the page is loaded. In Part 10 we looked at how to (automatically) add filtering buttons so that one can filter the data in a DataGrid. In Part 11 we examined how to create a DataGrid Web control with a column of related radio buttons. In Part 12 we examined how to create a sortable DataGrid that can be sorted in ascending and descending order. Part 13 examined how to sum up a DataGrid column and have the sum displayed in the footer. Part 14 looked at how to build a master/detail DataGrid. Part 15 looked at adding paging support to a DataGrid. Part 16 examined how to create an editable DataGrid with two data-dependent DropDownLists. Part 17 looked at building a fully-editable DataGrid. In this eighteenth part we'll examine an alternative approach for creating a bi-directional sortable DataGrid and see how to gussy up the DataGrid to include up and down arrows in the sorted column.

ASP.NET Data Web Controls Kick Start

ASP.NET Data Web Controls Kick Start

ASP.NET Data Web Controls Kick Start is author Scott Mitchell's most recent book, which thoroughly examines three of the most commonly used ASP.NET Web controls: the DataGrid, DataList, and Repeater. These three Web controls can be difficult to master due to their numerous features and capabilities. With this book, you'll quickly become an expert, learning the gritty details and true capabilities of each. This 400+ page book explores the topics in this article series in much greater depth, along with examining various topics and techniques not covered here.

Scott Mitchell is the editor and founder of 4GuysFromRolla.com, author of the An Extensive Examination of the DataGrid Web Control article series, and author of numerous other ASP and ASP.NET books.

[Buy this Book]
[Visit the Book's Companion Web Site]

Introduction


The DataGrid Web control includes a bevy of common features, such as paging, sorting, and row-by-row editing of the DataGrid's underlying data. We've discussed how to accomplish these tasks in previous installments of the An Extensive Examination of the DataGrid Web Control article series, first looking at creating a sortable DataGrid in Part 4. Unfortunately the DataGrid's built-in sorting only allows for uni-directional sorting. That is, when creating the DataGrid you must decide on a column-by-column basis if the data will be sorted in ascending or descending order.

While it's impressive the ease with which uni-directional sorting can be added to a DataGrid, ideally we'd like to offer bi-directional sorting. There are a couple of techniques that can be used to accomplish this end, one of which was discussed in Part 12 of this article series. Specifically, Part 12 showed how to dynamically adjust each DataGrid column's SortExpression property to toggle ascending or descending sorting. One downside of this approach, as Part 12 noted, was that you needed to hard-code in sortable column, mapping the SortExpression to the appropriate DataGridColumns index. This downside of this approach, then, is that it would need to be customized for each page that you wanted to use a bi-directional sortable DataGrid.

In this 18th part of the An Extensive Examination of the DataGrid Web Control article series we'll look at an alternative approach to implementing bi-directional sorting, one that doesn't require any hard-coded mapping and therefore can easily be reused. We'll also look at a simple method that will enhance the appearance of our bi-directional sortable DataGrid, adding little up and down arrows on the column header that the grid's data is sorted by. Read on to learn more! (If you are unfamiliar with creating a sortable DataGrid, please take a moment to first read Part 4 of this article series before continuing; if you have never created a bi-directional sortable DataGrid, be sure to read Part 12 before tackling this part.)

Storing Sorting Information in the ViewState


As you know, in a sortable DataGrid each sortable column has a SortExpression property that is passed to the DataGrid's SortCommand event handler when that particular column's sort heading is clicked. Typically the SortExpression will contain the actual SQL syntax that you want to have injected into the ORDER BY clause. For example, imagine that you were showing employee information in a DataGrid using BoundColumns to display the database fields Name, Salary, and HireDate. In the Salary DataGrid column you could simply use a SortExpression of Salary (or Salary ASC), which would indicate that you want to sort the column by the Salary field in ascending order. If you wanted to sort by salary in descending order you'd simply use Salary DESC as the SortExpression.

This technique works well for creating uni-directional sortable DataGrids. For bi-directional sortable DataGrids, however, we need to be able to dynamically add the DESC or ASC depending on whether or not we want to now sort in ascending or descending order. Part 12 of this article series looked at one technique to implement a bi-directional sortable DataGrid. Specifically, Part 12's logic checked the SortExpression property in the SortCommand event handler. If it ended with ASC it changed the clicked DataGrid column's SortExpression, replacing the ASC with DESC; similarly, if the SortExpression already ended with DESC it was replaced with ASC. While this approach definitely worked, one downside was that in order to set the correct DataGrid column's SortExpression we needed to provide a mapping from the SortExpression property passed in and the corresponding index in the DataGrid's Columns collection. With this hard-coded mapping, the code would have to be customized for each bi-directional sortable DataGrid you created.

A better approach, in my opinion, and the technique I discuss in my book ASP.NET Data Web Controls Kick Start, is to use the ViewState to track both the column to sort by and the direction. This technique involves maintaining two page-level properties which I usually name SortExpression (a string) and SortAscending (a Boolean). These two properties simply use the ViewState StateBag as their backing store (thereby ensuring that the values are remembered across postbacks). Then, in my SortCommand event handler I first check to see if the column the data is currently sorted by has already been clicked again. If so, I toggle the SortAscending property, thereby changing the sort direction. I finish by setting the SortExpression property maintained in ViewState to the SortExpression value passed into the SortCommand event handler.

'The Page-level properties that write to ViewState
Private Property SortExpression() As String
    Get
        Dim o As Object = viewstate("SortExpression")
        If o Is Nothing Then
            Return String.Empty
        Else
            Return o.ToString
        End If
    End Get
    Set(ByVal Value As String)
        viewstate("SortExpression") = Value
    End Set
End Property

Private Property SortAscending() As Boolean
    Get
        Dim o As Object = viewstate("SortAscending")
        If o Is Nothing Then
            Return True
        Else
            Return Convert.ToBoolean(o)
        End If
    End Get
    Set(ByVal Value As Boolean)
        viewstate("SortAscending") = Value
    End Set
End Property



'The SortCommand event handler
Private Sub dgPActivities_SortCommand(ByVal source As Object, _
   ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) _
   Handles dgPActivities.SortCommand
    'Toggle SortAscending if the column that the data was sorted by has
    'been clicked again...
    If e.SortExpression = Me.SortExpression Then 
      SortAscending = Not SortAscending
    Else
      SortAscending = True
    End If
    
    'Set the SortExpression property to the SortExpression passed in
    Me.SortExpression = e.SortExpression

    BindData()  'rebind the DataGrid data
End Sub
[View a Live Demo!]

The BindData() method contains the code that grabs the appropriately-sorted data from the database and binds it to the DataGrid. See Parts 4 or 12 for a description of the BindData() method for a sortable DataGrid.

Improving the Appearance of the Bi-Directional Sortable DataGrid


At this point we have a working bi-directional sortable DataGrid, however there are no visual cues to indicate how the data is sorted. Many websites that offer bi-directional sortable data display a little arrow or icon next to the column that the data is sorted by. What I'd like to show is a simple method that will add a little up or down arrow next to the sorted column, depending on whether the column sorted by is sorted in ascending or descending order.

The following method, UpdateColumnHeaders(DataGrid), takes in as input a DataGrid and iterates through its Columns collection, looking for the DataGrid column by which the data is sorted. Once it finds that DataGrid column is adds to it an image tag of either an up or down arrow, depending on if the data is sorted in ascending or descending order. (The up and down arrows I use in the live demo can be downloaded here: http://aspnet.4guysfromrolla.com/images/up.gif and http://aspnet.4guysfromrolla.com/images/down.gif.) Before adding the up or down arrow, a regular expression is used to strip out any image tag markup that might be present.

Sub UpdateColumnHeaders(ByVal dg As DataGrid)
   Dim c As DataGridColumn
   For Each c In dg.Columns
      'Clear any <img> tags that might be present
      c.HeaderText = Regex.Replace(c.HeaderText, "\s<.*>", String.Empty)

      If c.SortExpression = SortExpression Then
          If SortAscending Then
             c.HeaderText &= " <img src=""/images/up.gif"" border=""0"">"
          Else
             c.HeaderText &= " <img src=""/images/down.gif"" border=""0"">"
          End If
      End If
   Next
End Sub
[View a Live Demo!]

To use this method simply call it from the BindData() method prior to binding the data to the DataGrid. (See the live demo for a complete, working code example.)

Adding Up and Down Arrows Images for the ASP.NET 2.0 GridView Control
For those of you using ASP.NET 2.0, you'll be happy to know that I've written an article showing how to add these up and down arrow images for a sortable GridView. For more information, see: Extending the GridView to Include Sort Arrows.

Conclusion (and Making this Approach Reusable)


In this article we examined an alternative approach for building a bi-directional sortable DataGrid, one that uses two ViewState-backed Page properties to keep track of the column to sort by and whether the data should be sorted in ascending or descending order. Along with this we looked at a simple, generic method that can be called to add an up or down arrow in the DataGrid column by which the data is sorted.

At the beginning of this article I mentioned my preference for using ViewState to implement a bi-directional sortable DataGrid because it keeps the code for implementing the sort functionality loosely coupled from the data being bound to the DataGrid (whereas the approach discussed in Part 12 had the information tightly bound). Furthermore, the astute reader will notice that I made the UpdateColumnHeaders(DataGrid) generic as well - that is, it will work with any DataGrid you pass in, there's no coupling between the code and the specifics of a DataGrid.

Given this you could easily move the sorting properties and UpdateColumnHeaders(DataGrid) method to a custom base class. If you have a page, then, that needs to provide a bi-directional sortable DataGrid you simply have that page inherit from the custom base class page. With a bit of refactoring of the BindData() method and SortCommand event handler you could end up with a means to create a bi-directional sortable DataGrid with just a couple lines of code. I leave this migration to a base class and the necessary refactoring as an exercise for the interested reader. (For more information on custom base classes be sure to read Using a Custom Base Class for your ASP.NET Page's Code-Behind Classes.)

Happy Programming!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article