WinForm实现DataGridView表头复选框全选功能

运行效果

动画

实现思路

要实现DataGridView表头复选框全选功能,我们需要以下几个步骤:

  1. 创建自定义表头单元格类:继承自DataGridViewColumnHeaderCell,重写Paint方法绘制复选框
  2. 处理鼠标点击事件:在表头单元格中检测鼠标点击位置,判断是否点击了复选框
  3. 实现状态切换:点击复选框时切换选中状态,并触发事件通知父组件
  4. 添加事件处理:在主表单中订阅事件,实现全选/全不选逻辑

核心代码解析

1. 自定义表头单元格类

首先,我们需要创建一个自定义的表头单元格类,用于绘制复选框并处理点击事件:

public class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
{
    Point checkBoxLocation;
    Size checkBoxSize;
    bool _checked = false;
    Point _cellLocation = new Point();
    System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
        System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
    public event CheckBoxClickedHandler OnCheckBoxClicked;

    // 构造函数
    public DatagridViewCheckBoxHeaderCell()
    {
    }

    // 重写Paint方法绘制复选框
    protected override void Paint(System.Drawing.Graphics graphics,
        System.Drawing.Rectangle clipBounds,
        System.Drawing.Rectangle cellBounds,
        int rowIndex,
        DataGridViewElementStates dataGridViewElementState,
        object value,
        object formattedValue,
        string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // 调用基类方法绘制基本内容
        base.Paint(graphics, clipBounds, cellBounds, rowIndex,
            dataGridViewElementState, value,
            formattedValue, errorText, cellStyle,
            advancedBorderStyle, paintParts);
        
        // 计算复选框位置和大小
        Point p = new Point();
        Size s = CheckBoxRenderer.GetGlyphSize(graphics,
        System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
        p.X = cellBounds.Location.X +
            (cellBounds.Width / 2) - (s.Width / 2);
        p.Y = cellBounds.Location.Y +
            (cellBounds.Height / 2) - (s.Height / 2);
        _cellLocation = cellBounds.Location;
        checkBoxLocation = p;
        checkBoxSize = s;
        
        // 根据选中状态设置复选框样式
        if (_checked)
            _cbState = System.Windows.Forms.VisualStyles.
                CheckBoxState.CheckedNormal;
        else
            _cbState = System.Windows.Forms.VisualStyles.
                CheckBoxState.UncheckedNormal;
        
        // 绘制复选框
        CheckBoxRenderer.DrawCheckBox
        (graphics, checkBoxLocation, _cbState);
    }

    // 处理鼠标点击事件
    protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
    {
        // 计算点击位置
        Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
        
        // 判断是否点击了复选框
        if (p.X >= checkBoxLocation.X && p.X <=
            checkBoxLocation.X + checkBoxSize.Width
        && p.Y >= checkBoxLocation.Y && p.Y <=
            checkBoxLocation.Y + checkBoxSize.Height)
        {
            // 切换选中状态
            _checked = !_checked;
            
            // 触发事件
            if (OnCheckBoxClicked != null)
            {
                OnCheckBoxClicked(_checked);
                this.DataGridView.InvalidateCell(this);
            }
        }
        base.OnMouseClick(e);
    }
}

2. 事件委托定义

为了在表头复选框状态改变时通知父组件,我们需要定义一个事件委托:

public delegate void CheckBoxClickedHandler(bool state);

3. 实现全选/全不选逻辑

在主表单中,我们需要订阅表头复选框的点击事件,并实现全选/全不选逻辑:

private void HeaderCheckBoxClicked(bool state)
{
     //这一句很重要结束编辑状态,否则处于编辑状态的勾选框是不会被改变的
     dataGridView1.EndEdit();
     dataGridView1.Rows.OfType<DataGridViewRow>().ToList().ForEach(t => t.Cells[0].Value = state);        
}

使用方法

1. 添加自定义类

将上述DatagridViewCheckBoxHeaderCell类和CheckBoxClickedHandler委托添加到你的项目中。

2. 创建DataGridView并设置列

在表单中添加DataGridView控件,然后在代码中初始化:

private void InitializeDataGridView()
{
    // 创建复选框列
    DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
    checkBoxColumn.HeaderText = "选择";
    checkBoxColumn.Width = 80;
    
    // 设置自定义表头单元格
    DatagridViewCheckBoxHeaderCell headerCell = new DatagridViewCheckBoxHeaderCell();
    headerCell.OnCheckBoxClicked += new CheckBoxClickedHandler(HeaderCheckBoxClicked);
    checkBoxColumn.HeaderCell = headerCell;
    
    // 添加其他列
    dataGridView1.Columns.Add(checkBoxColumn);
    dataGridView1.Columns.Add("Name", "姓名");
    dataGridView1.Columns.Add("Age", "年龄");
    dataGridView1.Columns.Add("Gender", "性别");
    
    // 添加示例数据
    dataGridView1.Rows.Add(false, "张三", 20, "男");
    dataGridView1.Rows.Add(false, "李四", 21, "女");
    dataGridView1.Rows.Add(false, "王五", 22, "男");
    dataGridView1.Rows.Add(false, "赵六", 23, "女");
    dataGridView1.Rows.Add(false, "孙七", 24, "男");
}

3. 订阅事件

在表单构造函数中调用初始化方法,并确保事件能够正确触发:

public Form1()
{
    InitializeComponent();
    InitializeDataGridView();
}

参考资料

posted @ 2026-02-24 11:19  (*_^)?  阅读(2)  评论(0)    收藏  举报