上次从CodeProject上发现了一个老外写的开源的带CheckBox列头的类,当时就将文章翻译了过来并做成了一个小Demo,供大家参考,最近在开发中需要用到这个类,因此加以了改进,上次还有一个兄弟提到问怎样实现取消列表中选择的一行,列头的全选CheckBox也能处于不选中状态。这是一个很好的问题,我最近几天花了些时间,将其进行了些修改。终于可以实现这一功能了。废话不多说了,代码如下:
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Windows.Forms;namespace chbDGV
{ public delegate void CheckBoxClickedHandler(bool state);/// <summary>
/// 改变列头的CheckBox的状态 /// </summary> /// <param name="state"></param> public delegate void ChangeCheckBoxStatusHandler(bool state);public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs
{ bool _bChecked; public DataGridViewCheckBoxHeaderCellEventArgs(bool bChecked) { _bChecked = bChecked; }public bool Checked
{ get { return _bChecked; } } } class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell { Point checkBoxLocation; Size checkBoxSize; bool _checked = false; Point _cellLocation = new Point(); System.Windows.Forms.VisualStyles.CheckBoxState _cbState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal; public event CheckBoxClickedHandler OnCheckBoxClicked; public event ChangeCheckBoxStatusHandler OnChangeCheckBoxStatusHandler;public DatagridViewCheckBoxHeaderCell()
{ }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); p.Y = cellBounds.Location.Y + (cellBounds.Height / 2) - (s.Height / 2); _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); }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; if (OnCheckBoxClicked != null) { OnCheckBoxClicked(_checked); this.DataGridView.InvalidateCell(this); }}
base.OnMouseClick(e); }/// <summary>
/// 改变列头CheckBox的状态的事件 /// </summary> /// <param name="NewStatus"></param> public void OnChangeCheckBoxStatus(bool NewStatus) { if (OnCheckBoxClicked != null) { _checked = NewStatus; if (OnChangeCheckBoxStatusHandler != null) { OnChangeCheckBoxStatusHandler(NewStatus); } if (this.DataGridView != null) { this.DataGridView.InvalidateCell(this); } } }}
}测试的代码如下:
using System;
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace chbDGV
{ public partial class frmTestDGV : Form {DataGridViewCheckBoxColumn colCB = new DataGridViewCheckBoxColumn();
DatagridViewCheckBoxHeaderCell cbHeader = new DatagridViewCheckBoxHeaderCell(); DataTable dt = new DataTable();public frmTestDGV()
{ InitializeComponent(); }private void Form1_Load(object sender, EventArgs e)
{ BindDGV(); }public override void Refresh()
{base.Refresh();
}private void cbHeader_OnCheckBoxClicked(bool Status)
{ for (int i = 0; i < dgvTest.Rows.Count; i++) { dt.Rows[i]["Select"] = Status; } }private void BindDGV()
{ dt.Columns.Add("Select"); dt.Columns.Add("ID"); dt.Columns.Add("Code"); dt.Columns.Add("Name"); dt.Columns.Add("Desc"); for (int i = 0; i < 5; i++) { dt.Rows.Add(); dt.Rows[i][0] = false; dt.Rows[i][1] = "100"+i.ToString(); dt.Rows[i][2] = "Lucy1001"+i.ToString(); dt.Rows[i][3] = "KateTest"+i.ToString(); dt.Rows[i][4] = "remark..."; }colCB.HeaderCell = cbHeader;
dgvTest.Columns.Insert(0, colCB);cbHeader.OnCheckBoxClicked +=
new CheckBoxClickedHandler(cbHeader_OnCheckBoxClicked);dgvTest.AllowUserToAddRows = false;
dgvTest.AutoGenerateColumns = false; dgvTest.DataSource = dt; this.colCB.DataPropertyName = "Select"; this.ID.DataPropertyName = "ID"; this.Code.DataPropertyName = "Code"; this.TestName.DataPropertyName = "Name"; this.Desc.DataPropertyName = "Desc"; }/// <summary>
/// 点击DataGridView的行 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void dgv_CellClick(object sender, DataGridViewCellEventArgs e) { DataGridView dgvv = ((DataGridView)sender); if (dgvTest.CurrentCell.OwningColumn.DataPropertyName == "Select") { if (e.RowIndex != -1) { this.SetSelected(dgvv, e.RowIndex); } } }/// <summary>
/// 设置DataGridView的选择 /// </summary> /// <param name="dgvb"></param> /// <param name="rowIndex"></param> private void SetSelected(DataGridView dgvb, int rowIndex) { if (dgvb.Rows[rowIndex] != null) { if (dgvb.Rows[rowIndex].Cells[0].Value != null && dgvb.Rows[rowIndex].Cells[0].Value.ToString() != "") { bool status = !Convert.ToBoolean(dgvb.Rows[rowIndex].Cells[0].Value); dt.Rows[rowIndex][0] = status; dgvb.Rows[rowIndex].Cells[0].Value = status; for (int i = 0; i < dgvb.Rows.Count; i++) { if (dgvb.Rows[i].Cells[0].Value != null && dgvb.Rows[i].Cells[0].Value.ToString() != "") { status = Convert.ToBoolean(dgvb.Rows[i].Cells[0].Value); if (!status) { cbHeader.OnChangeCheckBoxStatus(status); break; } } } if (status) { cbHeader.OnChangeCheckBoxStatus(status); } dgvb.EndEdit(); } else { bool status1 = false; dgvb.Rows[rowIndex].Cells[0].Value = dt.Rows[rowIndex][0].ToString(); for (int i = 0; i < dgvb.Rows.Count; i++) { if (dgvb.Rows[i].Cells[0].Value != null && dgvb.Rows[i].Cells[0].Value.ToString() != "") { status1 = Convert.ToBoolean(dgvb.Rows[i].Cells[0].Value); if (!status1) { cbHeader.OnChangeCheckBoxStatus(status1); break; } } } if (status1) { cbHeader.OnChangeCheckBoxStatus(status1); } dgvb.EndEdit(); } } }}
}代码比较简单,我就没有加很多注释,也不介绍了。代码我会放在我的资源中供大家下载,资源名为:二。