导读:本期聚焦于唐僧创作的《C#怎么给DataGridView添加复选框并实现表格多选功能?》,敬请观看详情。在WinForms桌面程序里,用户经常需要一次性勾选多行数据再做批量处理。如果直接手写循环去绑定控件,很容易出现列重复或状态不同步。其实DataGridView本身支持两种复选框接入方式:一种是在数据源里加布尔字段让框架自动生成CheckBox列,另一种是手动插入DataGridViewCheckBoxColumn并接管单元格状态。前者适合绑定强类型列表,后者在动态表结构下更灵活。本文用一个可运行的案例说明两种做法的差异,并给出全选、反选以及获取选中行集合的实用代码,帮助你避开常见的刷新与索引越界问题。

在C#的WinForms开发中,DataGridView是最常用的数据展示控件之一。当业务要求用户在表格中多选记录进行删除、导出或状态变更时,最直观的做法就是给每一行前面加一个复选框。很多初学者会尝试自己放一堆CheckBox控件去对齐行高,这种做法不仅布局难维护,而且滚动和分页时状态极易丢失。实际上DataGridView已经内置了对复选框列的支持,只要用对方法,几十行代码就能稳定实现多选。

C#怎么给DataGridView添加复选框并实现表格多选功能?

利用数据源布尔字段自动生成复选框列

最常见也最省事的方式,是先把数据模型定义一个布尔类型的属性,比如叫IsSelected。当我们把实现了IListBindingList的集合赋值给DataGridView的DataSource时,WinForms会自动识别布尔属性,并生成对应的DataGridViewCheckBoxColumn。这种方式的优势在于数据状态和界面完全绑定,不用手动去读写单元格的值。

下面用一个简单的用户类来做演示。我们准备了编号、名称和是否选中三个字段,其中是否选中就是布尔类型。绑定之后,用户勾选方框,底层对象的IsSelected会自动变成true,反之取消勾选也会同步改回false。这样就避免了在按钮事件里遍历控件找状态的麻烦。

需要注意一点,如果使用的是普通List<T>而不是BindingList<T>,那么在代码里修改对象的IsSelected时,界面可能不会立刻刷新。此时可以调用DataGridView.Refresh()或者改用支持通知的BindingList。对于大多数批量操作界面来说,用户手动点勾才会变,所以用List也能跑,只是程序控制选中时记得刷新。

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DgvCheckDemo
{
    public class UserItem
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsSelected { get; set; }
    }

    public partial class Form1 : Form
    {
        private DataGridView dgv;
        private List<UserItem> users;

        public Form1()
        {
            InitializeComponent();
            dgv = new DataGridView();
            dgv.Dock = DockStyle.Fill;
            this.Controls.Add(dgv);

            users = new List<UserItem>
            {
                new UserItem { Id = 1, Name = "张三", IsSelected = false },
                new UserItem { Id = 2, Name = "李四", IsSelected = false },
                new UserItem { Id = 3, Name = "王五", IsSelected = false }
            };

            // 绑定数据源,布尔属性自动变成复选框列
            dgv.DataSource = users;
        }

        // 获取所有被勾选的用户
        public List<UserItem> GetCheckedUsers()
        {
            List<UserItem> result = new List<UserItem>();
            foreach (var u in users)
            {
                if (u.IsSelected)
                {
                    result.Add(u);
                }
            }
            return result;
        }
    }
}

手动添加DataGridViewCheckBoxColumn实现灵活控制

当表格列是动态拼出来的,或者数据来自没有布尔字段的数据库查询结果时,自动生成就不太方便了。这时候可以手动创建一个DataGridViewCheckBoxColumn对象,设置好列名和标题,再把它加进Columns集合里。这样做不会依赖数据源结构,适合在已有表格右侧插入一个"选择"列的场景。

手动添加时要关注两个细节:一是把列的Width设小一点,比如40,让界面更紧凑;二是如果希望表头也能点一下全选,可以把HeaderText设成空,然后在CellClick事件里判断点击的是不是头单元格。相比自动绑定,手动列的值需要通过dgv.Rows[i].Cells["selectCol"].Value来读取,类型是object,要做真假判断时最好用Convert.ToBoolean包一层,防止null导致异常。

