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

GridView 自定义分页

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (34投票s)

2006年11月3日

2分钟阅读

viewsIcon

386516

downloadIcon

1

本文演示了如何使用自定义分页来提高 GridView 分页的性能。

引言

GridView 控件提供了一种简单的方法来在页面上显示大量的项目,而无需占用太多空间,这得益于分页。您可以在几秒钟内启用 GridView 控件中的分页功能。如果您要获取少于 100 个项目,内置分页效果很好。一旦项目数量增加,性能就会受到影响。性能下降的主要原因是,每当您转到 GridView 的新页面时,它都会从数据库中获取所有项目。在本文中,我将演示如何使用自定义分页来提高 GridView 分页的性能。

数据库和存储过程

我将使用经典的 Northwind 数据库。存储过程由 Greg Hamilton 编写。您可以在此处查看 Greg Hamilton 的文章:更有效地分页浏览大型结果集。 Greg 创建了一个非常高效的存储过程,无需使用临时表或 TABLE 变量即可工作。

我修改了存储过程,添加了一些字段。 这是修改后的存储过程版本

CREATE PROCEDURE [usp_GetProducts] 
@startRowIndex int,
@maximumRows int, 
@totalRows int OUTPUT

AS

DECLARE @first_id int, @startRow int

SET @startRowIndex =  (@startRowIndex - 1)  * @maximumRows

IF @startRowIndex = 0 
SET @startRowIndex = 1

SET ROWCOUNT @startRowIndex

SELECT @first_id = ProductID FROM Products ORDER BY ProductID

PRINT @first_id

SET ROWCOUNT @maximumRows

SELECT ProductID, ProductName FROM Products WHERE 
ProductID >= @first_id 
ORDER BY ProductID
 
SET ROWCOUNT 0

-- GEt the total rows 

SELECT @totalRows = COUNT(ProductID) FROM Products
GO

我强烈建议您查看 Greg 的文章,其中他详细解释了存储过程的工作原理。

在页面上显示分页数据

我将使用“下一步”和“上一步”按钮来分页浏览记录。 Label 控件将显示我们在分页的 GridView 中的当前位置。 首先,让我们设置一些变量。

protected int currentPageNumber = 1;
private const int PAGE_SIZE = 10;

currentPageNumber 表示 GridView 的当前页,PAGE_SIZE 是每页显示的记录总数。 您还可以允许用户使用 DropDownList 调整页面大小,但本文未涉及此内容。

接下来,我们需要将数据源绑定到 GridView。 让我们整体查看 BindData 方法,稍后我将对其进行剖析,以便您更好地了解它。

private void BindData()
{
    string connectionString = "Server=localhost;" + 
           "Database=Northwind;Trusted_Connection=true";
    SqlConnection myConnection = new SqlConnection(connectionString);
    SqlCommand myCommand = new SqlCommand("usp_GetProducts", 
                                           myConnection);
    myCommand.CommandType = CommandType.StoredProcedure;

    myCommand.Parameters.AddWithValue("@startRowIndex", 
                                      currentPageNumber);
    myCommand.Parameters.AddWithValue("@maximumRows", PAGE_SIZE);
    myCommand.Parameters.Add("@totalRows", SqlDbType.Int, 4);
    myCommand.Parameters["@totalRows"].Direction = 
                       ParameterDirection.Output;

    SqlDataAdapter ad = new SqlDataAdapter(myCommand);

    DataSet ds = new DataSet();
    ad.Fill(ds);

    gvProducts.DataSource = ds;
    gvProducts.DataBind();

    // get the total rows 
    double totalRows = (int)myCommand.Parameters["@totalRows"].Value;

    lblTotalPages.Text = CalculateTotalPages(totalRows).ToString();

    lblCurrentPage.Text = currentPageNumber.ToString(); 

    if (currentPageNumber == 1)
    {
        Btn_Previous.Enabled = false;

        if (Int32.Parse(lblTotalPages.Text) > 0)
        {
            Btn_Next.Enabled = true;
        }
        else
            Btn_Next.Enabled = false;

    }

    else
    {
        Btn_Previous.Enabled = true;

        if (currentPageNumber == Int32.Parse(lblTotalPages.Text))
            Btn_Next.Enabled = false;
        else Btn_Next.Enabled = true; 
    }
}

现在,让我们更详细地看一下上面的代码。 我将 currentPageNumberPAGE_SIZE 发送到数据库,以便我可以获取当前页面的数据。 totalRows 变量返回表中的总行数。 获得 totalRows 后,我将计算将用于此 GridView 的总页数。 总页数是通过使用一个小的辅助函数计算的

private int CalculateTotalPages(double totalRows)
{
    int totalPages = (int)  Math.Ceiling(totalRows / PAGE_SIZE);

    return totalPages; 
}

BindData 方法的末尾,有一些条件检查,以确保仅在适用的情况下才显示“下一步”和“上一步”按钮。

将事件附加到按钮

剩下的最后一件事是将事件附加到 Button 控件。 查看以下代码,我在其中创建了两个 Button 控件。

<asp:Button ID="Btn_Previous" CommandName="Previous" 
            runat="server" OnCommand="ChangePage" 
            Text="Previous" />
<asp:Button ID="Btn_Next" runat="server" CommandName="Next" 
            OnCommand="ChangePage" Text="Next" />

两个按钮都调用下面显示的 ChangePage 事件

// This method will handle the navigation/ paging index
protected void ChangePage(object sender, CommandEventArgs e)
{
    
    switch (e.CommandName)
    {
        case "Previous":
            currentPageNumber = Int32.Parse(lblCurrentPage.Text) - 1;
            break; 

        case "Next":
            currentPageNumber = Int32.Parse(lblCurrentPage.Text) + 1; 
            break; 
    }

    BindData();
}

ChangePage 事件用于更改 GridView 的页码,并通过调用 BindData 方法来更新 Label 文本。

© . All rights reserved.