65.9K
CodeProject 正在变化。 阅读更多。
Home

带分页的 Repeater: 在自定义控件上执行 Postback

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.71/5 (4投票s)

2007年8月23日

CPOL

3分钟阅读

viewsIcon

45692

downloadIcon

168

带分页的 Repeater:一个自定义 ASP.NET 控件。

Screenshot - repeater-with-paging1.gif

Screenshot - repeater-with-paging2.gif

引言

使用现成的 ASP.NET DataGridGridView,可以非常方便地实现数据分页。然而,它们的缺点是您必须绑定 **所有** 数据才能使分页生效。这并不实用。假设您有 1,000,000 条数据,并且只想每页显示 25 条,您肯定不希望仅仅为了实现分页而绑定全部 1,000,000 条数据。

我编写的这个控件继承自 Repeater,并且我添加了一个 Literal 控件用于分页。该控件还实现了 IPostBackEventHandler 接口,这允许您执行服务器回发(Literal 用于分页时会用到)。该控件允许您只绑定想要显示给用户的数据,同时也能实现分页功能。

背景

本文档仅面向有自定义控件创建经验的中高级 ASP.NET 开发人员。提供的文件是 .vb 文件,您需要将它们添加到自己的项目中。我 **不会** 解释如何在 Visual Studio 中创建类库项目等内容。

该控件将使用自定义的 EventArgs、委托和事件。如果您不熟悉这些概念,可能会感到困惑。

Using the Code

从附件文件 RepeaterWithPaging.vb 中。

  1. 添加对 System.Web 的引用。
  2. 添加 Imports 声明。
  3. Imports System.Collections.Generic
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
  4. 继承自 Repeater 并实现 IPostBackEventHandler 以允许回发。
  5. Public Class RepeaterWithPaging _
        Inherits Repeater _
        Implements IPostBackEventHandler
  6. 创建所需的类变量和属性。
  7. #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. 实现 IPostBackEventHandler 所需的方法。当分页触发回发时,会调用此方法。我稍后会解释这一点。
  9. Public Sub RaisePostBackEvent(ByVal eventArgument As String) _
         Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
    End Sub
  10. 创建一个委托,用于处理分页 Literal 触发的回发事件。
  11. Public Delegate Sub PagingLiteralEventHandler(ByVal sender As Object, _
                    ByVal ev As PagingLiteralEventArgs)
  12. 基于该委托创建一个事件。
  13. Public Event PagingClicked As PagingLiteralEventHandler
  14. PagingLiteralEventArgs 类定义在文件 PagingLiteralEventArgs.vb 中。该文件继承自 EventArgs 类,并具有一个公共属性 CurrentPage。使用 EventArgs,您可以传递参数。您可以添加任意数量的参数,但对于分页 Literal 控件正常工作,我们只需要 CurrentPage 属性,用于获取用户正在查看的当前页码。
  15. 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. 回到 RepeaterWithPaging.vb。现在我们需要初始化用于分页的 Literal 控件。我们重写基类的 OnInit 方法,并且当页面不是回发时,我们将当前页码设置为 1。
  17. 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. 填充分页 Literal。我想要强调这个方法
  19. Me.Page.ClientScript.GetPostBackEventReference(Me, i)

    这个方法是触发回发的关键!您可以将此方法添加为 JavaScript 调用,如果您在 Internet Explorer 或 Firefox 中查看源代码,可以看到它会渲染为 _doPostBack()。此方法传递两个输入参数:调用控件和参数。我将 Me 作为控件,并将页码(由“i”表示 - 请参见下面的方法)作为参数传递点击的页码。

    这将被前面解释的接口实现的方法捕获

    RaisePostBackEvent(ByVal eventArgument As String)

    eventArgument 变量将包含传递过来的参数。

    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. RaisePostBackEvent() 中,触发我们之前声明的 PagingClicked 事件。这意味着当分页 Literal 上的文本被点击时,PagingClicked 事件就会被触发。然后我们将通过 eventArgument 变量传递过来的页码参数传入。
  21. 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. 渲染 RepeaterLiteral
  23. 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

就是这样!现在,让我们转到前端 ASPX 页面。

前端

  1. 注册您的自定义控件。
  2. <%@ Register TagPrefix="CRE" Namespace="ContentReadyEnterprise.Web.Controls" 
        Assembly="ContentReadyEnterprise.Web.Controls" %> 
  3. 像普通 Repeater 一样声明您的自定义 Repeater,但请注意我们之前创建的自定义属性和事件。当您基于自定义委托(在本例中为 PagingClicked)创建新事件时,Visual Studio 会自动在其前面添加“On”前缀!这很棒!当您在 ASPX 中查看 Repeater 的属性时,可以看到 OnPagingClicked 事件就在那里!
  4. <CRE:RepeaterWithPaging ID="rptTest" runat="server" 
          OnPagingClicked="Paging_Clicked" 
          NumberOfData="100" NumberPerPage="10">
        <ItemTemplate>
            <%#Container.DataItem%>
            <br />
        </ItemTemplate>
    </CRE:RepeaterWithPaging>
  5. 在代码隐藏文件中,捕获 Paging_Clicked 事件。
  6. Protected Sub Paging_Clicked(ByVal sender As Object, ByVal ev As PagingLiteralEventArgs)
        Response.Write("I click page number: " & ev.CurrentPage.ToString())
    End Sub
  7. 绑定测试数据并测试分页。
  8. 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

各位,就这样了!

关注点

看到实现一个能够回发的控件如此之容易,真是太有趣了。

© . All rights reserved.