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

Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Stump the SQL Guru!
Web Hosts
Author an Article

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

Creating a Repeater that Supports Pagination and Sorting

By Rachael Schoenbaum


ASP.NET ships with a number of controls designed for displaying data, such as the DataGrid, DataList, and Repeater. While the DataGrid is, by far, the most robust of the three data Web controls, the DataGrid's layout of its data is fairly rigid. That is, with a DataGrid each record in the DataSource is going to be rendered as a single row in a table, with each field as a table column. On the other end of the spectrum the Repeater control allows complete and total control of the rendered output, but is lacking the advanced features inherent in the DataGrid, such as sorting and paging of the underlying data. (For a more detailed discussion on the trade offs of each of the three data Web controls be sure to read Scott Mitchell's article, Deciding When to Use the DataGrid, DataList, or Repeater.)

After encountering a number of project requirements where I needed both the rendering flexibility of the Repeater and the sorting and paging features of the DataGrid, I decided to create a custom, compiled Web control that would marry the flexibility of the Repeater with the functionality of the DataGrid. In this article we'll examine this control of mine, SortablePaginationRepeater, and see how to extend the Repeater to provide pagination and sorting. (Take a moment to view a live demo of the control we'll be creating...)

- continued -

Extending .NET Classes

Extending a class in .NET is basically like saying:
I really like the functionality of this class, but it's missing a few things and/or doing a few things wrong for my needs. I don't want to attempt to re-write the functionality of the entire class, I only want to change the pieces that don't work for me.
When you extend a class, you get access to all of its original public and protected members and are allowed to override the ones you need to change. You can also add new functionality that the original never had in the first place. This gives you a lot of freedom to use classes that come natively in .NET to provide the basic structure for the functionality you want to create, without having to write it from scratch. There are a number of articles here on 4Guys that illustrate how to extend an existing Web control: Extending a class in .NET in code is really quite easy - just add the Inherits keyword to your class's definition, specifying the class to extend. For example, to create a class named SortablePaginationRepeater that extends the Repeater class, you would use the following syntax for the class's definition:

Public Class SortablePaginationRepeater : Inherits Repeater

Note: You can also put the Inherits keyword on the line following the class declaration (thereby removing the colon as well).

In order to enhance the Repeater to support paging and sorting we'll create a new class that uses the Repeater as the base class. The new class, by default, will contain the complete functionality of the Repeater control; we'll add our own properties, methods, and event handlers or override the Repeater's in order to add the necessary functionality for sorting and paging.

Step 1: Adding Properties to the Control

When extending an existing control, oftentimes you'll need to add some new properties that capture information important to the extended control's new functionality. For example, our control is going to need a way for a page developer to pass in information regarding how the data should be sorted, how many records to show per page, and so on. When adding properties to a Web control it is important to use the ViewState collection so that any values changed programmatically by the page developer persist across postbacks. Here is an example of the property syntax utilizing ViewState as a backing store:

Public Property SortBy() As String
      If obj Is Nothing Then
         Return vbNullString
         _Return Ctype(ViewState("SortBy"), String)
      End If
   End Get
   Set(ByVal arg As String)
      ViewState("SortBy") = arg
   End Set
End Property

The following properties are available in the SortablePaginationRepeater control:

  • PageLocation – this defines where the pagination controls appear: at the top of the page, bottom of the page, or both.
  • PagerStyle – this allows the user to define the type of pagination controls that appear: Dropdown, NumericPages, NextPrev, or TextBox.
  • PageSize – the number of records that appear per page
  • PageButtonCount – used only for PagerStyle.NumericPages, this defines the number of page buttons that appear
  • CurrentPageIndex – the current page to display
  • SortBy – a string containing the column and direction to sort by
  • TableWidth – the width the table containing the pagination controls is; this can be expressed as a whole number or percentage
  • GoButtonCssClass – used only for PagerStyle.TextBox, this defines the CSS class for the button
  • SortColumn – stores the information that is used for the sorting control

Setting Up the Object for Pagination

.NET comes with a native object called the PagedDataSource, which provides a really convenient way to page through data. The PagedDataSource class has a DataSource property that should be assigned the data to page through. In addition, the PagedDataSource class contains properties to specify the number of records per page and the current page you want to display. The PagedDataSource can then be bound to a data Web control and the appropriate subset of records will be displayed. To provide paging in our control, then, instead of using the DataSource the page developer passes in, we will internally use a PagedDataSource. Here's an example of how this is done:

Public Overrides Sub DataBind()

  ' Test for type of data source.  
  If TypeOf DataSource Is System.Collections.IEnumerable Then

    _PagedDataSource.DataSource = DataSource

  ElseIf TypeOf DataSource Is System.Data.DataView Then
    Dim data As DataView = CType(DataSource, DataView)
    _PagedDataSource.DataSource = data.Table.Rows()

  ElseIf TypeOf DataSource Is System.Data.DataTable Then
    Dim data As DataTable = CType(DataSource, DataTable)
    _PagedDataSource.DataSource = data.DefaultView()

  ElseIf TypeOf DataSource Is System.Data.DataSet Then

    Dim data As DataSet = CType(DataSource, DataSet)

    ' Test if DataMember provided.  If not, default to the 0th table in the set
    If DataMember <> vbNullString AndAlso data.Tables.Contains(DataMember) Then
        _PagedDataSource.DataSource = data.Tables(DataMember).DefaultView()
    ElseIf data.Tables.Count > 0 Then
        _PagedDataSource.DataSource = data.Tables(0).DefaultView()
        Throw New SortablePaginationException("DataSet doesn't have any tables.")
    End If

    Throw New SortablePaginationException("DataSource must be of type " & _ 
"System.Collections.IEnumerable.  The DataSource you provided is of type " & _

  End If

  'Set the page size as provided by the consumer
  _PagedDataSource.PageSize = Me.PageSize

  'Insure that the page doesn't exceed the maximum number of pages 
  If Me.CurrentPageIndex >= _PagedDataSource.PageCount Then
    Me.CurrentPageIndex = _PagedDataSource.PageCount - 1
  End If

  _PagedDataSource.CurrentPageIndex = Me.CurrentPageIndex

  MyBase.DataSource = _PagedDataSource

End Sub

You'll notice that not every data type can be converted into a PagedDataSource, hence the exception that is thrown. Only enumerable objects (those capable of being counted or indexed) can be assigned as a DataSource for the PagedDataSource. There are a couple of exceptions - namely DataViews, DataTables, and DataSets - that may not be enumerable themselves but have properties that are. In this case, we set the DataSource to the enumerable property of the object.

Another interesting thing to note is how DataSets get used. The Repeater has a native property called DataMember. This property allows you to specify a particular DataTable of the DataSource to use. If the DataMember property is not provided, the object uses the first table in the index of tables. (For more information on the PagedDataSource, see Harrison Enholm's article, Adding Paging Support to the Repeater or DataList with the PagedDataSource Class.)

Now that we've looked at how to implement paging, we're ready to turn our attention to the steps necessary to add sorting support. In Part 2 we'll examine the steps taken to provide sorting support as well as see the control used in an ASP.NET page.

  • Read Part 2!

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