C# winform 自制分页功能

一个精简的分页类,配合现有的界面按钮使用:

分页类(Pagination.cs)

csharp 复制代码
using System;
using System.Collections.Generic;

/// <summary>
/// 分页管理类
/// </summary>
public class Pagination
{
    private int _pageIndex = 1;      // 当前页码
    private int _pageSize = 10;       // 每页显示条数
    private int _totalCount = 0;      // 总记录数
    private int _totalPages = 0;      // 总页数

    /// <summary>
    /// 页码改变事件(在UI中订阅此事件来刷新数据)
    /// </summary>
    public event Action OnPageChanged;

    /// <summary>
    /// 当前页码(从1开始)
    /// </summary>
    public int PageIndex
    {
        get { return _pageIndex; }
        set
        {
            if (value >= 1 && value <= _totalPages)
            {
                _pageIndex = value;
                OnPageChanged?.Invoke();
            }
        }
    }

    /// <summary>
    /// 每页显示条数
    /// </summary>
    public int PageSize
    {
        get { return _pageSize; }
        set
        {
            if (value > 0)
            {
                _pageSize = value;
                // 改变每页条数后重置到第一页
                _pageIndex = 1;
                // 重新计算总页数
                RecalculateTotalPages();
                OnPageChanged?.Invoke();
            }
        }
    }

    /// <summary>
    /// 总记录数
    /// </summary>
    public int TotalCount
    {
        get { return _totalCount; }
        set
        {
            _totalCount = value;
            RecalculateTotalPages();
        }
    }

    /// <summary>
    /// 总页数
    /// </summary>
    public int TotalPages => _totalPages;

    /// <summary>
    /// 是否有上一页
    /// </summary>
    public bool HasPrevPage => _pageIndex > 1;

    /// <summary>
    /// 是否有下一页
    /// </summary>
    public bool HasNextPage => _pageIndex < _totalPages;

    /// <summary>
    /// 数据起始索引(用于SQL查询的 OFFSET,从0开始)
    /// </summary>
    public int StartIndex => (_pageIndex - 1) * _pageSize;

    /// <summary>
    /// 重新计算总页数
    /// </summary>
    private void RecalculateTotalPages()
    {
        if (_totalCount == 0)
        {
            _totalPages = 1;
        }
        else
        {
            _totalPages = (int)Math.Ceiling((double)_totalCount / _pageSize);
        }

        // 如果当前页超出总页数,调整到最后一页
        if (_pageIndex > _totalPages)
        {
            _pageIndex = _totalPages;
        }
    }

    /// <summary>
    /// 上一页
    /// </summary>
    public void PrevPage()
    {
        if (HasPrevPage)
        {
            PageIndex--;
        }
    }

    /// <summary>
    /// 下一页
    /// </summary>
    public void NextPage()
    {
        if (HasNextPage)
        {
            PageIndex++;
        }
    }

    /// <summary>
    /// 跳转到指定页
    /// </summary>
    /// <param name="pageNumber">页码(从1开始)</param>
    /// <returns>是否跳转成功</returns>
    public bool GoToPage(int pageNumber)
    {
        if (pageNumber >= 1 && pageNumber <= _totalPages)
        {
            PageIndex = pageNumber;
            return true;
        }
        return false;
    }

    /// <summary>
    /// 获取分页信息文本(用于显示在界面上)
    /// </summary>
    public string GetPageInfoText()
    {
        return $"第 {_pageIndex} / {_totalPages} 页,共 {_totalCount} 条记录";
    }

    /// <summary>
    /// 获取按钮状态(用于界面按钮的Enabled属性)
    /// </summary>
    public (bool canPrev, bool canNext) GetButtonStatus()
    {
        return (HasPrevPage, HasNextPage);
    }
}

使用示例(在窗体中)

csharp 复制代码
public partial class MainForm : Form
{
    private Pagination _pagination;
    private DataTable _allData;  // 全部数据

    public MainForm()
    {
        InitializeComponent();
        InitPagination();
        LoadMockData();
        LoadPageData();
    }

    private void InitPagination()
    {
        _pagination = new Pagination();
        _pagination.PageSize = 10;  // 设置每页条数
        _pagination.OnPageChanged += () =>
        {
            // 页码改变时重新加载数据
            LoadPageData();
            UpdateUI();
        };
    }

