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

一个非常漂亮且完整的自定义 GridView 分页器,没有 ViewState

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.73/5 (8投票s)

2007年10月14日

CPOL

5分钟阅读

viewsIcon

78178

downloadIcon

1001

如何实现一个自定义的 GridView 分页器,完全不依赖 ViewState 或 GridView 的分页功能。

引言

在我关于自定义 GridView 分页器的文章中,我收到了反馈,有人担心 Web 控件(DataSources、GridView 等)的分页能力依赖于 ViewState,从而影响了页面数据的加载大小。在这篇文章中,我为您呈现了原始 FullGridPager 类的 无 ViewState 版本。新类名为 FullGridPagerNVS,其中 NVS 代表“NoViewState”(无 ViewState)。它实现了分页功能,而不依赖于 GridView 的分页功能——GridViewAllowPaging 属性设置为 false。此外,没有使用数据源来绑定数据到 GridView。这是通过两个数据层类(DataLayerHelperCustomersDataLayer)来实现的,它们只返回受行边界限制的相应行集。

图 1 展示了自定义分页器(格式与原始文章完全相同)。

图 1:自定义分页器

背景

可选地,您可以参考我关于如何为 GridViewPagerTemplate 模板创建自定义分页器的 原始文章

运行代码所需

除了 App_Code 文件夹中的 FullGridPagerNVS.cs 外,还需要以下文件才能使分页器正常工作:

  • FullGridPagerNVS.css:分页器使用的样式。
  • Images 文件夹:包含“第一页”、“上一页”、“下一页”和“最后一页”链接的图像。
  • DataLayerHelper.cs:一个通用的数据库数据层类。
  • CustomersDataLayer.cs:一个类,用于返回考虑分页的数据库行集。它使用了 Northwind 数据库的 Customers 表。

一如既往,ZIP 文件中包含了一个测试用的 ASPX 网页,用于演示 FullGridPagerNVS 类的用法。

  • NVSTest.aspxNVSTest.aspx.cs

使用代码

