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






3.86/5 (7投票s)
一种不使用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。这种技术将在您的页面中为您提供最大的灵活性。