Introduction
The ASP.NET version 3.5 ListView
provides developers with a much needed breath of fresh air with respect to simplifying HTML complexity when a data bound grid control is needed. The ListView
enables developers to have full control over generated HTML, yet have simplified data binding, custom paging, and column sorting features. While column sorting is provided with ListView
, a clear indication as to which column has been most recently sorted is not provided. There are many techniques on the Internet for providing DataGrid
and GridView
column sort indicators. The purpose of this posting is to provide a custom control for providing a ListView
column sort indicator.
Using the code
This ListView
column sort indicator consists of two custom controls; a ListViewSort
custom control, which inherits from ListView
, and a ListViewSortColumnHeader
composite custom control. The ListViewSortColumnHeader
control is used when defining each sortable header within the ListView
LayoutTemplate
. The ListViewSort
custom control is used in place of the ListView
ASP.NET control, and exposes the following extension public properties:
ImageUrlAscending
- The image file which is used to represent an ascending sort direction in the active sorted header. If omitted, an embedded web resource is used as the default.ImageUrlDescending
- The image file which is used to represent a descending sort direction in the active sorted header. If omitted, an embedded web resource is used as the default.SortExpressionDefault
- The name of the data element which is the default sort expression.SortDirectionDefault
- The initial sort direction when a header is sorted.
Other than the above extension public properties, the ListViewSort
is identical to the ListView
, illustrated as follows:
1: <myControls:ListViewSort ID="listViewSort"
2: DataSourceID="ObjMenu"
3: DataKeyNames="Name"
4: SortExpressionDefault="Name"
5: SortDirectionDefault="Ascending"
6: runat="server">
7: <LayoutTemplate>
8: <table runat="server"
9: class="listViewGrid"
10: cellspacing="0"
11: border="0">
12: <tr>
13: <th>
14: <myControls:ListViewSortColumnHeader runat="server"
15: Key="Name"
16: Text="Food Name" />
17: </th>
18: <th>
19: <myControls:ListViewSortColumnHeader runat="server"
20: Key="Price"
21: Text="Price" />
22: </th>
23: <th>
24: <myControls:ListViewSortColumnHeader runat="server"
25: Key="Description"
26: Text="Description" />
27: </th>
28: <th>
29: <myControls:ListViewSortColumnHeader runat="server"
30: Key="Calories"
31: Text="Calories" />
32: </th>
33: </tr>
34:
35: <tr runat="server" id="itemPlaceholder" />
36:
37: </table>
38: <asp:DataPager ID="dataPager" runat="server">
39: <Fields>
40: <asp:NumericPagerField ButtonCount="10"
41: NextPageText="..."
42: PreviousPageText="..." />
43: </Fields>
44: </asp:DataPager>
45: </LayoutTemplate>
46: <ItemTemplate>
47: <tr class="<%# ((ListViewDataItem)Container).DisplayIndex % 2 == 0 ?
"itemRow" : "altItemRow" %>">
The ListViewSortColumnHeader
composite control is used in place of a HyperLink
ASP.NET control, normally used to activate column sorting. ListViewSortColumnHeader
exposes the Key
and Text
properties. The Key
property associates the header with a databound expression, while the Text
property provides for the actual text being displayed in the header. The ListViewSortColumnHeader
control essentially generates the asp:HyperLink
control and an asp:PlaceHolder
control for an anticipated asp:Image
control whenever the header participates in a sorting operation.
The ListViewSort
custom control overrides a single event from the inherited ListView
control, OnDataBound
, illustrated as follows:
1: protected override void OnDataBound(EventArgs e)
2: {
3: if (base.SortExpression.Length == 0)
4: {
5: if (SortExpressionDefault.Length > 0)
6: {
7: base.Sort(SortExpressionDefault, SortDirectionDefault);
8: }
9: }
10:
11: List<Control> controls = Helpers.GetControlsByType(this,
typeof(ListViewSortColumnHeader));
12: foreach (Control control in controls)
13: {
14: ListViewSortColumnHeader header = (ListViewSortColumnHeader)control;
15: if (header.HasSortDirectionIndicator() == true)
16: {
17: header.ResetSortDirectionIndicator();
18: }
19: }
20:
21: foreach (Control control in controls)
22: {
23: ListViewSortColumnHeader header = (ListViewSortColumnHeader)control;
24: if (header.Key == base.SortExpression)
25: {
26: header.SetSortDirectionIndicator(base.SortExpression,
base.SortDirection);
27: break;
28: }
29: }
30:
31: base.OnDataBound(e);
32: }
During the ListViewSort
OnDataBound
event processing, the existing ListViewSort
headers are examined and any existing sort direction indicator asp:Image
controls are removed, and then the appropriate sort direction indicator asp:Image
control is injected into the new header being sorted. With the exception of maintaining the four ListViewSort
extension public properties within ViewState, that is essentially all that the ListViewSort
does. This level of simplicity ensures that the sort direction indicator logic does not need to work its way into your application for each and every web page which uses a ListView
. A sample ListViewSort
output is illustrated. In this illustration (and the related project demo file), any of the headers can be clicked and the table data will be sorted in either ascending or descending order.
The project demo file for the above sample HTML and the code above also demonstrates the usage of an ASP.NET ObjectDataSource
control, enabled for custom paging, to ensure that only the currently displayed ListViewSort
data is maintained within ViewState at any point in time.
History
- 13-May-2008 - Initial release.