列头添加复选框(这个方法试过-列数不多可以用)

第一:添加列标题时,添加两个空格——用于显示复选框;
第二:实现列标题添加复选框,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void AddCheckeBoxToDGVHeader(DataGridView dgv)
{
for (int i = 0; i < this.dgvList.Columns.Count; i++)
{
System.Windows.Forms.CheckBox ckBox = new System.Windows.Forms.CheckBox();
//ckBox.Text = "全选";
ckBox.Checked = true;
System.Drawing.Rectangle rect =
dgv.GetCellDisplayRectangle(i, -1, false);
ckBox.Size = new System.Drawing.Size(25, 25);

ckBox.Location = rect.Location;
ckBox.Padding = new System.Windows.Forms.Padding(2, 6, 0, 0);
ckBox.BackColor = Color.Transparent;
ckBox.Name = dgv.Columns[i].Name;
ckBox.CheckedChanged += new EventHandler(ckBox_CheckedChanged);

dgv.Controls.Add(ckBox);
}
}

void ckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chb = sender as CheckBox;
MessageBox.Show("Test=="+ chb.Name);
}

运行效果:

在dataGridView表格中插入复选框

1
2
3
4
5
DataGridViewColumn myCol = new DataGridViewCheckBoxColumn();
myCol.Name = "SelBox"; //设置列的名称
myCol.HeaderText = "字段行的值"; //显示的列名
dataGridView1.Columns.Insert(0, myCol);//在dataGridView1的指定列添加复选框
//dataGridView1.Columns.Add(myCol); //在最后列插入复选框,可自由选择

C#DataGridViewCheckBoxColumn用法

实现功能:

点击单元格实现checkbox的勾选,点击头标题实现全选和非全选,记录选中的行数 (注意:this.dataList.RefreshEdit();//否则可能不全选)

增加一列复选框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//增加一列复选框
DataGridViewCheckBoxColumn columncb = new DataGridViewCheckBoxColumn();


/// <summary>
/// 窗体加载
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmAddOrder_Load(object sender, EventArgs e)
{

//初始化数据
this.dataList.DataSource = dataSource_NoOrder;//绑定数据源

//给datagridview加复选框的初始化
columncb.FlatStyle = FlatStyle.Standard;
columncb.HeaderText = "👆全选";
columncb.Name = "cb_check";
columncb.TrueValue = true;
columncb.FalseValue = false;
columncb.DataPropertyName = "IsChecked";
//datagridview的Name为dataList
dataList.Columns.Insert(0, columncb);

}


/// <summary>
/// 头checkbox是否选中
/// </summary>
bool headCkBoxIsChecked = false;

/// <summary>
/// 点击datagridview单元格,可以勾选该行的checkbox
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataList_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{

if (e.RowIndex == -1 && !headCkBoxIsChecked && e.ColumnIndex == 0)
{
for (int i = 0; i < dataList.Rows.Count; i++)
{
this.dataList.Rows[i].Cells["cb_check"].Value = true;
}
headCkBoxIsChecked = true;
columncb.HeaderText = "✋ 已全选";
}
else if (e.RowIndex == -1 && headCkBoxIsChecked && e.ColumnIndex == 0 )
{
for (int i = 0; i < dataList.Rows.Count; i++)
{
this.dataList.Rows[i].Cells[0].Value = false;

}
headCkBoxIsChecked = false;
columncb.HeaderText = "👆 全选";
}
else if(e.ColumnIndex == 0)
{
if ((bool)dataList.Rows[e.RowIndex].Cells["cb_check"].EditedFormattedValue == true)
{
this.dataList.Rows[e.RowIndex].Cells["cb_check"].Value = false;
}
else
{
this.dataList.Rows[e.RowIndex].Cells["cb_check"].Value = true;
}

}
this.dataList.RefreshEdit();//刷新操作,否则点击之后可能不能立即勾选
//记录选中行数
selectNum = 0;
for (int i = 0; i < this.dataList.Rows.Count; i++)
{
if ((bool)dataList.Rows[i].Cells["cb_check"].EditedFormattedValue)
{
selectNum += 1;
}
}
this.lbNum.Text = string.Format("{0} ", selectNum);

}

一个单元格添加CheckBox

把 DataGridViewCheckBoxCell 实例放在指定的单元格里

1
2
var chk = new DataGridViewCheckBoxCell();
dataGridView1.Rows[0].Cells[0] = chk;

DataGridView控件列头添加CheckBox

DataGridView控件是CS架构中用的比较频繁的一个控件,里面提供了checkbox列的功能,可是却没有在列头给出checkbox控件用于全选/全部取消所有行的功能,确实是个遗憾,这里就通过绘制实现这个功能.

添加一个帮助类

添加一个帮助类DataGridViewCheckBoxHeaderCell,用于绘制列头checkbox和创建鼠标单击事件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class DataGridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
{
public delegate void DataGridViewCheckBoxHeaderEventHander(object sender, DataGridViewCheckBoxHeaderEventArgs e);

private Point checkBoxLocation;
private Size checkBoxSize;
private bool _checked = false;
private Point _cellLocation = new Point();

private System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;

public event DataGridViewCheckBoxHeaderEventHander OnCheckBoxClicked;


//绘制列头checkbox
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) - 1; //列头checkbox的X坐标
p.Y = cellBounds.Location.Y +
(cellBounds.Height/2) - (s.Height/2); //列头checkbox的Y坐标
_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);
}

