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

适用于 GridView、DataList、Repeater、DataGridView 的 SQL 分页控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (32投票s)

2011年5月6日

CPOL

5分钟阅读

viewsIcon

85983

downloadIcon

3578

DataPager 是一个自定义控件,可以附加到数据控件(如 GridView、ListView、Datalist、Repeater),从而为该控件实现分页。

引言

DataPager 是一个自定义控件,可以附加到数据控件(如 GridViewListViewDatalistRepeater),从而为该控件实现分页。

DataPager 本身显示“首页”“下一页”“上一页”“末页”按钮(或数字页码自定义组合)。 单击分页控件上的按钮,您的数据控件将使用 SQL 分页自动翻页浏览数据。 

只需将 DataPager 拖放到您的 .aspx.cs 页面中,并添加一两行代码即可

Records.png

用户控件中的问题事件处理

用户控件有很多优点——它们允许您将一组常用控件抽象为一个单一的可重用控件。有时,业务需求需要在用户控件及其包含的 ASP.NET 网页之间传递数据。例如,您可能有一个地址控件,并在加载页面时设置地址控件的街道、城市和州属性。然而,虽然 Aspx 页面触发用户控件的方法相对简单,但用户控件反过来触发其包含页面的方法却并非易事。

背景

SQL 分页意味着它使用 SQL 2005 中的新 ROW_NUMBER() (免费的 SQL Express 版本及更高版本均支持)和新的 ASP.NET 2.0 GridView/ObjectDataSource 控件实现了超级高效的数据分页。 

示例 SQL Server 分页查询

With RecordEntries as (
		SELECT ROW_NUMBER() OVER (ORDER BY [OrderByField) as Row, 
		FROM [TableName]
	)
Select * FROM RecordEntries
WHERE Row between @startRowIndex and @endRowIndex

Using the Code

当您将该控件放在 .aspx 页面中时,您可以设置 DataPager 控件的以下属性: 

DataPager.png

现在,在 .aspx.cs 文件中添加以下代码行

委托最终是用户控件能够调用方法的必要条件,即我们希望传递一个方法引用给它,并让它根据自己的条件调用该方法。这正是委托的作用。根据 MSDN 的说法,委托“是一个引用静态方法或类实例和该类实例方法的数据结构。”

换句话说,您可以将一个方法引用赋给一个委托,并像传递其他类型一样传递它。我们将通过一个示例解决方案来解决我们在介绍中提到的记录导航器问题。在此示例中,有一个 WebForm 包含一个用户控件。用户控件包含两个属性,一个用于委托,一个用于业务数据——在本例中是一个整数索引。WebForm 有一个 BindGrid() 方法来填充数据,然后相应地填充页面控件。WebForm 创建一个引用 BindGrid() 方法的委托,并将该委托传递给用户控件的委托类型属性。每当用户控件的上一页或下一页按钮被单击时,它就会调用给定的委托,并传入从用户控件中选择的数据值(在本例中只是索引)。最后,委托反过来触发父页面的 BindGrid() 方法。

public delegate void delPopulateData(int myInt);

技术实现

现在我们对要做的事情有了一个宏观的理解,让我们开始编码吧。首先,我们要创建用户控件。创建一个名为 DataPager.ascx 的用户控件,并向其中添加以下两个属性(代码非常直观):

DataPager_CS.png

aspx.cs 页面包含以下代码

Records_cs.png

程序流程

在初始 WebForm 加载时,相关的控件流从 WebFormPage_Load 开始,并设置用户控件的属性。由于数据(如页面索引)会被序列化并保存在页面的 ViewState 中,因此首次加载时只需设置业务数据。由于 Delegate 默认不会被序列化并保存到 ViewState 中,因此每次回发时都会设置 Delegate 属性。在 WebForm Page_Load 之后,会调用用户控件的 Page_Load 。这会设置默认的业务值(存储在用户控件的属性中),然后调用 UpdatePageIndex() 方法。

if (!IsPostBack)
        {
            BindGrid(1);
        }
        delPopulateData delPopulate = new delPopulateData(this.BindGrid);
        pagerApps.UpdatePageIndex = delPopulate;

此方法更新用户控件的 GUI 以反映值,然后从属性中获取 Delegate 引用并调用该方法,从而触发父页面上的数据更新。当用户单击 RecordIndex 的上一页或下一页按钮时,它们会相应地更新内部业务数据,然后调用 UpdatePageIndex() 方法,该方法会如前所述更新父页面。控件流对于回发几乎是相同的——只是默认的业务数据不会重置。

SQL Server 分页逻辑

以下存储过程将仅返回通过参数传递的记录

--EXEC [GetAppsDetails] 1,10
ALTER PROCEDURE [dbo].[GetAppsDetails] 
	@PageIndex INT,
	@RecordsPerPage INT
AS  
BEGIN  
SET NOCOUNT ON  
	Declare @startRowIndex INT;
	Declare @endRowIndex INT;
	set @endRowIndex = (@PageIndex * @RecordsPerPage);
	set @startRowIndex = (@endRowIndex - @RecordsPerPage) + 1;

	With RecordEntries as (
		SELECT ROW_NUMBER() OVER (ORDER BY A.APP_TYPE_ID ASC) as Row, _
		A.APP_TYPE_ID, 
		A.APP_TYPE_NAME,A.APP_STORE_ID,R.REVIEW_TITLE,R.AUTHOR_NAME,_
		R.REVIEW_DATE,
		R.REVIEW_RATING,R.REVIEW_TEXT FROM [dbo].[APP_TYPES] A
		INNER JOIN [CUSTOMER_APP_REVIEWS] R ON A.APP_TYPE_ID=R.APP_TYPE_ID
	)
	Select APP_TYPE_ID, APP_TYPE_NAME, APP_STORE_ID, REVIEW_TITLE, AUTHOR_NAME, 
	REVIEW_DATE, REVIEW_RATING, REVIEW_TEXT
	FROM RecordEntries
	WHERE Row between 
	@startRowIndex and @endRowIndex
	
	SELECT COUNT(*) FROM [dbo].[APP_TYPES] A
	INNER JOIN [CUSTOMER_APP_REVIEWS] R ON A.APP_TYPE_ID=R.APP_TYPE_ID
END 

摘要

用户控件为 Web 应用程序提供了许多好处。利用这些好处的一部分是在 WebForm 和用户控件之间双向传递数据。虽然将数据传递给用户控件很简单,但将数据从用户控件传回页面却并非如此。但是,我们可以通过让页面实例化一个 Delegate 并将其传递给用户控件来解决这个问题,从而使用户控件能够按需触发父页面的方法。

如果源数据中不存在数据,则 DataPager 的外观如下:

NoRecordFound.png

关注点

我将尝试开发一个不需要一行代码的控件,例如

public delegate void delPopulateData(int myInt);
 delPopulateData delPopulate = new delPopulateData(this.BindGrid);
        pagerApps.UpdatePageIndex = delPopulate;

历史

如果您发现其中存在任何问题或错误,请留下评论或给我发电子邮件。如果您对此有任何记录,也请告诉我,这样我就不必重复您辛勤的工作。如果这对您有帮助,请给个“投票”

适用于 GridView、DataList、Repeater、DataGridView 的 SQL 分页控件 - CodeProject - 代码之家
© . All rights reserved.