下面的例子展示怎么在窗体加载时给已经绑定了普通文本的DataGridView追加复选框列,并在按钮里统计选中行。可以看到,即使原始数据没有布尔字段,我们依然能用独立列完成多选,且不影响原有数据绑定逻辑。

using System;
using System.Data;
using System.Windows.Forms;

namespace DgvManualCheck
{
    public partial class Form2 : Form
    {
        private DataGridView dgv;

        public Form2()
        {
            InitializeComponent();
            dgv = new DataGridView();
            dgv.Dock = DockStyle.Fill;
            this.Controls.Add(dgv);

            // 模拟只有文本列的数据
            DataTable dt = new DataTable();
            dt.Columns.Add("Id");
            dt.Columns.Add("Product");
            dt.Rows.Add("1", "键盘");
            dt.Rows.Add("2", "鼠标");
            dt.Rows.Add("3", "显示器");
            dgv.DataSource = dt;

            // 手动插入复选框列
            DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
            chk.Name = "selectCol";
            chk.HeaderText = "选择";
            chk.Width = 40;
            dgv.Columns.Insert(0, chk);
        }

        // 统计选中行数量
        public int CountChecked()
        {
            int count = 0;
            foreach (DataGridViewRow row in dgv.Rows)
            {
                if (row.Cells["selectCol"].Value != null &&
                    Convert.ToBoolean(row.Cells["selectCol"].Value))
                {
                    count++;
                }
            }
            return count;
        }
    }
}

全选反选与获取选中行集合的实用封装

有了复选框列之后,用户通常还希望有"全选"和"反选"按钮。如果每次都去遍历所有行改单元格值,代码会散落在各个事件里。更好的做法是写一个通用方法,接收目标状态和DataGridView实例,统一处理。对于手动列,直接给Value赋true或false;对于绑定布尔字段的列,也可以绕过界面直接改数据源,再刷新。

获取选中行时,建议返回一个明确的列表而不是在循环里直接做业务,这样单元测试和后期维护都简单。下面这段代码演示了全选、反选以及导出选中行文本ID的完整逻辑。注意在改完单元格值后,如果绑定的是List,要调用dgv.Refresh();如果是手动列则无需额外刷新,控件自己会重绘。

还有一个容易踩的坑:当用户点击复选框时,CellValueChanged事件里如果又去改别的行,可能会触发递归。所以全选操作最好放在按钮点击里,而不是在某个单元格变化事件中去联动,否则界面会卡顿甚至死循环。把读写逻辑收口到几个方法里,是保持DataGridView多选功能稳定的关键。

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace DgvSelectUtil
{
    public class DgvHelper
    {
        // 全选或取消全选
        public static void SetAllChecked(DataGridView dgv, string colName, bool check)
        {
            foreach (DataGridViewRow row in dgv.Rows)
            {
                if (row.Cells[colName].ReadOnly == false)
                {
                    row.Cells[colName].Value = check;
                }
            }
            dgv.Refresh();
        }

        // 反选
        public static void ReverseChecked(DataGridView dgv, string colName)
        {
            foreach (DataGridViewRow row in dgv.Rows)
            {
                object val = row.Cells[colName].Value;
                bool cur = val != null && Convert.ToBoolean(val);
                row.Cells[colName].Value = !cur;
            }
            dgv.Refresh();
        }

        // 获取选中行的主键文本列表
        public static List<string> GetCheckedIds(DataGridView dgv, string checkCol, string idCol)
        {
            List<string> ids = new List<string>();
            foreach (DataGridViewRow row in dgv.Rows)
            {
                object val = row.Cells[checkCol].Value;
                if (val != null && Convert.ToBoolean(val))
                {
                    ids.Add(row.Cells[idCol].Value.ToString());
                }
            }
            return ids;
        }
    }
}

通过上述三种角度的实现,你可以根据项目里表格是静态还是动态、有没有现成布尔字段,来选择合适的复选框接入方案。无论哪种方式,核心都是把选中状态和数据或单元格值绑定清楚,并提供统一的全选反选入口,这样在多选批量处理需求下界面既好用又不容易出bug。

C#DataGridViewCheckBox修改时间:2026-08-17 04:40:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。