Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Repeater with Paging: Performing Postback on a Custom Control

2.71/5 (4 votes)
23 Aug 2007CPOL3 min read 1   150  
Repeater with paging: a custom ASP.NET control.

Screenshot - repeater-with-paging1.gif

Screenshot - repeater-with-paging2.gif

Introduction

With the out-of-the-box ASP.NET DataGrid or GridView, it's very easy to control data with paging. However, the weakness is you have to bind all data in order to make the paging to work. It's not practical. Let's say you have 1,000,000 number of data rows and you want to display only 25 per page, you will not want to bind the whole 1,000,000 data rows just for making the paging to work.

This control that I wrote inherits from Repeater, and I added a Literal control for the paging. This control also implements IPostBackEventHandler, which allows you to perform postback to the server (used by the Literal for the paging). This control allows you to bind only the data that you want to display to the user, but also makes the paging to work.

Background

This article is only for intermediate-advanced ASP.NET developers who have had experience in creating custom controls. The files attached are .vb files which you need to add to your own project. I will not explain how to create a Class Library project in Visual Studio, etc.

This control will use a custom EventArgs and delegates and events. If you're not familiar with these, you may get confused.

Using the Code

From the file attachment, RepeaterWithPaging.vb.

  1. Add a reference to System.Web.
  2. Add the Imports declarations.
  3. VB
    Imports System.Collections.Generic
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
  4. Inherit from Repeater and implement IPostBackEventHandler to allow postback.
  5. VB
    Public Class RepeaterWithPaging _
        Inherits Repeater _
        Implements IPostBackEventHandler
  6. Create the required class variables and properties.
  7. VB
    #Region "Class Variables"
        Private litPaging As Literal 'THE LITERAL CONTROL FOR PAGING
        Private intNumberOfData As Integer
        Private intNumberPerPage As Integer
        Private intCurrentPageNumber As Integer
        Private strPagingCssClass As String
        Public Event PagingClicked As PagingLiteralEventHandler
    #End Region
    
    #Region "Public Properties"
        'Used by the paging literal to display the page number from 1 to x
        'depending on the number of data specified here.
        Public Property NumberOfData() As Integer    
            Get
                Return intNumberOfData
            End Get
            Set(ByVal Value As Integer)
                intNumberOfData = Value
            End Set
        End Property
    
        'The number of data displayed per page, used by paging literal as well.
        Public Property NumberPerPage() As Integer
            Get
                Return intNumberPerPage
            End Get
            Set(ByVal Value As Integer)
                intNumberPerPage = Value
            End Set
        End Property
    
        'Current page viewed.
        Public Property CurrentPageNumber() As Integer
            Get
                Return Me.intCurrentPageNumber
            End Get
            Set(ByVal value As Integer)
                Me.intCurrentPageNumber = value
            End Set
        End Property
    
        'The CSS class for the paging literal
        Public Property PagingCssClass() As String
            Get
                Return Me.strPagingCssClass
            End Get
            Set(ByVal value As String)
                Me.strPagingCssClass = value
            End Set
        End Property
    #End Region
  8. Implement the required method from IPostBackEventHandler. This method is called when the postback is triggered by the paging. I'll explain this later.
  9. VB
    Public Sub RaisePostBackEvent(ByVal eventArgument As String) _
         Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
    End Sub
  10. Create a delegate for handling the postback event by the paging literal.
  11. VB
    Public Delegate Sub PagingLiteralEventHandler(ByVal sender As Object, _
                    ByVal ev As PagingLiteralEventArgs)
  12. Create an event based on that delegate.
  13. VB
    Public Event PagingClicked As PagingLiteralEventHandler
  14. The PagingLiteralEventArgs class is defined in the file PagingLiteralEventArgs.vb. This file inherits from the EventArgs class, and it has a public property CurrentPage. Using EventArgs, you can pass arguments. You can add as many arguments as you want, but for the paging literal control to work, we only need the CurrentPage property which we use to get the current page number viewed by the user.
  15. VB
    Public Class PagingLiteralEventArgs
        Inherits EventArgs
    
    #Region "Class Variables"
        Private intCurrentPage As Integer
    #End Region
    
    #Region "Public Properties"
        Public Property CurrentPage() As Integer
            Get
                Return intCurrentPage
            End Get
            Set(ByVal Value As Integer)
                intCurrentPage = Value
            End Set
        End Property
    #End Region
    
    End Class
  16. Back to RepeaterWithPaging.vb. We now need to initialize the Literal for paging. Let's override the OnInit method from the base class, and also, when the page is not posting back, we set the current page number to 1.
  17. VB
    Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
        MyBase.OnInit(e)
    
        litPaging = New Literal
        Me.Controls.Add(litPaging) 'Add to control collection
    
        If Not Me.Page.IsPostBack Then
            Me.intCurrentPageNumber = 1
        End If
    End Sub
  18. Populate the paging literal. I want to stress out this method:
  19. VB
    Me.Page.ClientScript.GetPostBackEventReference(Me, i)

    This method is the one that triggers the postback! You can add this method as a JavaScript call, and if you View Source in Internet Explorer or Firefox, you can see that it renders as _doPostBack(). This method passes two input parameters: the calling control and the argument. I pass Me as the control and the page number (denoted by "i" - see the method below) to pass the clicked page number as the argument.

    This will then be captured by this method implemented from the interface explained earlier:

    VB
    RaisePostBackEvent(ByVal eventArgument As String)

    The eventArgument variable will contain the argument passed.

    VB
    Private Sub PopulatePaging()
        'Number of pages is obtained by dividing number of data with number per page
        Dim intNoOfPages As Integer = Me.NumberOfData / Me.NumberPerPage
        
    
    
        'If there is still extra data
        'e.g Number of data is 303 and number per page is 100
    
        'there are still 3 items left after page 3, so add page by 1.
        If Me.NumberOfData Mod Me.NumberPerPage > 0 Then
            intNoOfPages += 1
        End If
    
        'Display paging from 1 to number of pages
        For i As Integer = 1 To intNoOfPages
            'If user navigates to the current page, make it bold.
            If i = Me.intCurrentPageNumber Then
                Me.litPaging.Text &= "<a class=""" & _
                       Me.PagingCssClass & """ href=""#"" onclick=""" & _
                       Me.Page.ClientScript.GetPostBackEventReference(Me, i) & _
                       """><b>" & i & "</b></a> | "
            Else
                'Make it normal
                Me.litPaging.Text &= "<a class=""" & Me.PagingCssClass & _
                        """ href=""#"" onclick=""" & _
                        Me.Page.ClientScript.GetPostBackEventReference(Me, i) & """>" & _
                    i & "</a> | "
            End If
        Next
    End Sub
  20. Within RaisePostBackEvent(), trigger the PagingClicked event we declares previously. It means that when the text is clicked on the paging literal, the PagingClicked event is fired. We then pass in the page number argument that is passed through the eventArgument variable.
  21. VB
    Public Sub RaisePostBackEvent(ByVal eventArgument As String) _
           Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
    
    
        'This is the power of custom EventArgs, you can pass it as an argument
        Dim objEventArgs As New PagingLiteralEventArgs
        objEventArgs.CurrentPage = CInt(eventArgument)
        Me.intCurrentPageNumber = eventArgument
    
        'Raise the event with passing the custom PagingLiteralEventArgs
        RaiseEvent PagingClicked(Me, objEventArgs)
    End Sub
  22. Render both the Repeater and the Literal.
  23. VB
    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        MyBase.Render(writer)
    
        
        writer.Write("<p/>")
        
        Me.PopulatePaging()
        Me.litPaging.RenderControl(writer)
    End Sub

That's it! Now, let's go to the front end ASPX page.

Front-End

  1. Register your custom control.
  2. ASP.NET
    <%@ Register TagPrefix="CRE" Namespace="ContentReadyEnterprise.Web.Controls" 
        Assembly="ContentReadyEnterprise.Web.Controls" %> 
  3. Declare your custom repeater as a normal repeater, but note the custom properties and the event we created earlier. When you create a new event based on a custom delegate (in this case, PagingClicked), Visual Studio automatically adds the "On" word in front of it! Pretty good! When you view the properties of the Repeater from the ASPX, you can see the OnPagingClicked event is there!
  4. ASP.NET
    <CRE:RepeaterWithPaging ID="rptTest" runat="server" 
          OnPagingClicked="Paging_Clicked" 
          NumberOfData="100" NumberPerPage="10">
        <ItemTemplate>
            <%#Container.DataItem%>
            <br />
        </ItemTemplate>
    </CRE:RepeaterWithPaging>
  5. On the code-behind, let's capture the Paging_Clicked event.
  6. VB
    Protected Sub Paging_Clicked(ByVal sender As Object, ByVal ev As PagingLiteralEventArgs)
        Response.Write("I click page number: " & ev.CurrentPage.ToString())
    End Sub
  7. Bind the test data and test the paging.
  8. VB
    Protected Sub Page_Load(ByVal sender As Object, _
                  ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            Me.GetTestData()
        End If
    End Sub
    
    'Capture paging event    
    Protected Sub Paging_Clicked(ByVal sender As Object, _
                  ByVal ev As PagingLiteralEventArgs)
        Me.GetTestData()
    End Sub
    
    'You can write your own method here.
    Private Sub GetTestData()
        Dim alistTest As New List(Of String)
        Dim intStartNumber As Integer = _
            rptTest.CurrentPageNumber * rptTest.NumberPerPage
    
        If rptTest.CurrentPageNumber = 1 Then
            intStartNumber = 1
        End If
    
        Dim intEndNumber As Integer = intStartNumber + rptTest.NumberPerPage
        
        For i As Integer = intStartNumber To intEndNumber
            alistTest.Add(i)
        Next
    
        rptTest.DataSource = alistTest
        rptTest.DataBind()
    End Sub

That's it guys!

Points of Interest

It's very interesting to see how easy it is to make a control that can do postback.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)