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

定制ASP.NET页面中的列表和分页

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.86/5 (7投票s)

2009年12月24日

CPOL

4分钟阅读

viewsIcon

38325

downloadIcon

177

一种不使用Repeater或DataGrid等数据控件显示带分页的列表页的简单方法。

引言

此示例演示了如何使用SQL Server 2005的ROW_NUMBER函数进行分页,并通过自定义代码隐藏中的HTML来获得更好的外观。

使用代码

首先,我们需要选择要列出的记录。在常规的分页技术中,我们会将所有记录加载到数据集中,然后使用PagedDataSource显示适当的页面。这种技术的主要缺点是,我们正在内存中存储所有记录,而实际上只显示一页中的少量记录。每次点击页码时,都会重新选择所有记录。为了克服这个麻烦,我们可以有效地使用SQL Server 2005的ROW_NUMBER函数。

下面的代码片段显示了选择特定记录的存储过程;我们传递了两个参数

  • @intCurrentPage int - 此参数用于选择某一页的记录。
  • @intRecordPerPage int - 此参数用于获取每页要显示的记录数。

例如,如果我们传递@intCurrentPage为1,@intRecordPerPage为10,则结果将是第1到10条记录。此存储过程连接到AdventureWorks数据库,并从Production.Product表中选择记录。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Johnson
-- Create date: 24-12-2009
-- Description: To get specific records from product table 
--       of AdventureWorks database.
-- =============================================
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

CREATE PROCEDURE [dbo].[uspFetchCustomer]
@intCurrentPage int,
@intRecordPerPage int
AS
BEGIN
    SET NOCOUNT ON;

    --***Find the starting record id and ending record id ****
    declare @intStartRec int
    set @intStartRec=(@intCurrentPage*@intRecordPerPage)-@intRecordPerPage
    declare @intEndRec int
    set @intEndRec=(@intCurrentPage*@intRecordPerPage)+1    
    --********************************************************

    Begin
        --***Select the records from @intStartRec to @intEndRec ***
        Select * from
        (
            select ROW_NUMBER() OVER (ORDER BY ProductID) as SlNo,ProductID,
            [Name],ProductNumber,Color
            from Production.Product
        ) Temp
        Where SlNo>@intStartRec and slno<@intEndRec    
        --***********************************************************

        --***Get the total number of records***************
        select COUNT(ProductID) as TotalRecords
        from Production.Product
        --************************************************
    End
END

此存储过程的输出

通过传递: @intCurrentPage=1, @intRecordPerPage=10来执行存储过程。

First Result Set
SlNo    ProductID   Name                        ProductNumber       StandardCost
1        1        Adjustable Race                AR-5381                0.00
2        2        Bearing Ball                BA-8327                0.00
3        3        BB Ball Bearing                BE-2349                0.00
4        4        Headset Ball Bearings        BE-2908                0.00
5        316        Blade                        BL-2036                0.00
6        317        LL Crankarm                        CA-5965                0.00
7        318        ML Crankarm                        CA-6738                0.00
8        319        HL Crankarm                        CA-7457                0.00
9        320        Chainring Bolts                CB-2903                0.00
10        321        Chainring Nut                CN-6137                0.00


TotalRecords
504

第一个结果集是第一页的记录。第二个结果集是记录的总数。

在AdventureWorks数据库中执行此存储过程,并创建一个连接字符串以连接到AdventureWorks。

connectionString ="Data Source=[SERVER NAME];
   Initial Catalog=AdventureWorks;User ID=[USERNAME]; Password=[PASSWORD]" />

在代码隐藏中使用结果

现在,数据库中已准备好存储过程。开始实现我们的列表和分页方法。为了显示列表,我们不使用任何数据控件,直接将HTML写入ASPX页面。

为此,我们首先需要在代码隐藏中声明两个字符串

Protected strList As String     ' to set the HTML of the listing
Protected strPages As String    ' to set the HTML of paging

字符串变量strList存储记录的HTML,而字符串strPages存储分页的HTML。

填充DataReader

首先,我们需要获取页索引。我们可以将页索引存储在一个隐藏的文本字段(txtHidPageIndex)中;默认情况下,将显示第一页。通过此隐藏字段,我们可以存储用户点击的页索引,并在服务器端访问隐藏字段以了解页码。我们需要一个服务器控件来监听页面点击事件。我向页面添加了一个链接按钮控件(lnkPaging)以发起点击并执行一些服务器端操作。

编写一个JavaScript函数来接受页码,并将该页码设置为隐藏字段。之后,执行链接按钮的postback,以便我们可以执行一些服务器端操作。可以通过ASP.NET的doPostBack方法来启动链接按钮的Click事件。

