原文链接:http://www.codeproject.com/Articles/42437/Toggling-the-States-of-all-CheckBoxes-Inside-a-Dat
1、 指定DataGridView的第一列为DataGridViewCheckBoxColumn
2、 为第一列的标题栏添加一个CheckBox,假设为HeaderCheckBox
同时为HeaderCheckBox定义好 MouseClick 和 KeyUp 事件
private void frmSelectAll_Load(object sender, EventArgs e)
{
…
AddHeaderCheckBox();
HeaderCheckBox.KeyUp += new KeyEventHandler(HeaderCheckBox_KeyUp);
HeaderCheckBox.MouseClick += new MouseEventHandler(HeaderCheckBox_MouseClick);
…
}
private void AddHeaderCheckBox()
{
HeaderCheckBox = new CheckBox();
HeaderCheckBox.Size = new Size(15, 15);
//Add the CheckBox into the DataGridView
this.dgvSelectAll.Controls.Add(HeaderCheckBox);
}
private void HeaderCheckBox_MouseClick(object sender, MouseEventArgs e)
{
HeaderCheckBoxClick((CheckBox)sender);
}
private void HeaderCheckBox_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Space)
HeaderCheckBoxClick((CheckBox)sender);
}
private void HeaderCheckBoxClick(CheckBox HCheckBox)
{
IsHeaderCheckBoxClicked = true;
foreach (DataGridViewRow Row in dgvSelectAll.Rows)
((DataGridViewCheckBoxCell)Row.Cells[0]).Value = HCheckBox.Checked;
dgvSelectAll.RefreshEdit();
TotalCheckedCheckBoxes = HCheckBox.Checked ? TotalCheckBoxes : 0;
IsHeaderCheckBoxClicked = false;
}
3、 以上代码发现HeaderCheckBox不在正确的位置显示
所以添加绘制代码,调整位置
private void frmSelectAll_Load(object sender, EventArgs e)
{
...
dgvSelectAll.CellPainting += new DataGridViewCellPaintingEventHandler(dgvSelectAll_CellPainting);
...
}
private void dgvSelectAll_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == -1 && e.ColumnIndex == 0)
ResetHeaderCheckBoxLocation(e.ColumnIndex, e.RowIndex);
}
private void ResetHeaderCheckBoxLocation(int ColumnIndex, int RowIndex)
{
//Get the column header cell bounds
Rectangle oRectangle = this.dgvSelectAll.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);
Point oPoint = new Point();
oPoint.X = oRectangle.Location.X + (oRectangle.Width - HeaderCheckBox.Width) / 2 + 1;
oPoint.Y = oRectangle.Location.Y + (oRectangle.Height - HeaderCheckBox.Height) / 2 + 1;
//Change the location of the CheckBox to make it stay on the header
HeaderCheckBox.Location = oPoint;
}
4、 到此为止,第一列的显示,全选/全不选功能已经做好
此时,如果DataGridView的ReadOnly为True,则发现点击CheckBox,无法修改其选中状态
而设置ReadOnly为false,则发现可以修改CheckBox的状态,但是DataGridView处于编辑状态
private void frmSelectAll_Load(object sender, EventArgs e)
{
...
dgvSelectAll.CurrentCellDirtyStateChanged += new EventHandler(dgvSelectAll_CurrentCellDirtyStateChanged);
...
}
private void dgvSelectAll_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgvSelectAll.CurrentCell is DataGridViewCheckBoxCell)
dgvSelectAll.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
注意:如果仅希望第一列可以修改,其他列不能修改,可以把其他列设置为只读
5、 单击HeaderCheckBox,让DataGridView处于全选状态
然后取消部分记录的选中状态,此时HeaderCheckBox仍然为选中状态,而不是预期中的非选中状态
private void frmSelectAll_Load(object sender, EventArgs e)
{
...
dgvSelectAll.CellValueChanged += new DataGridViewCellEventHandler(dgvSelectAll_CellValueChanged);
...
}
private void dgvSelectAll_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (!IsHeaderCheckBoxClicked)
RowCheckBoxClick((DataGridViewCheckBoxCell)dgvSelectAll[e.ColumnIndex, e.RowIndex]);
}
private void RowCheckBoxClick(DataGridViewCheckBoxCell RCheckBox)
{
if (RCheckBox != null)
{
//Modifiy Counter;
if ((bool)RCheckBox.Value && TotalCheckedCheckBoxes < TotalCheckBoxes)
TotalCheckedCheckBoxes++;
else if (TotalCheckedCheckBoxes > 0)
TotalCheckedCheckBoxes--;
//Change state of the header CheckBox.
if (TotalCheckedCheckBoxes < TotalCheckBoxes)
HeaderCheckBox.Checked = false;
else if (TotalCheckedCheckBoxes == TotalCheckBoxes)
HeaderCheckBox.Checked = true;
}
}
6、
IsHeaderCheckBoxClicked的作用
因为HeaderCheckBox状态的改变,会触发DataGridView的CellValueChanged事件
而DataGridView的CellValueChanged事件也会导致HeaderCheckBox状态修改
所以,这里用了一个全局变量,来避免程序进入死循环