C# DataGridView 选中所有复选框

问题描述

在程序中尝试选中所有复选框,但出现错误。如果单击顶部的完整选中/释放复选框,同时选中包含复选框的列,则选定区域不会改变。该如何解决?

上面的图片是点击完整版本之后的。

下面是本文的测试代码,函数 dataGridView1_CellPainting() 和 dgvCheckBox_CheckedChanged() 用于完整检查/释放操作。

namespace TestWinForm

{

public partial class Form1 : Form

{

List<string> saved_file_names = new List<string>();

int table_index = 0;

public Form1()

{

InitializeComponent();

}

private void add_Click(object sender, EventArgs e)

{

OpenFileDialog ofd = new OpenFileDialog();

ofd.Title = "文本";

ofd.Filter = "txt | *.txt";

ofd.Multiselect = true; //

DialogResult dr = ofd.ShowDialog();

if (dr == DialogResult.OK)

{

foreach (string file_name in ofd.FileNames)

{

// 1.

if (saved_file_names.Contains(file_name))

continue;

// 2.

dataGridView1.Rows.Add();

dataGridView1.Rowstable_index.Cells1.Value = table_index + 1;

dataGridView1.Rowstable_index.Cells2.Value = file_name;

saved_file_names.Add(file_name);

dataGridView1.Rowstable_index.Cells3.Value = "none";

table_index++;

}

}

}

private void delete_Click(object sender, EventArgs e)

{

bool is_checked = false;

List<int> delete_index = new List<int>();

for (int i = 0; i < table_index; i++)

{

if (Convert.ToBoolean(dataGridView1.Rowsi.Cells0.Value) == true)

delete_index.Add(i);

}

if (delete_index.Count == 0)

return;

delete_index.Reverse();

foreach (var index in delete_index)

{

table_index--;

saved_file_names.RemoveAt(index);

dataGridView1.Rows.RemoveAt(index);

}

}

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

{

if (e.ColumnIndex == 0 && e.RowIndex == -1)

{

e.PaintBackground(e.ClipBounds, false);

Point pt = e.CellBounds.Location;

int nChkBoxWidth = 15;

int nChkBoxHeight = 15;

int offsetx = (e.CellBounds.Width - nChkBoxWidth) / 2;

int offsety = (e.CellBounds.Height - nChkBoxHeight) / 2;

pt.X += offsetx;

pt.Y += offsety;

CheckBox cb = new CheckBox();

cb.Size = new Size(nChkBoxWidth, nChkBoxHeight);

cb.Location = pt;

cb.Checked = true;

cb.CheckedChanged += new EventHandler(dgvCheckBox_CheckedChanged);

((DataGridView)sender).Controls.Add(cb);

e.Handled = true;

}

}

private void dgvCheckBox_CheckedChanged(object sender, EventArgs e)

{

foreach (DataGridViewRow r in dataGridView1.Rows)

{

r.Cells0.Value = ((CheckBox)sender).Checked;

}

}

}

}

解决方法

请考虑使用数据绑定,DataGridView这可以简化您的操作。通过定义一个Record包含属性的类,当您将该记录添加到这些记录的bool IsChecked绑定列表时,复选框行会自动创建。然后,您可以通过在记录中设置属性来操作该复选框,而无需调用 UI 对象本身。

单击标题单元格:

如果全部选中或未选中,则全部将切换。

如果混合了已选中和未选中,则所有都将被提升为已选中。

示例代码:

using System;

using System.ComponentModel;

using System.Linq;

using System.Windows.Forms;

namespace dgv_ac

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

/// <summary>

/// Wait for the main form to be created, then attach

/// your Binding List as the data source of the DGV

/// </summary>

protected override void OnHandleCreated(EventArgs e)

{

base.OnHandleCreated(e);

dataGridView1.DataSource = this.DataSource;

initDGV();

}

private void initDGV()

{

dataGridView1.AllowUserToAddRows = false;

// Now you can populate the DataGridView simply

// by adding some records to the list.

for (int i = 0; i < 5; i++)

{

DataSource.Add(new Record { Number = i, FileName = $"MyFile_{i}.txt" });

}

// Once the first record is added, the Columns information is

// available and we can do column formatting.

dataGridView1.Columnsnameof(Record.FileName).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

var checkboxColumn = dataGridView1.Columnsnameof(Record.IsChecked);

checkboxColumn.HeaderText = string.Empty;

checkboxColumn.Width = 40;

dataGridView1.CellClick += onCellClick;

dataGridView1.CellContentClick += onCellContentClick;

}

/// <summary>

/// Detect check box click and end the edit mode in this case.

/// </summary>

private void onCellContentClick(object sender, DataGridViewCellEventArgs e)

{

if(e.RowIndex != -1)

{

var cell = dataGridView1e.ColumnIndex, e.RowIndex;

if(cell is DataGridViewCheckBoxCell checkbox)

{

dataGridView1.EndEdit();

}

}

}

/// <summary>

/// Detect header click and set the records accordingly.

/// </summary>

private void onCellClick(object sender, DataGridViewCellEventArgs e)

{

if(e.RowIndex == -1)

{

switch (dataGridView1.Columnse.ColumnIndex.Name)

{

case nameof(Record.IsChecked):

if (DataSource.Any()) // Check to see if there are any records at all.

{

if(DataSource.Count(record=>record.IsChecked) == DataSource.Count)

{

// This block says thet're all chacked or all unchecked.

if(DataSource.First().IsChecked) // then they all are

{

setAll(false);

}

else

{

setAll(true);

}

}

else setAll(true); // If they're mixed, make them all checked.

}

break;

}

}

void setAll(bool value)

{

foreach (var record in DataSource)

{

record.IsChecked = value;

}

Refresh();

}

}

public BindingList<Record> DataSource = new BindingList<Record>();

}

// This is the record class that will provide column

// information to the DataGridView automatically.

public class Record

{

public int Number { get; set; }

public bool IsChecked { get; set; }

public string FileName { get; set; }

}

}

另一种方法

这种方式,本文未测试:

private void dgvCheckBox_CheckedChanged(object sender, EventArgs e)

{

foreach (DataGridViewRow r in dataGridView1.Rows)

{

if (r.Cells0 is DataGridViewCheckBoxCell checkbox)

{

dataGridViewDocuments.EndEdit();

}

r.Cells0.Value = ((CheckBox)sender).Checked;

}

}

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

相关推荐
csdn_aspnet5 小时前
C# .NetCore Swagger ISchemaFilter 注入示例值、描述
c#·.netcore·swagger
海天鹰6 小时前
C#:object.ShortcutKeys 不支持非功能单独按键
c#
下页、再停留6 小时前
【C#桌面客户端系列学习-10】连接SQLite数据库
数据库·c#·visual studio
RobinDevNotes16 小时前
一套代码发布到十几个平台:Cocos入门速览
typescript·c#·游戏开发
阿松爱学习19 小时前
【Unity开发】监听Scene场景事件
unity·c#
天天代码码天天1 天前
屏幕翻拍满是彩色条纹?用 C# + Vulkan 做了一个去摩尔纹工具,支持单图与文件夹批量
c#·去摩尔纹
2501_930707781 天前
使用C#代码在 Word 文档中添加、插入或删除页面
开发语言·c#·word
淡海水1 天前
03-03-架构篇-SGen GC架构解析
unity·架构·c#·gc·sgen
曹牧2 天前
C#:输入的字符串格式不正确
c#
根号五2 天前
JetBrains Rider 使用教程(1)新建解决方案
c#·jetbrains rider