在C# WinForms开发中,DataGridView是常用的数据展示控件,但当需要展示的数据量达到数万甚至数十万条时,一次性将所有数据加载到DataGridView中会导致界面卡顿、内存占用飙升,甚至出现程序无响应的情况。实现DataGridView分页功能,分批次加载数据,是解决这个问题的核心方案。

分页实现的核心思路
DataGridView分页的本质是只加载当前页需要展示的数据,而不是全部数据。核心逻辑可以分为三个部分:
- 计算总数据量和总页数,确定分页的基础参数
- 根据当前页码和每页显示条数,查询对应范围的数据
- 将查询到的数据绑定到DataGridView,同时更新分页状态信息
基础分页参数定义
首先需要定义分页相关的参数,方便后续逻辑复用,我们可以在窗体类中添加以下字段:
// 每页显示的记录数 private int pageSize = 20; // 当前页码,默认从第一页开始 private int currentPage = 1; // 总记录数 private int totalCount = 0; // 总页数 private int totalPage = 0; // 模拟的数据源,实际开发中替换为数据库查询 private List<User> allData = new List<User>();
模拟海量数据生成
为了测试分页效果,我们先生成一批模拟数据,实际开发中这里的allData可以替换为从数据库查询得到的全量数据集合:
// 用户实体类
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
// 生成模拟数据的方法
private void GenerateTestData()
{
allData = new List<User>();
// 生成10000条测试数据
for (int i = 1; i <= 10000; i++)
{
allData.Add(new User
{
Id = i,
Name = $"用户{i}",
Age = 20 + (i % 30),
Address = $"测试地址{i}"
});
}
}
分页数据查询方法
根据当前页码和每页条数,从全量数据中截取对应范围的数据,这里使用LINQ的Skip和Take方法实现:
// 获取当前页的数据
private List<User> GetPageData(int pageIndex)
{
// 计算需要跳过的记录数
int skipCount = (pageIndex - 1) * pageSize;
// 跳过前面的记录,取pageSize条数据
return allData.Skip(skipCount).Take(pageSize).ToList();
}
分页状态计算与绑定
在加载数据前,需要先计算总记录数和总页数,然后更新分页相关的显示信息:
// 初始化分页参数并加载第一页数据
private void InitPagination()
{
// 获取总记录数
totalCount = allData.Count;
// 计算总页数,使用Math.Ceiling处理除不尽的情况
totalPage = (int)Math.Ceiling((double)totalCount / pageSize);
// 重置当前页码为第一页
currentPage = 1;
// 加载第一页数据
LoadPageData();
}
加载指定页数据的方法,负责将数据绑定到DataGridView,同时更新页码显示:
// 加载指定页的数据到DataGridView
private void LoadPageData()
{
// 获取当前页的数据
List<User> pageData = GetPageData(currentPage);
// 绑定到DataGridView
dataGridView1.DataSource = pageData;
// 更新分页状态显示,假设窗体上有label显示分页信息
lblPageInfo.Text = $"第{currentPage}页/共{totalPage}页,总记录数:{totalCount}";
// 更新按钮状态,首页、上一页、下一页、末页按钮根据实际需求添加
btnFirstPage.Enabled = currentPage > 1;
btnPrevPage.Enabled = currentPage > 1;
btnNextPage.Enabled = currentPage < totalPage;
btnLastPage.Enabled = currentPage < totalPage;
}
分页按钮事件处理
为分页相关的按钮添加点击事件,实现页码切换:
// 首页按钮点击事件
private void btnFirstPage_Click(object sender, EventArgs e)
{
currentPage = 1;
LoadPageData();
}
// 上一页按钮点击事件
private void btnPrevPage_Click(object sender, EventArgs e)
{
if (currentPage > 1)
{
currentPage--;
LoadPageData();
}
}
// 下一页按钮点击事件
private void btnNextPage_Click(object sender, EventArgs e)
{
if (currentPage < totalPage)
{
currentPage++;
LoadPageData();
}
}
// 末页按钮点击事件
private void btnLastPage_Click(object sender, EventArgs e)
{
currentPage = totalPage;
LoadPageData();
}
实际数据库场景适配
如果数据来自数据库,不建议先查询全量数据再分页,而是直接在数据库查询时完成分页,减少数据传输量。以SQL Server为例,可以使用OFFSET FETCH语句实现分页查询:
// 从数据库查询分页数据的方法示例
private List<User> GetDataFromDb(int pageIndex)
{
int offset = (pageIndex - 1) * pageSize;
string sql = $"SELECT Id, Name, Age, Address FROM UserTable ORDER BY Id OFFSET {offset} ROWS FETCH NEXT {pageSize} ROWS ONLY";
// 执行数据库查询的逻辑,这里省略具体的ADO.NET操作
// 返回查询得到的List<User>集合
return new List<User>();
}
注意事项
- 分页查询时数据库端必须有明确的排序规则,否则每次查询的页码数据可能不一致
- 每页显示条数可以根据实际需求调整,建议不要设置过大,通常20-50条比较合适
- 如果数据会频繁变动,每次切换页码时建议重新查询总记录数,保证分页信息准确
- DataGridView的列如果是自动生成的,可以在绑定数据后调整列宽、列名等属性,提升展示效果
C#DataGridView分页海量数据展示修改时间:2026-07-20 00:12:40