using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; namespace TemuKJD.UserComponent { /// /// 带表头全选的选择框列 /// public class DataGridViewCheckBoxColumnSelectAll : DataGridViewCheckBoxColumn { private DatagridViewCheckBoxHeaderCell headerCell; private bool loaded; public event CheckBoxClickedHandler OnCheckBoxClicked; int TotalCheckedCheckBoxes = 0; bool IsHeaderCheckBoxClicked = false; public DataGridViewCheckBoxColumnSelectAll() { this.headerCell = new DatagridViewCheckBoxHeaderCell(); base.HeaderCell = this.headerCell; this.headerCell.OnCheckBoxClicked += new CheckBoxClickedHandler(this.headerCell_OnCheckBoxClicked); this.loaded = false; } public DataGridViewCheckBoxColumnSelectAll(bool threeState) : base(threeState) { this.headerCell = new DatagridViewCheckBoxHeaderCell(); base.HeaderCell = this.headerCell; } /// /// 在DataGridView改变时进行事件的绑定 /// protected override void OnDataGridViewChanged() { if (this.DataGridView != null) { this.DataGridView.CellValueChanged -= DataGridView_CellValueChanged; this.DataGridView.CellValueChanged += DataGridView_CellValueChanged; this.DataGridView.CurrentCellDirtyStateChanged -= DataGridView_CurrentCellDirtyStateChanged; this.DataGridView.CurrentCellDirtyStateChanged += DataGridView_CurrentCellDirtyStateChanged; } } /// /// 在复选的时候进行判断. /// /// /// void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0 && e.ColumnIndex >= 0) { if (!IsHeaderCheckBoxClicked) RowCheckBoxClick((DataGridViewCheckBoxCell)this.DataGridView[e.ColumnIndex, e.RowIndex]); } } /// /// 在复选框被选中的时候触发该事件, 该事件用于触发ValueChanged事件 /// /// /// private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (this.DataGridView.CurrentCell is DataGridViewCheckBoxCell) this.DataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); } /// /// 复选框被点击时所需要做的操作 /// /// private void RowCheckBoxClick(DataGridViewCheckBoxCell checkBox) { var head = this.headerCell as DatagridViewCheckBoxHeaderCell; if (checkBox != null) { //计算所有被选中的行的数量 if ((bool)checkBox.Value && TotalCheckedCheckBoxes < this.DataGridView.RowCount) TotalCheckedCheckBoxes++; else if (TotalCheckedCheckBoxes > 0) TotalCheckedCheckBoxes--; //当所有复选框都被选中的时候,列的头上的复选框被选中, 反之则不被选中. if (TotalCheckedCheckBoxes < this.DataGridView.RowCount) head.IsChecked = false; else if (TotalCheckedCheckBoxes == this.DataGridView.RowCount) head.IsChecked = true; //强制repained head.DataGridView.InvalidateCell(head); } } /// /// 头被选中时触发OnCheckBoxClicked事件. /// /// private void headerCell_OnCheckBoxClicked(bool state) { if (this.OnCheckBoxClicked != null) { this.OnCheckBoxClicked(state); } } public delegate void CheckBoxClickedHandler(bool state); internal class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell { private CheckBoxState _cbState = CheckBoxState.UncheckedNormal; private Point _cellLocation = new Point(); private bool _checked; private Point checkBoxLocation; private Size checkBoxSize; public bool IsChecked { get { return _checked; } set { _checked = value; if (this._checked) { this._cbState = CheckBoxState.CheckedNormal; } else { this._cbState = CheckBoxState.UncheckedNormal; } } } public event CheckBoxClickedHandler OnCheckBoxClicked; /// /// 点击列头的时候触发的事件,这里有个判断, 如果点击的位置是复选框则触发OnCheckBoxClicked事件. /// /// protected override void OnMouseClick(DataGridViewCellMouseEventArgs e) { Point point = new Point(e.X + this._cellLocation.X, e.Y + this._cellLocation.Y); if (((point.X >= this.checkBoxLocation.X) && (point.X <= (this.checkBoxLocation.X + this.checkBoxSize.Width))) && ((point.Y >= this.checkBoxLocation.Y) && (point.Y <= (this.checkBoxLocation.Y + this.checkBoxSize.Height)))) { this._checked = !this._checked; bool temp = this._checked; if (this.OnCheckBoxClicked != null) { this.OnCheckBoxClicked(this._checked); base.DataGridView.InvalidateCell(this); } foreach (DataGridViewRow row in base.DataGridView.Rows) { ((DataGridViewCheckBoxCell)row.Cells[e.ColumnIndex]).Value = temp; } base.DataGridView.RefreshEdit(); } base.OnMouseClick(e); } /// /// 绘制一个CheckBox /// protected override void Paint(Graphics graphics, Rectangle clipBounds, 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 point = new Point(); Size glyphSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal); point.X = (cellBounds.Location.X + (cellBounds.Width / 2)) - (glyphSize.Width / 2) - 1; // x位置补偿一个像素(否则在win11中偏右) point.Y = (cellBounds.Location.Y + (cellBounds.Height / 2)) - (glyphSize.Height / 2); //point.X = cellBounds.Location.X + (cellBounds.Width - glyphSize.Width) / 2; // 放一块以后除以2会有抖动 //point.Y = cellBounds.Location.Y + (cellBounds.Height - glyphSize.Height) / 2; this._cellLocation = cellBounds.Location; this.checkBoxLocation = point; this.checkBoxSize = glyphSize; if (this._checked) { this._cbState = CheckBoxState.CheckedNormal; } else { this._cbState = CheckBoxState.UncheckedNormal; } CheckBoxRenderer.DrawCheckBox(graphics, this.checkBoxLocation, this._cbState); } } } }