    private void UpdateUI()
    {
        // 更新按钮状态
        var (canPrev, canNext) = _pagination.GetButtonStatus();
        btnPrev.Enabled = canPrev;
        btnNext.Enabled = canNext;

        // 更新显示信息
        lblPageInfo.Text = _pagination.GetPageInfoText();
    }

    // 按钮事件
    private void btnPrev_Click(object sender, EventArgs e)
    {
        _pagination.PrevPage();
    }

    private void btnNext_Click(object sender, EventArgs e)
    {
        _pagination.NextPage();
    }

    // 跳转按钮
    private void btnJump_Click(object sender, EventArgs e)
    {
        if (int.TryParse(txtJumpPage.Text, out int page))
        {
            if (!_pagination.GoToPage(page))
            {
                MessageBox.Show($"页码范围:1-{_pagination.TotalPages}");
            }
        }
        else
        {
            MessageBox.Show("请输入有效的页码");
        }
    }

    // 设置每页条数
    private void cmbPageSize_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (cmbPageSize.SelectedItem != null)
        {
            int pageSize = Convert.ToInt32(cmbPageSize.SelectedItem);
            _pagination.PageSize = pageSize;
        }
    }

    // 加载分页数据
    private void LoadPageData()
    {
        // 方法1:从内存数据中取
        var pageData = _allData.Rows
            .Cast<DataRow>()
            .Skip(_pagination.StartIndex)
            .Take(_pagination.PageSize)
            .CopyToDataTable();

        dataGridView1.DataSource = pageData;

        // 方法2:从数据库查询(推荐)
        // string sql = @"
        //     SELECT * FROM Users 
        //     ORDER BY ID 
        //     OFFSET @Offset ROWS 
        //     FETCH NEXT @PageSize ROWS ONLY";
        // 
        // var parameters = new 
        // { 
        //     Offset = _pagination.StartIndex, 
        //     PageSize = _pagination.PageSize 
        // };
        // dataGridView1.DataSource = ExecuteQuery(sql, parameters);
    }

    private void LoadMockData()
    {
        // 模拟155条数据
        _allData = new DataTable();
        _allData.Columns.Add("ID", typeof(int));
        _allData.Columns.Add("Name", typeof(string));

        for (int i = 1; i <= 155; i++)
        {
            _allData.Rows.Add(i, $"用户{i}");
        }

        // 设置总记录数
        _pagination.TotalCount = _allData.Rows.Count;
    }
}

核心属性说明

属性 说明
PageIndex 当前页码(从1开始)
PageSize 每页条数
TotalCount 总记录数(外部赋值)
TotalPages 总页数(自动计算)
HasPrevPage 是否有上一页
HasNextPage 是否有下一页
StartIndex 数据起始索引(从0开始,用于SQL的OFFSET)

使用步骤

  1. 实例化分页类_pagination = new Pagination();
  2. 订阅事件_pagination.OnPageChanged += LoadData;
  3. 设置总记录数_pagination.TotalCount = totalRows;
  4. 按钮事件调用_pagination.PrevPage() / NextPage() / GoToPage()
  5. 获取数据 :使用 StartIndexPageSize 查询数据库
  6. 更新UI :根据 HasPrevPage/HasNextPage 控制按钮启用状态

这个分页类不包含任何UI控件,完全独立,你只需要在窗体的按钮事件中调用对应方法即可。

相关推荐
summerkissyou19871 小时前
Android-线程安全-volatile
android·线程
Rust研习社1 小时前
Rust 智能指针 Cell 与 RefCell 的内部可变性
开发语言·后端·rust
南無忘码至尊2 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎
leaves falling2 小时前
C++模板进阶
开发语言·c++
坐吃山猪3 小时前
Python27_协程游戏理解
开发语言·python·游戏
gCode Teacher 格码致知3 小时前
Javascript提高:小数精度和随机数-由Deepseek产生
开发语言·javascript·ecmascript
椰猫子3 小时前
Javaweb(Filter、Listener、AJAX、JSON)
java·开发语言
盛世宏博北京4 小时前
以太网温湿度传感器运维技巧,提升设备稳定性与使用寿命
开发语言·php·以太网温湿度传感器
代码改善世界4 小时前
【MATLAB初阶】矩阵操作(一)
开发语言·matlab·矩阵