由于这是一个非标准的 ASP.NET 实现,我将解释它是如何工作的。首先,我将列出此项目的主要关注点和限制:

  • 不能使用数据源来获取数据。相反,代码编写了一个非常简单的数据层,用于在考虑分页的情况下从数据库获取数据。DataLayerHelper 类是一个通用的数据层,它只对数据库执行参数化 SQL 查询。虽然它包含许多方法,但只有 GetExecuteScalar 对我们感兴趣。
  • CustomersDataLayer 类使用 DataLayerHelper 方法查询 Northwind 数据库的 Customers 表,具体来说:

    • GetCustomers 方法以 DataTable 的形式返回 Customers 表的所有行。
    • GetCustomersCount 方法返回 Customers 表中的总行数。
    • GetPageCustomers 方法使用以上两个方法来返回一个行受限的 DataTable。它有两个参数:
      1. startIndex:要开始检索的行号,以及
      2. maxPageRows:每页显示的最大行数。

    这样,我们就可以指定行边界,例如,如果 startIndex = 10 且 maxPageRows = 5,那么返回的行集将只包含行 10、11、12、13、14。请注意,startIndex 是从零开始的。下面的代码片段仅移除了所需边界之外的非必要行(行 0-9 和 15-max)。

    public static DataTable GetPageCustomers(int startIndex, int maxPageRows) 
    { 
        // Delete the unneccessary rows and return the datatable.
        DataTable tbl= GetCustomers(); 
        int maxRows = GetCustomersCount(); 
        int max = startIndex + (maxPageRows - 1); 
        if (max > maxRows) max = maxRows; 
        for (int i = 0; i < startIndex; i++)
            tbl.Rows[i].Delete(); 
        for (int i = max + 1; i < maxRows; i++) 
            tbl.Rows[i].Delete(); return tbl; 
    }

    由于没有数据源,以下代码(NVSTest.aspx.cs 文件)用于手动将数据绑定到 GridView

    GridView1.DataSource = 
      CustomersDataLayer.GetPageCustomers(StartIndex, PageSize); GridView1.DataBind();
  • GridView 必须将其 AllowPaging 属性设置为 false,当然。因此,没有 PageIndexPageCount 属性可供依赖。总行数也是我们必须知道的一个值。因此,这些值在网页代码中初始化,并存储在 Session 状态中。
  • public partial class NVSTest : System.Web.UI.Page { 
        protected void Page_Load(object sender, EventArgs e
        { 
            if (!IsPostBack) 
            { 
                StartIndex = 0; 
                MaxRows = CustomersDataLayer.GetCustomersCount(); 
                BindData(); 
            } 
            else 
                ShowFullGridPagerNVS(); 
        } 
        
        public int StartIndex 
        { 
            get { return (int)Session["startIndex"]; } 
            set { Session["startIndex"] = value; } 
        } 
        
        public int MaxRows 
        { 
            get { return (int)Session["maxRows"]; } 
            set { Session["maxRows"] = value; } 
        }
    }

    您也可以将它们存储在任何您喜欢的地方——甚至在 ViewState 中!以下是它们的含义:

    • StartIndex:绑定的行集必须从此行开始。
    • MaxRows:绑定行集中的总行数。

考虑到以上几点,我对 FullGridPagerNVS 类做了一些修改。

  • 除了 MaxVisiblePageNumbers 之外,总行数(MaxRows)和每页行数(MaxPageRows)必须作为参数传递。
  • 该类计算总页数(totalPages)。这取代了 GridViewPageCount 属性。
  • 该类通过将行索引(StartIndex)转换为页索引来计算当前页。
  • currentPageIndex = (int)Math.Ceiling((decimal)StartIndex / maxPageRows);

    这取代了 GridViewPageIndex 属性。

  • 自定义分页器不能再放置在 PageTemplate 模板内。这会影响回发期间动态创建的控件的行为。该类现在动态创建所有必要的控件,包括“第一页”、“上一页”、“下一页”、“最后一页”链接以及页组 DropDownList。请注意,在重新创建它们之前,HTML 容器会被清空。
  • public void CreateCustomPager(Control Container, int StartIndex) { 
        [...] 
        HtmlTable pagerInnerTable = 
            (HtmlTable)Container.FindControl("pagerInnerTable"); 
        if (pagerInnerTable != null) 
        { 
            // Remove the dynamically created cells before 
            // recreating them. 
            pagerInnerTable.Rows[0].Cells.Clear(); 
            [...] 
        } 
        [...] 
        HtmlTable pagerOuterTable = 
             (HtmlTable)Container.FindControl("pagerOuterTable"); 
        if (pagerOuterTable != null) 
        { 
            // Remove the pageGroups cell if it exists. 
            if (pagerOuterTable.Rows[0].Cells.Count > 1) 
                pagerOuterTable.Rows[0].Cells.RemoveAt(1); 
            [...] 
        } 
    }
  • 所有页面链接不再能调用特殊的 Page 命令。它们的 CommandArgument 值不再是 PageIndex 值。页组 DropDownList 也是如此。FullGridPagerNVS 通过将每个页索引乘以每页的总行数来将每个页索引映射到起始行索引。例如:
    • 上一页按钮的值
    • ((currentPageIndex - 1) * maxPageRows).ToString();
    • 页码链接的值
    • ((i - 1) * maxPageRows).ToString();
    • 最后一页链接的值
    • ((totalPages-1) * maxPageRows).ToString();
    • ddlPageGroups 选定的值
    • new ListItem(group, (groupFirstPageNumber * maxPageRows).ToString());
  • 每次用户点击自定义分页器时,StartIndex 值必须更改,并且 GridView 必须重新绑定数据。现在由网页(NVSTest.aspx)负责此责任。FullGridPagerNVS 类不了解数据绑定(而且这也不是它的业务)。但是,它必须提供处理动态创建的控件事件的手段。它通过指定两个事件处理程序来实现:
  • public event CommandEventHandler PageNumberClick; 
    public event EventHandler PageGroupChange;

    动态控件绑定到这些事件处理程序,例如:

    lnkPage.Command += new CommandEventHandler(PageNumberClick);

    最后,网页代码后置中所需的代码:

    ullGridPager.PageNumberClick += new CommandEventHandler(lnkPage_Command); 
    fullGridPager.PageGroupChange += new EventHandler(ddlPageGroups_SelectedIndexChanged);

    当用户点击页码链接时,会发生以下情况:

    void lnkPage_Command(object sender, CommandEventArgs e) 
    { 
        StartIndex = Int32.Parse(e.CommandArgument.ToString()); 
        BindData(); 
    }

关注点

请确保您理解这是一个非标准的 ASP.NET 分页实现。这是基于我在关于如何创建自定义 GridView 分页器的文章中收到的反馈而进行的按需工作。我强烈建议您阅读原始文章,其中为您提供了直接、面向 ASP.NET 的解决方案。

历史

© . All rights reserved.