/// <summary>
/// 点击列头checkbox单击事件
/// </summary>
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;


//获取列头checkbox的选择状态
DataGridViewCheckBoxHeaderEventArgs ex = new DataGridViewCheckBoxHeaderEventArgs();
ex.CheckedState = _checked;

object sender = new object(); //此处不代表选择的列头checkbox,只是作为参数传递。应该列头checkbox是绘制出来的,无法获得它的实例

if (OnCheckBoxClicked != null)
{
OnCheckBoxClicked(sender, ex); //触发单击事件
this.DataGridView.InvalidateCell(this);
}
}
base.OnMouseClick(e);
}
}

//定义包含列头checkbox选择状态的参数类
public class DataGridViewCheckBoxHeaderEventArgs : EventArgs
{
private bool checkedState;

public bool CheckedState
{
get { return checkedState; }
set { checkedState = value; }
}
}

代码使用

在有DataGridView的界面,添加代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/// <summary>
///给DataGridView添加checkbox列头
/// </summary>
private void AddCheckboxCell()
{
DataGridViewCheckBoxHeaderCell ch = new DataGridViewCheckBoxHeaderCell();
ch.OnCheckBoxClicked += new DataGridViewCheckBoxHeaderCell.DataGridViewCheckBoxHeaderEventHander(ch_OnCheckBoxClicked);
//第一列为DataGridViewCheckBoxColumn
DataGridViewCheckBoxColumn checkboxCol = new DataGridViewCheckBoxColumn();
checkboxCol.HeaderCell = ch;
checkboxCol.HeaderCell.Value = string.Empty; //消除列头checkbox旁出现的文字
this.dgvSelectAll.Columns.Insert(0, checkboxCol);
}
void ch_OnCheckBoxClicked(object sender, DataGridViewCheckBoxHeaderEventArgs e)
{
foreach (DataGridViewRow dgvRow in this.dgvSelectAll.Rows)
{
dgvRow.Cells[0].Value = e.CheckedState;
}
this.dgvSelectAll.RefreshEdit();
}

formatted值的类型错误 System.FormatException 异常

在DataGridView手动添加了CheckBox列;在窗体Show的时候,遇到一个错误:
**错误如下: **

  • DataGridView中发生一下异常:System.FormatException:单元格的Formatted值的类型错误.要替换此默认对话框,请处理DataError事件.

点击以后有一对话框错误如下:

DataGridView中发生一下异常:

SystemArgumentException:为DataGridViewCheckBoxCell提供的值的类型错误.

在System.Windows.Forms.DataGridViewCheckBoxCell.set_EditiingCellFormattedValue(Object value)

在System.Windows.Forms.DataGridView.InitializeEditingCellValue (DataGridViewCessStyle&dataGridViewCellStyle,DataGridViewCell&dataGridViewCell)

要替换此默认对话框,请处理DataError事件.

我之前曾经用过CheckBox列,此次和之前的区别是 AllowUserToAddRows=true;
我将该属性设置为false,错误没有出现,可以确定该错误与系统自动添加的行及checBox的默认值为null有关。

我在DefaultValuesNeeded事件中增加了默认值,发现错误依旧。

仔细研究发现如下两种解决方法:

其一:在CellFormatting事件中处理

1
2
3
4
5
6
7
8
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "AZK")
{
if (e.Value == null)
e.Value = false;
}

}

其二:在在CellFormatting事件中不处理,但DataError事件中处理

1
2
3
4
{               
if (dataGridView1.Rows[e.RowIndex].IsNewRow)
return;
}

Note: DataGridView中几个事件发生的顺序记录如下,以备查寻
在AllowUserToAddRows=true时候的事件发生次序

1
Form.Show ---> CellFormatting (如果出错,goto DataError),注意这里的NewRow没有触发DefaultValuesNeeded事件。

如果发生其他比如 RowEnter事件

1
2
3
4
5
(DefaultValuesNeeded) ---> RowEnter ---> CellClick

(DefaultValuesNeeded) ---> RowsAdded ---> UserAddedRow

DefaultValuesNeeded事件不会发生在 IsNewRow=true的row上

相关链接(侵删)

  1. DateGridView标题列头添加复选框
  2. C#在dataGridView表格中插入复选框
  3. C#DataGridViewCheckBoxColumn用法(刷新操作,否则点击之后可能不能立即勾选)
  4. 如何在DataGridView中的某一个单元格添加CheckBox?
  5. C# winform单元格的formatted值的类型错误 DataGridView中CheckBox列运行时候System.FormatException异常

=================我是分割线=================

欢迎到公众号来唠嗑: