如何获取DataGridView中选中复选框对应行数据并存入数组?
解决DataGridView CheckBox列选中行数据收集的问题
我来帮你分析两段代码的问题,再给出靠谱的解决方案。
第一段代码的问题
先看你这段代码:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { foreach (DataGridViewRow row in this.dataGridView1.Rows) { if (Convert.ToBoolean(this.dataGridView1.Rows[e.RowIndex].Cells["chkBoxColumn"].Value = true) == true) { MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString()); } } }
这里有两个关键错误:
- 循环没用到当前遍历的row:你在循环里一直操作
e.RowIndex对应的行(也就是触发事件的那一行),所以循环多少次就会弹多少次这一行的内容,自然会重复弹出最后选中项。 - 赋值操作代替了判断:
Value = true是把CheckBox的值强制设为true,而不是判断它是否为true,这会导致所有点击都会把当前CheckBox设为选中,逻辑完全错了。
第二段代码的问题
再看这段:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { for (int i = 0; i < dataGridView1.Rows.Count; i++) { if (bool.Parse(dataGridView1.Rows[i].Cells["chkBoxColumn"].Value.ToString()) == true) { MessageBox.Show(dataGridView1.Rows[i].Cells[1].Value.ToString()); } } }
空引用异常的原因很明确:
- DataGridView默认会在最后一行显示一个新行(
IsNewRow为true),这一行的CheckBox值是null,调用Value.ToString()直接就会抛出空引用。 - 就算不是新行,当CheckBox没被点击过的时候,Value也可能是
null,bool.Parse同样会报错。
正确的实现方式
我们需要安全判断CheckBox状态,同时收集选中行到数组里,代码如下:
1. 核心事件代码
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // 只处理CheckBox列的变化,避免其他列触发无效操作 if (e.ColumnIndex == dataGridView1.Columns["chkBoxColumn"].Index && e.RowIndex >= 0) { // 用List临时存储选中行,最后转成数组 List<DataGridViewRow> selectedRowsList = new List<DataGridViewRow>(); foreach (DataGridViewRow row in dataGridView1.Rows) { // 跳过新行,避免空引用 if (row.IsNewRow) continue; // 安全判断CheckBox的值:先检查Value是否为null,再转换 bool isChecked = false; if (row.Cells["chkBoxColumn"].Value != null) { isChecked = Convert.ToBoolean(row.Cells["chkBoxColumn"].Value); } if (isChecked) { selectedRowsList.Add(row); } } // 转换为数组,这就是你需要的选中行数组 DataGridViewRow[] selectedRowsArray = selectedRowsList.ToArray(); // 测试输出:遍历数组显示每行第2列内容(处理空值避免报错) foreach (var row in selectedRowsArray) { string cellValue = row.Cells[1].Value?.ToString() ?? "该单元格为空"; MessageBox.Show(cellValue); } } }
2. 额外优化:解决CheckBox点击不立即触发事件的问题
默认情况下,DataGridView的CheckBox需要点击两次才会触发CellValueChanged,我们可以加一个事件来修复这个问题:
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dataGridView1.IsCurrentCellDirty && dataGridView1.CurrentCell is DataGridViewCheckBoxCell) { // 立即提交单元格编辑状态 dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); } }
记得在窗体设计器里把这个事件绑定到DataGridView上,或者在构造函数里手动绑定:
public YourForm() { InitializeComponent(); dataGridView1.CurrentCellDirtyStateChanged += dataGridView1_CurrentCellDirtyStateChanged; }
这样修改后,就能完美解决你遇到的重复弹窗和空引用问题,正确收集所有选中行到数组中了。
内容的提问来源于stack exchange,提问作者Dhenz
相关产品推荐
相关产品推荐