function doPaging(intPageIndex)
{
    document.getElementById('txtHidPageIndex').value=intPageIndex;
    __doPostBack('lnkPaging','');
}

链接按钮(lnkPaging)的代码隐藏如下所示

Protected Sub lnkPaging_Click(ByVal sender As Object, _
          ByVal e As System.EventArgs) Handles lnkPaging.Click
    DoSearch(Val(txtHidPageIndex.Value))
End Sub

下面的代码片段显示了如何用当前页的记录填充DataReader

Private Sub DoSearch(Optional ByVal intPageIndex As Integer = 1)

    Dim intRecordPerPage As Integer = 10
    Dim objCon As New SqlConnection(_
      ConfigurationManager.ConnectionStrings("ConString").ConnectionString)
    Dim objCmd As New SqlCommand()
    objCmd.Connection = objCon
    Dim objReader As SqlDataReader
    objCmd.CommandType = CommandType.StoredProcedure
    objCmd.CommandText = "uspFetchProduct"
    objCmd.Parameters.Add(New SqlParameter("@intCurrentPage", intPageIndex))
    objCmd.Parameters.Add(New SqlParameter("@intRecordPerPage", intRecordPerPage))
    objCon.Open()
    objReader = objCmd.ExecuteReader(CommandBehavior.CloseConnection)

我分配了10条记录显示在一页上。如果您希望用户自定义每页的记录数,可以在网站设置中添加一个选项,并获取该值作为每页记录数。现在,我们已经从DataReader中获取了结果。创建一个StringBuilder来存储创建的HTML。

Dim sbHTML As New StringBuilder
sbHTML.Append("YOUR HEADER INFORMATION")
While objReader.Read
sbHTML.Append("THE LISTING COLUMNS ")

填充列表的HTML后,我们可以将其分配给protected变量strList

strList = sbHTML.ToString

记录的分页

现在是关键部分:如何进行分页。对于分页,我们首先需要记录的总数。从DataReader中获取此数字。

objReader.NextResult()
Dim intTotalRecords As Integer = 0
If objReader.Read Then
    intTotalRecords = Val(objReader(0))
End If

现在,变量intTotalRecords包含了记录的总数。第二项任务是找到页数。这在下面的代码片段中显示

'(100/10) mod=0 and  (105/10) mod=5
Dim intReminder As Integer = intTotalRecords Mod intRecordPerPage
'(100/10) =10 and 105\10 =10
Dim intTotalPages As Integer = intTotalRecords \ intRecordPerPage
If intReminder > 0 Then
'(100/10) so 10 pages, if (105/10) means 11 pages
    intTotalPages += 1
End If

现在,我们需要找到每页的起始记录和结束记录。我们假设列表中显示的页码包含五页。因此,用户将看到“第一页”和“上一页”按钮,然后是下一组五页的按钮,最后是“下一页”和“最后一页”按钮。

Dim intPagesShowing As Integer = 5
' 5 pages will be showing in the list (1|2|3|4|5 then show next button)

Dim intStartPage As Integer
Dim intEndPage As Integer
intStartPage = IIf(intPageIndex <= intPagesShowing, 1, intPageIndex)

If intTotalPages > intPagesShowing And intTotalPages > intStartPage Then
    intEndPage = IIf((intStartPage + intPagesShowing - 1) > intTotalPages, _
                      intTotalPages, (intStartPage + intPagesShowing - 1))
Else
    intEndPage = intTotalPages
End If

现在,我们可以通过检查页索引和剩余页数来隐藏或禁用“第一页”、“上一页”、“下一页”和“最后一页”按钮

Dim bShowFirst As Boolean = False
Dim bShowPrevious As Boolean = False
Dim bShowNext As Boolean = False
Dim bShowLast As Boolean = False

If intPageIndex > 1 Then
    bShowPrevious = True
    bShowFirst = True
End If

If intEndPage < intTotalPages Then
    bShowNext = True
    bShowLast = True
End If

现在,我们可以添加页码,这些页码从起始页到最后一页

For iPage As Integer = intStartPage To intEndPage
    sbHTML.Append(iPage)
Next

填充分页的HTML后,将StringBuilder值存储在protected字符串strPages中。只有当页数大于1时,才会显示分页。

If intTotalPages > 1 Then
    strPages = sbHTML.ToString
End If

关注点

使用此方法时,我们不需要任何数据控件。我们创建并管理列表和分页的HTML。这种技术将在您的页面中为您提供最大的灵活性。

定制ASP.NET页面中的列表和分页 - CodeProject - 代码之家
© . All rights reserved.