When you think ASP, think...
Recent Articles xml
All Articles
ASP.NET Articles
Related Web Technologies
User Tips!
Coding Tips
spgif spgif

Book Reviews
Sample Chapters
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Stump the SQL Guru!
Web Hosts
Author an Article
spgif spgif

ASP ASP.NET ASP FAQs Feedback topnav-right
Print this Page!
Published: Wednesday, February 9, 2005

Creating a Repeater that Supports Pagination and Sorting, Part 2

By Rachael Schoenbaum

  • Read Part 1

  • 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:

    <CustomWebControls:SortablePaginationRepeater Id="MyRepeater" runat="server" ...>
        <SortColumn ColumnName="LastName, FistName" DisplayName="User Name" />
        <SortColumn ColumnName="Email" DisplayName="E-mail Address" />
        <SortColumn ColumnName="LastLogin" DisplayName="Last Login Date" />

    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:

    1. Require a postback to the server, which will requery the data in resorted order, resending the sorted content back to the client, or
    2. 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:
    1. 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.
    2. 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)    
        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)
       'Add in column for sorting, if necessary
       If _SortList.Count > 1 Then
          _TableCell = New 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
       'Add cell to the row
       'Add row to table
       'Display the pagination controls
       If Me.PageLocation <> PagerPosition.Bottom Then
       End If
       'Display the repeater
       'Display the pagination controls
       If Me.PageLocation <> PagerPosition.Top Then
       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.

    <%@ Register TagPrefix="CustomWebControls" 
                    Assembly="CustomWebControls" %>
    <form id="MyForm" runat="server">
      <CustomWebControls:SortablePaginationRepeater Id="MyRepeater" 
             runat="server" PageSize="10" PageButtonCount="5" 
             PageLocation="TopAndBottom" TableWidth="100%" 
             PagerStyle="NumericPages" DataSource="MyDataSource">
         <SortColumn ColumnName="LastName, FistName" DisplayName="User Name" />
         <SortColumn ColumnName="Email" DisplayName="E-mail Address" />
         <SortColumn ColumnName="LastLogin" DisplayName="Last Login Date" />
         <!-- Note that the rest of this control looks 
                 exactly like a normal repeater -->
         <Header Template>
                <th>User Name</th>
                <th>E-mail Address</th>
                <th>Last Login Date</th>
              <td><%# DataBinder.Eval(Container.DataItem, "FirstName") & " " & _
                       DataBinder.Eval(Container.DataItem, "LastName") %></td>
              <td><%# DataBinder.Eval(Container.DataItem,"Email")%></td>
              <td><%# DataBinder.Eval(Container.DataItem,"LastLogin")%>
    [View a Live Demo!]

    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.

    Happy Programming!

  • By Rachael Schoenbaum


  • Download the complete code (in ZIP format)
  • View a Live Demo
  • 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.

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