最近的一個winform的項目中,碰到datagridview控件的第一列添加全選的功能,通常這個功能,有兩種實現方式:1. 為控件添加DataGridViewCheckBoxColumn來實現,但是需要提供全選反選功能,2. 再加一個checkbox控件跟datagridview組合來實現全選反選功能。但是,感覺這兩種實現效果都不是很好。網上查資料,發現一個老外的實現方法,比較簡單通用。demo 代碼最下面的連接給出。
他的實現方式就是:DataGridViewCheckBoxColumn的父類DataGridViewColumnHeaderCell 里面有個HeaderCell的屬性,看下DataGridViewColumnHeaderCell 的繼承關系,就可以知道它繼承自DataGridViewCell類, 所以只需要重寫DataGridViewColumnHeaderCell類的paint方法,用CheckBoxRenderer畫一個Checkbox到單元格上。即可實現在datagridview的列頭增加一個全選的checkbox 。以下是實現代碼:
實現代碼
public delegate void CheckBoxClickedHandler(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 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); } }
調用方式
DataGridViewCheckBoxColumn colCB = new DataGridViewCheckBoxColumn(); DatagridViewCheckBoxHeaderCell cbHeader = new DatagridViewCheckBoxHeaderCell(); colCB.HeaderCell = cbHeader; datagridview1.Columns.Add(colCB);
cbHeader.OnCheckBoxClicked +=
new CheckBoxClickedHandler(cbHeader_OnCheckBoxClicked);
1. 我們只需要定義一個DataGridViewCheckBoxColumn。
2. 然后為每一行的checkbox 定義一個CheckboxClicked 事件。
測試程序
創建一個Winform 項目,加個datagridview控件,初始化幾行默認數據。注意:datagirdview有編輯狀態,如果有一行數據在編輯狀態,那這一行被編輯。
解決辦法就是在事件的綁定方法里面增加EndEdit()調用。
public partial class Form1 : Form { public Form1() { InitializeComponent(); InitDtSource(); } private void cbHeader_OnCheckBoxClicked(bool state) { //這一句很重要結束編輯狀態 dgInfo.EndEdit(); dgInfo.Rows.OfType<DataGridViewRow>().ToList().ForEach(t => t.Cells[0].Value = state); } private void InitDtSource() { try { var _dtSource = new DataTable(); //1、添加列 _dtSource.Columns.Add("姓名", typeof(string)); //數據類型為 文本 _dtSource.Columns.Add("身份證號", typeof(string)); //數據類型為 文本 _dtSource.Columns.Add("時間", typeof(string)); //數據類型為 文本 _dtSource.Columns.Add("地點", typeof(string)); //數據類型為 文本 for (int i = 0; i < 10; i++) { DataRow drData = _dtSource.NewRow(); drData[0] = "test" + i; drData[1] = "35412549554521263" + i; drData[2] = "2017-05-21 10:55:21"; drData[3] = "北京市"; _dtSource.Rows.Add(drData); } dgInfo.DataSource = _dtSource; InitColumnInfo(); } catch (Exception ex) { } } private void InitColumnInfo() { int index = 0; DataGridViewCheckBoxColumn colCB = new DataGridViewCheckBoxColumn(); DatagridViewCheckBoxHeaderCell cbHeader = new DatagridViewCheckBoxHeaderCell(); colCB.HeaderCell = cbHeader; colCB.HeaderText = "全選"; cbHeader.OnCheckBoxClicked += new CheckBoxClickedHandler(cbHeader_OnCheckBoxClicked); dgInfo.Columns.Insert(index, colCB); index++; dgInfo.Columns[index].HeaderText = "姓名"; dgInfo.Columns[index].Width = 90; index++; dgInfo.Columns[index].HeaderText = "身份證號"; dgInfo.Columns[index].Width = 120; index++; dgInfo.Columns[index].HeaderText = "時間"; dgInfo.Columns[index].Width = 150; index++; dgInfo.Columns[index].HeaderText = "地點"; dgInfo.Columns[index].Width = 100; System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleCenter;//211, 223, 240 dataGridViewCellStyle2.ForeColor = System.Drawing.Color.Blue; dataGridViewCellStyle2.SelectionForeColor = System.Drawing.Color.Blue; dgInfo.Columns[index].DefaultCellStyle = dataGridViewCellStyle2; } }
其他
1. 參考地址:https://www.codeproject.com/Articles/20165/CheckBox-Header-Column-For-DataGridView
2. Demo下載