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

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (7投票s)

2009年12月10日

Ms-PL

3分钟阅读

viewsIcon

42625

downloadIcon

719

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)。
  • FirstLinkIDPreviousLinkIDNextLinkIDLastLinkID - 这些属性指定用于导航的 HyperLink 控件的 ID。 如果您将属性留空,则将被忽略。 因此,如果您只需要“上一页”和“下一页”链接,则只需指定 PreviousLinkIDNextLinkID

使用 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 页”)。
© . All rights reserved.