You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebForms中GridView分页仅查询单页数据的实现方法

没问题,这个需求在WebForms里完全可以实现,核心就是放弃GridView的默认分页机制,改用自定义分页——也就是每次只从数据库拉取当前页需要的10条数据,而不是全表查询。我给你一步步拆解怎么做:

核心思路

默认的GridView分页是先把全表数据查出来放到内存里,再截取当前页的内容,这在数据量大的时候肯定会卡。自定义分页则是让数据库只返回当前页的10条数据,同时获取总记录数来生成分页导航。

具体实现步骤

1. 准备数据访问方法

你需要写两个数据库操作方法:一个用来获取指定页的数据,另一个用来获取总记录数。这里以SQL Server为例(如果是MySQL/Oracle,语法略有不同,后面会提):

获取分页数据的方法

public DataTable GetPagedData(int pageIndex, int pageSize)
{
    // 计算当前页的起始行和结束行(SQL Server的ROW_NUMBER是从1开始的)
    int startRow = (pageIndex - 1) * pageSize + 1;
    int endRow = pageIndex * pageSize;
    
    string sql = @"
        SELECT * FROM (
            -- 先给每条数据加行号,注意这里的ORDER BY要换成你实际的排序字段
            SELECT *, ROW_NUMBER() OVER(ORDER BY YourSortColumn DESC) AS RowNum
            FROM YourTableName
        ) AS TempTable
        WHERE RowNum BETWEEN @StartRow AND @EndRow";
    
    DataTable result = new DataTable();
    // 用using自动释放连接,避免资源泄漏
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["YourConnString"].ConnectionString))
    {
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            // 参数化查询,防止SQL注入
            cmd.Parameters.AddWithValue("@StartRow", startRow);
            cmd.Parameters.AddWithValue("@EndRow", endRow);
            
            SqlDataAdapter adapter = new SqlDataAdapter(cmd);
            adapter.Fill(result);
        }
    }
    return result;
}

获取总记录数的方法

public int GetTotalRecordCount()
{
    string sql = "SELECT COUNT(*) FROM YourTableName";
    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["YourConnString"].ConnectionString))
    {
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            conn.Open();
            return (int)cmd.ExecuteScalar();
        }
    }
}

注意:如果是MySQL,分页用LIMIT (pageIndex-1)*pageSize, pageSize;如果是Oracle,用ROWNUM来筛选,语法会稍有不同,核心都是让数据库做分页筛选。

2. 配置页面控件

GridView设置

把GridView的AllowPaging设为false(因为我们不用它的默认分页),然后定义好你的列:

<asp:GridView ID="gvData" runat="server" AutoGenerateColumns="false" Width="100%">
    <Columns>
        <asp:BoundField DataField="Id" HeaderText="ID" />
        <asp:BoundField DataField="Name" HeaderText="名称" />
        <!-- 其他列根据你的需求添加 -->
    </Columns>
</asp:GridView>

分页导航控件

推荐用第三方的AspNetPager控件(这个是WebForms里常用的分页控件,NuGet可以直接安装),配置起来很方便:

<webdiyer:AspNetPager ID="anpPager" runat="server" 
    PageSize="10" 
    OnPageChanged="anpPager_PageChanged"
    AlwaysShow="true"
    ShowPageIndexBox="true"
    LayoutType="Table">
</webdiyer:AspNetPager>

如果不想用第三方控件,也可以自己写上一页/下一页按钮,维护当前页码的ViewState就行,后面会提。

3. 页面后台逻辑

首次加载绑定数据

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // 先获取总记录数,传给分页控件
        anpPager.RecordCount = GetTotalRecordCount();
        // 绑定第一页数据
        BindGridData(anpPager.CurrentPageIndex);
    }
}

// 封装绑定数据的方法
private void BindGridData(int pageIndex)
{
    gvData.DataSource = GetPagedData(pageIndex, anpPager.PageSize);
    gvData.DataBind();
}

分页变更事件

当用户点击分页按钮时,重新绑定对应页的数据:

protected void anpPager_PageChanged(object sender, EventArgs e)
{
    BindGridData(anpPager.CurrentPageIndex);
}

4. 自定义分页按钮(不用第三方控件的方案)

如果不想依赖第三方控件,自己做分页按钮也可以:

  1. 先在页面加几个控件:
<asp:Button ID="btnPrev" runat="server" Text="上一页" OnClick="btnPrev_Click" />
<asp:Label ID="lblPageInfo" runat="server" Text="第1页/共0页"></asp:Label>
<asp:Button ID="btnNext" runat="server" Text="下一页" OnClick="btnNext_Click" />
  1. 后台维护当前页码的ViewState:
// 用ViewState保存当前页码,避免回发丢失
private int CurrentPage
{
    get { return ViewState["CurrentPage"] == null ? 1 : (int)ViewState["CurrentPage"]; }
    set { ViewState["CurrentPage"] = value; }
}
  1. 按钮点击事件:
protected void btnPrev_Click(object sender, EventArgs e)
{
    int totalPages = (int)Math.Ceiling(GetTotalRecordCount() / (double)10);
    if (CurrentPage > 1)
    {
        CurrentPage--;
        BindGridData(CurrentPage);
        UpdatePageInfoLabel(totalPages);
    }
}

protected void btnNext_Click(object sender, EventArgs e)
{
    int totalPages = (int)Math.Ceiling(GetTotalRecordCount() / (double)10);
    if (CurrentPage < totalPages)
    {
        CurrentPage++;
        BindGridData(CurrentPage);
        UpdatePageInfoLabel(totalPages);
    }
}

// 更新页码信息标签
private void UpdatePageInfoLabel(int totalPages)
{
    lblPageInfo.Text = $"第{CurrentPage}页/共{totalPages}页";
}

然后在首次加载时也要更新页码标签:

if (!IsPostBack)
{
    int totalPages = (int)Math.Ceiling(GetTotalRecordCount() / (double)10);
    UpdatePageInfoLabel(totalPages);
    BindGridData(1);
}
额外注意事项
  • 排序处理:如果需要支持GridView排序,要把ROW_NUMBER()里的ORDER BY换成动态的排序字段,比如根据用户点击的列来修改SQL里的排序条件。
  • 参数化查询:一定要用参数化查询,不要直接拼接SQL字符串,防止SQL注入。
  • 数据库连接:用using语句自动释放数据库连接,避免资源泄漏。

这样每次页面加载或者点击分页按钮时,只会从数据库查询当前页的10条数据,大大减少了数据传输量,页面加载速度会快很多。

内容的提问来源于stack exchange,提问作者Konstantin Kožuchov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:09:09