using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TemuKJD.Extension { public static class DataGridViewExtension { public static object GetCellValueFromColumnName(this DataGridViewCellCollection CellCollection, string name) { return CellCollection.Cast().FirstOrDefault(c => c.OwningColumn.Name == name)?.Value; } public static CheckBox AddSelectorColumn(this DataGridView dgv, string columnName = "Selected", Action addHeaderCheckBoxOverride = null) { if (dgv.Columns[columnName] == null) { //var dt = dgv.Table(); //var dcol = new DataColumn(columnName, typeof(bool)); //dt.Columns.Add(dcol); //dt.ColumnChanged += (s, e) => //{ // var chCols = e.Row.GetChangedColumns(); // if (chCols.Count == 1 && chCols[0].Equals(dcol)) // e.Row.AcceptChanges(); //}; } var col = dgv.Columns[columnName]; col.HeaderText = ""; col.ReadOnly = false; if (addHeaderCheckBoxOverride != null) { addHeaderCheckBoxOverride(col); return null; } else { return col.AddHeaderCheckBox(); } } public static CheckBox AddHeaderCheckBox(this DataGridViewColumn column, HorizontalAlignment align = HorizontalAlignment.Center, int leftBorderOffset = 0, int rightBorderOffset = 0, Func getValue = null, Action setValue = null, bool isSetCheckedChangedEvent = true, CheckBox checkBox = null, bool isClearHeaderText = false) { if (column?.DataGridView == null) //throw new ArgumentNullException("First you need to add the column to grid."); MessageBox.Show("DataGridView中没有对应的CheckBox列"); // Creating checkbox without panel if (checkBox == null) { checkBox = new CheckBox(); checkBox.Name = "chk" + column.Name; } checkBox.Size = new Size(15, 15); checkBox.BackColor = Color.Transparent; checkBox.Enabled = true; // Reset properties checkBox.Padding = new Padding(0); checkBox.Margin = new Padding(0); checkBox.Text = ""; if (isClearHeaderText) column.HeaderText = ""; var changedByUser = true; var dgv = column.DataGridView; if (isSetCheckedChangedEvent) { checkBox.CheckedChanged += (s, e) => { if (changedByUser) { try { changedByUser = false; if (dgv.IsCurrentCellInEditMode && dgv.CurrentCell.OwningColumn.Name.Equals(column.Name)) dgv.EndEdit(); var dgvRows = new List((dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows).Cast()); if (column.IsDataBound) { //adding to list because of BindingSource sort by that column var boundItems = new List(); var areDataRows = dgvRows.Count < 1 || dgvRows[0].DataBoundItem is DataRowView; if (areDataRows) { foreach (DataGridViewRow row in dgvRows) boundItems.Add(((DataRowView)row.DataBoundItem).Row); foreach (DataRow dr in boundItems) { var val = dr[column.DataPropertyName]; if ((val is bool && (bool)val) != checkBox.Checked) dr[column.DataPropertyName] = checkBox.Checked; } } else { foreach (DataGridViewRow row in dgvRows) boundItems.Add(row.DataBoundItem); foreach (var item in boundItems) { var val = getValue(item); if (val != checkBox.Checked) setValue(item, checkBox.Checked); } } } else { foreach (DataGridViewRow dgr in dgvRows) { var cell = dgr.Cells[column.Name]; if ((cell.Value is bool && (bool)cell.Value) != checkBox.Checked) cell.Value = checkBox.Checked; } } } finally { changedByUser = true; } } }; } // Add checkbox to datagrid cell dgv.Controls.Add(checkBox); Action onColResize = () => { var colCheck = dgv.Columns[column.Name]; if (colCheck == null) return; int colLeft = (dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0) - (colCheck.Frozen ? 0 : dgv.HorizontalScrollingOffset); foreach (DataGridViewColumn col in dgv.Columns) { if (col.DisplayIndex >= colCheck.DisplayIndex) break; if (!col.Visible) continue; colLeft += col.Width; } var newPoint = new Point(colLeft, dgv.ColumnHeadersHeight / 2 - checkBox.Height / 2); if (align == HorizontalAlignment.Left) newPoint.X += 3; else if (align == HorizontalAlignment.Center) newPoint.X += colCheck.Width / 2 - checkBox.Width / 2; else if (align == HorizontalAlignment.Right) newPoint.X += colCheck.Width - checkBox.Width - 3; var minLeft = colLeft + leftBorderOffset; var maxLeft = colLeft + colCheck.Width - checkBox.Width + rightBorderOffset; if (newPoint.X < minLeft) newPoint.X = minLeft; if (newPoint.X > maxLeft) newPoint.X = maxLeft; checkBox.Location = newPoint; checkBox.Visible = colCheck.Visible; }; dgv.ColumnWidthChanged += (s, e) => onColResize(); dgv.ColumnHeadersHeightChanged += (s, e) => onColResize(); dgv.Scroll += (s, e) => onColResize(); dgv.Resize += (s, e) => onColResize(); dgv.Sorted += (s, e) => onColResize(); dgv.RowHeadersWidthChanged += (s, e) => onColResize(); dgv.ColumnStateChanged += (s, e) => onColResize(); Action onDataChanged = (e) => { if (!changedByUser) return; if (e is DataColumnChangeEventArgs) { if (!((DataColumnChangeEventArgs)e).Column.ColumnName.Equals(column.Name)) return; } else if (e is ListChangedEventArgs) { var prop = ((ListChangedEventArgs)e).PropertyDescriptor; if (prop != null && !prop.Name.Equals(column.DataPropertyName)) return; } bool allAreTrue = true; foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows) { var val = row.Cells[column.Name].Value; if (!(val is bool) || !(bool)val) { allAreTrue = false; break; } } try { changedByUser = false; var tag = checkBox.Tag; checkBox.Tag = "AUTO"; try { if (isSetCheckedChangedEvent) { checkBox.Checked = allAreTrue; } } finally { checkBox.Tag = tag; } } finally { changedByUser = true; } }; dgv.CellClick += (s, e) => onDataChanged(e); dgv.CellContentClick += (s, e) => onDataChanged(e); dgv.SelectionChanged += (s, e) => onDataChanged(e); if (dgv.DataSource is BindingSource) ((BindingSource)dgv.DataSource).ListChanged += (s, e) => onDataChanged(e); else if (dgv.DataSource is DataSet) ((DataSet)dgv.DataSource).Tables[dgv.DataMember].ColumnChanged += (s, e) => onDataChanged(e); else if (dgv.DataSource is DataTable) ((DataTable)dgv.DataSource).ColumnChanged += (s, e) => onDataChanged(e); onColResize(); return checkBox; } } }