In Part 1 we started our overview of the SortablePaginationRepeater control, examining
the added properties and how to add paging support. In this final part of the article we'll see how to add sorting support
and look at an example of the pageable, sortable Repeater in an ASP.NET Web page.
Setting Up the Object for Sorting
To provide sorting the page developer will need to specify what columns are sortable and how these sortable columns should be
displayed in the Repeater. They'll do this through markup in the SortablePaginationRepeater's declarative syntax. For
example, when creating a SortablePaginationRepeater that has three sortable columns the declarative syntax might look like:
In order to achieve this desired declarative syntax, the first thing we need is a separate class used to define the tag
that contains the sorting information (i.e., <SortColumn>). The class is
comprised of two string properties, ColumnName and DisplayName. The
ColumnName property provides the name (and direction, if necessary) that the results should
be sorted by. The DisplayName is the text that should appear to the end user.
There are two fundamental ways to sort data in a Web page:
Require a postback to the server, which will requery the data in resorted order, resending the sorted content back
to the client, or
Perform the sorting on the client using client-side script. This entails having the complete contents being paged through
available on the client through hidden form fields or hidden HTML sections, and having the ability to show/hide/reorder the
data on the fly with client-side techniques. (For example, the 4Guys article Paging
Records on the Client shows how to accomplish complete, client-side paging in classic ASP.)
The SortablePaginationRepeater uses the former approach, requiring a postback every time the user wants to resort the
data.
Displaying the Pagination and Sorting Controls
Once the SortablePaginationRepeater has a paginated data source and sorting is in place, we must display the various
pagination and sorting controls. Displaying the controls is comprised of two parts:
Register the Javascript code – the control uses some client-side JavaScript code to change the current page index
or sorting column and direction, and then submit the form. This registration of the JavaScript routines is done in the
SortablePaginationRepeater class's OnPreRender method.
Create the Paging/Sorting Controls – the user interface used to change the page the user is on must be created and
added to the SortablePaginationRepeater's control hierarchy. This is done in the Render method.
Examining the OnPreRender Method
The OnPreRender method fires during a control's PreRender stage, and is intended to be used to
emit client-side JavaScript. In the SortablePaginationRepeater class's OnPreRender method we register the needed
JavaScript code blocks and then call the base class's OnPreRender() method. Calling the base class's OnPreRender()
method ensures that the base class (the Repeater class, for our control) gets an opportunity to run the code associated with
its OnPreRender() method.
Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs)
MyBase.OnPreRender(e)
If Not Page Is Nothing Then
'Add hidden fields used to store the next page the user wants to visit
'Note that the __NEXTPAGE value could be a previous page or a next page
Page.RegisterHiddenField("__NEXTPAGE", "")
Page.RegisterHiddenField("__SORTBY", "")
'Add javascript used for pagination
If Not Page.IsClientScriptBlockRegistered("Paginate") Then
Page.RegisterClientScriptBlock("Paginate", _
"<script language=""javascript"">" & vbCrLf & _
"<!--" & vbCrLf & _
" function __doPaginate () {" & vbCrLf & _
" // Javascript pagination logic" & vbCrLf & _
" }" & vbCrLf & _
"// -->" & vbCrLf & _
"</script>" & vbCrLf)
End If
'Add javascript used for sorting
If _SortList.Count > 1 Then
If Not Page.IsClientScriptBlockRegistered("Sort") Then
Page.RegisterClientScriptBlock("Sort", _
"<script language=""javascript"">" & vbCrLf & _
"<!--" & vbCrLf & _
" function __doSort () {" & vbCrLf & _
" // Javascript sort logic" & vbCrLf & _
" }" & vbCrLf & _
"// -->" & vbCrLf & _
"</script>" & vbCrLf)
End If
End If
End If
End Sub
Note that we register not only the Javascript code block that is used by the pagination controls, but also the hidden
fields used to store the page the user wants to navigate to.
Rendering the Control
Each time an ASP.NET page is requested, be it on the first visit or on subsequent postbacks, the controls that makeup the page
are rendered. Rendering is the process of generating the appropriate HTML markup for each control. For the SortablePaginationRepeater
control the markup that needs to be generated includes not only the base Repeater, but also the paging and sorting UI elements.
Generating markup in a server control is not as easy as just squirting out one big HTML string. Rather, we create instances
of the classes that correspond to the HTML elements we want displayed and add these to the server control's Controls
collection. The actual generation of HTML markup is performed for us, behind the scenes.
Here's a snippet of code for rendering an HTML table by creating a Table class instance:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim _Table As Table
Dim _TableRow As TableRow
Dim _TableCell As TableCell
Dim PageLoop As Integer
Dim PageTable As Table
Dim PageRow As TableRow
Dim PageCell As TableCell
_Table = New Table
_Table.Width = Me.TableWidth
_Table.CellPadding = 1
_Table.CellSpacing = 2
_TableRow = New TableRow
'Add left cell, which contains "Page x of y"
_TableCell = New TableCell
_TableCell.Width = New Unit(100D, UnitType.Percentage)
_TableCell.Controls.Add(_PageLabel)
_TableRow.Cells.Add(_TableCell)
'Add in column for sorting, if necessary
If _SortList.Count > 1 Then
_TableCell = New TableCell
_TableCell.Controls.Add(_SortDropDown)
_TableRow.Cells.Add(_TableCell)
End If
'Create right cell, which contains pagination controls
_TableCell = New TableCell
_TableCell.HorizontalAlign = HorizontalAlign.Right
'Create table to store pagination controls
PageTable = New Table
PageTable.CellSpacing = 1
PageTable.CellPadding = 2
PageRow = New TableRow
'...Removed for brevity, logic to defined how the
' pagination controls are displayed...
'Add pagination table to the table cell
_TableCell.Controls.Add(PageTable)
'Add cell to the row
_TableRow.Cells.Add(_TableCell)
'Add row to table
_Table.Rows.Add(_TableRow)
'Display the pagination controls
If Me.PageLocation <> PagerPosition.Bottom Then
_Table.RenderControl(writer)
End If
'Display the repeater
MyBase.Render(writer)
'Display the pagination controls
If Me.PageLocation <> PagerPosition.Top Then
_Table.RenderControl(writer)
End If
End Sub
Note the last 15 or so lines of code in the above subroutine. Everything prior to that sets up the HTML that will be
displayed. After the controls are put into HTML objects, the Render() method determines if that HTML should
be displayed above the repeater or below the Repeater.
Perhaps the most interesting thing of all is that the while the controls require a special rendering, the Repeater
itself is rendered as-is, using the native implementation (i.e., via the call to MyBase.Render()). By
converting the DataSource provided to a PagedDataSource, .NET inherently provides the logic
necessary to display only the page in question.
Using the SortablePaginationRepeater Control in an ASP.NET Web Page
To use the control in an ASP.NET page, you must first register it. This is a similar concept to registering a user control.
After the @Page declaration, add the following line:
<%@ Register TagPrefix="CustomWebControls" Namespace="Namespace Of Control" Assembly="Name of DLL" %>
To call the control in your ASP.NET page, make sure you use the tag prefix you defined when you registered the control and
you should use the name of class after the colon. See below for an example.
Note that by supplying the sort column tags, you are telling the control to include a sort control. If you don't provide
this tag, there will be no sort control. Also note that it is possible to provide values for all the other public
properties, even though they may not be shown in this example. By not providing the value, you accept the default value
defined in the control's constructor.
About the Author
Rachael Schoenbaum is a developer specializing in ASP, ASP.NET, Visual Basic, SQL Server, XML, and related technologies.
She consults for Lucidea and has been programming since 1999.