使用 ASP.NET URL 路由进行数据分页






4.89/5 (7投票s)
ASP.NET 4.0 中一个很棒的功能是 Web Forms 的 URL 路由。但是,它与 DataPager 控件配合不好。 一种替代的数据分页界面可以提供帮助,同时还可以解决其他分页问题。
引言
ASP.NET 3.5 包含一个非常有用的组件 - DataPager
控件。 该控件允许您对实现 IPageableItemContainer
接口的任何控件的内容进行分页 - 到目前为止,只有通用的 ListView
控件,它也是 ASP.NET 3.5 的一部分。
ASP.NET 4.0 向 Web Forms 添加了另一个很棒的功能:URL 路由,该功能首先在 ASP.NET MVC 中出现。 路由引擎使您可以比破解 URL 重写更容易地创建规范且用户友好的 URL。 您可以在 Scott Guthrie 的这篇博客文章中阅读有关 URL 路由的更多信息。
问题是这两个功能不能很好地协同工作,并且 DataPager
控件确实存在其他一些限制。
- 在当前的 ASP.NET 4.0 beta 2 中,如果指定了
QueryStringField
属性,则DataPager
根本不起作用。 这是一个已知错误,将在最终版本中修复(错误 #515348)。 但是对于早期采用者来说,这目前是一个问题。 DataPager
控件仅支持查询字符串或 JavaScript 回发进行分页。 您无法在路由中指定当前页面索引。DataPager
呈现其自己的 UI,可以对其进行自定义,但不容易,尤其是在 CSS 样式方面。
解决方案
我的解决方案是编写自己的数据分页控件。 此控件使用与 DataPager
相同的 IPageableItemContainer
基础结构,但具有不同的 UI 生成理念。
该控件不呈现自己的界面,而是使用标准的 HyperLink
控件,设置它们的 NavigateUrl
属性,并根据配置,可以在不需要时隐藏或禁用它们。
此控件用作控件扩展器,扩展任何 IPageableItemContainer
(简而言之:ListView
)控件。
DataPagerExtender 控件的配置属性
TargetControlID
- 应该分页的控件的 ID。PageSize
- 单个页面上的项目数;默认为 10。PageIndexSource
- 从何处获取当前页面索引。 可以是RouteParameter
(默认)或QueryString
。CollectionKey
- 设置查询字符串字段或路由参数的名称(见上文),以从中获取当前页面索引。InactiveLinkMode
- 指定链接不活动时的行为方式(即,第一页上的“上一页”链接)。 默认值为Ignore
,在这种情况下,链接将被忽略并保持不变。 设置为Hide
时,特定的链接控件将被隐藏(Visible=false
),设置为Disable
时,该控件将被禁用(Enabled=false
)。FirstLinkID
、PreviousLinkID
、NextLinkID
、LastLinkID
- 这些属性指定用于导航的HyperLink
控件的 ID。 如果您将属性留空,则将被忽略。 因此,如果您只需要“上一页”和“下一页”链接,则只需指定PreviousLinkID
和NextLinkID
。
使用 DataPagerExtender 控件
首先,以通常的方式在 ListView
控件中显示您的数据。 然后,创建四个 HyperLink
控件,用于导航到第一页、上一页、下一页和最后一页(在下面的代码中以粗体标记)
<asp:ListView ID="ListView1" runat="server" DataSourceID="LinqDataSource1">
<LayoutTemplate>
<table>
<thead>
<tr>
<th>ProductID</th>
<th>ProductName</th>
<th>UnitPrice</th>
</tr>
</thead>
<tbody>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</tbody>
<tfoot>
<tr>
<td colspan="3">
<div style="float: left">
<asp:HyperLink ID="LinkFirst" runat="server" Text="<< first" />
<asp:HyperLink ID="LinkPrevious" runat="server" Text="< previous" />
</div>
<div style="float: right">
<asp:HyperLink ID="LinkNext" runat="server" Text="next >" />
<asp:HyperLink ID="LinkLast" runat="server" Text="last >>" />
</div>
</td>
</tr>
</tfoot>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label runat="server" Text='<%# Eval("ProductID") %>' />
</td>
<td>
<asp:Label runat="server" Text='<%# Eval("ProductName") %>' />
</td>
<td>
<asp:Label runat="server" Text='<%# Eval("UnitPrice") %>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:LinqDataSource ID="LinqDataSource1" runat="server" TableName="Products"
ContextTypeName="NorthwindDataContext" OrderBy="ProductName"
Select="new (ProductID, ProductName, UnitPrice)" />
然后,添加 DataPagerExtender
控件(在我的例子中,我在 my
前缀上注册了它,并且我正在使用查询字符串)
<my:DataPagerExtender ID="DPE1" runat="server" TargetControlID="ListView1"
PageIndexSource="QueryString" CollectionKey="Page"
FirstLinkID="LinkFirst" LastLinkID="LinkLast"
NextLinkID="LinkNext" PreviousLinkID="LinkPrevious" />
将 DataPagerExtender 与路由一起使用
首先,您必须稍微修改上面的控件引用
<my:DataPagerExtender ID="DPE1" runat="server" TargetControlID="ListView1"
PageIndexSource="RouteParameter" CollectionKey="Page"
FirstLinkID="LinkFirst" LastLinkID="LinkLast"
NextLinkID="LinkNext" PreviousLinkID="LinkPrevious" />
然后,您必须创建一些包含 {Page}
路由参数(以及可能的一些其他参数)的路由。 建议此参数默认为 "1"
,因此当未明确指定时,将显示第一页
void Application_Start(object sender, EventArgs e) {
RouteTable.Routes.MapPageRoute("PagedProducts", // route name
"pagedproducts/{Page}", // path
"~/Products2.aspx", // internal handler
false, // do not check physical file
new RouteValueDictionary { { "Page", "1" } }); // default to first page
}
限制
与原始 DataPager
控件相比,我的 DataPagerExtender
存在一些限制
- 它不支持回发进行分页。
- 仅支持“下一页/上一页”等分页样式,而不支持具有直接跳转功能的页码列表。
- 没有声明式的方式来显示分页信息(例如,“显示 100 项中的第 1-10 项,第 1 页,共 10 页”)。