任何列中DataGridView标头中的复选框
实际上我已经解决了DGV标题中有复选框的问题,这里是代码
Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true); rect.Y = 3; rect.X = rect.Location.X + (rect.Width/4); CheckBox checkboxHeader = new CheckBox(); checkboxHeader.Name = "checkboxHeader"; //datagridview[0, 0].ToolTipText = "sdfsdf"; checkboxHeader.Size = new Size(18, 18); checkboxHeader.Location = rect.Location; checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged); dataGridView1.Controls.Add(checkboxHeader);
实际上首先我在我的DGV上添加了一个列,这是一个DataGridViewCheckBoxColumn,然后在添加上面代码的表单的加载中,我的问题就像你在下面看到的第一列它工作得很好,因为我可以设置rect.X in该列的代码,但是通知符列如何以编程方式知道此列标题的位置,因为日志列可以通过最大化和这些内容进行更改。
最后,我怎么能以编程的方式知道列[3]的标题位置是什么….提前谢谢
试试这个
#region GridViewCheckBoxColumn [System.Drawing.ToolboxBitmap(typeof(System.Windows.Forms.DataGridViewCheckBoxColumn))] public class GridViewCheckBoxColumn : DataGridViewCheckBoxColumn { #region Constructor public GridViewCheckBoxColumn() { DatagridViewCheckBoxHeaderCell datagridViewCheckBoxHeaderCell = new DatagridViewCheckBoxHeaderCell(); this.HeaderCell = datagridViewCheckBoxHeaderCell; this.Width = 50; //this.DataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.grvList_CellFormatting); datagridViewCheckBoxHeaderCell.OnCheckBoxClicked += new CheckBoxClickedHandler(datagridViewCheckBoxHeaderCell_OnCheckBoxClicked); } #endregion #region Methods void datagridViewCheckBoxHeaderCell_OnCheckBoxClicked(int columnIndex, bool state) { DataGridView.RefreshEdit(); foreach (DataGridViewRow row in this.DataGridView.Rows) { if (!row.Cells[columnIndex].ReadOnly) { row.Cells[columnIndex].Value = state; } } DataGridView.RefreshEdit(); } #endregion } #endregion #region DatagridViewCheckBoxHeaderCell public delegate void CheckBoxClickedHandler(int columnIndex, bool state); public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs { bool _bChecked; public DataGridViewCheckBoxHeaderCellEventArgs(int columnIndex, 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); pX = cellBounds.Location.X + (cellBounds.Width / 2) - (s.Width / 2); pY = 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(eX + _cellLocation.X, eY + _cellLocation.Y); if (pX >= checkBoxLocation.X && pX <= checkBoxLocation.X + checkBoxSize.Width && pY >= checkBoxLocation.Y && pY <= checkBoxLocation.Y + checkBoxSize.Height) { _checked = !_checked; if (OnCheckBoxClicked != null) { OnCheckBoxClicked(e.ColumnIndex, _checked); this.DataGridView.InvalidateCell(this); } } base.OnMouseClick(e); } } #endregion #region ColumnSelection class DataGridViewColumnSelector { // the DataGridView to which the DataGridViewColumnSelector is attached private DataGridView mDataGridView = null; // a CheckedListBox containing the column header text and checkboxes private CheckedListBox mCheckedListBox; // a ToolStripDropDown object used to show the popup private ToolStripDropDown mPopup; /// /// The max height of the popup /// public int MaxHeight = 300; /// /// The width of the popup /// public int Width = 200; /// /// Gets or sets the DataGridView to which the DataGridViewColumnSelector is attached /// public DataGridView DataGridView { get { return mDataGridView; } set { // If any, remove handler from current DataGridView if (mDataGridView != null) mDataGridView.CellMouseClick -= new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick); // Set the new DataGridView mDataGridView = value; // Attach CellMouseClick handler to DataGridView if (mDataGridView != null) mDataGridView.CellMouseClick += new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick); } } // When user right-clicks the cell origin, it clears and fill the CheckedListBox with // columns header text. Then it shows the popup. // In this way the CheckedListBox items are always refreshed to reflect changes occurred in // DataGridView columns (column additions or name changes and so on). void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (e.Button == MouseButtons.Right && e.RowIndex == -1 && e.ColumnIndex == 0) { mCheckedListBox.Items.Clear(); foreach (DataGridViewColumn c in mDataGridView.Columns) { mCheckedListBox.Items.Add(c.HeaderText, c.Visible); } int PreferredHeight = (mCheckedListBox.Items.Count * 16) + 7; mCheckedListBox.Height = (PreferredHeight < MaxHeight) ? PreferredHeight : MaxHeight; mCheckedListBox.Width = this.Width; mPopup.Show(mDataGridView.PointToScreen(new Point(eX, eY))); } } // The constructor creates an instance of CheckedListBox and ToolStripDropDown. // the CheckedListBox is hosted by ToolStripControlHost, which in turn is // added to ToolStripDropDown. public DataGridViewColumnSelector() { mCheckedListBox = new CheckedListBox(); mCheckedListBox.CheckOnClick = true; mCheckedListBox.ItemCheck += new ItemCheckEventHandler(mCheckedListBox_ItemCheck); ToolStripControlHost mControlHost = new ToolStripControlHost(mCheckedListBox); mControlHost.Padding = Padding.Empty; mControlHost.Margin = Padding.Empty; mControlHost.AutoSize = false; mPopup = new ToolStripDropDown(); mPopup.Padding = Padding.Empty; mPopup.Items.Add(mControlHost); } public DataGridViewColumnSelector(DataGridView dgv) : this() { this.DataGridView = dgv; } // When user checks / unchecks a checkbox, the related column visibility is // switched. void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked); } } #endregion
此解决方案适用于我,它将复选框添加到标题单元格。 你只需要实现“全部检查”方法并最终实现“on column resize”方法(用于替换中心的复选框)
// Creating checkbox without panel CheckBox checkbox = new CheckBox(); checkbox.Size = new System.Drawing.Size(15, 15); checkbox.BackColor = Color.Transparent; // Reset properties checkbox.Padding = new Padding(0); checkbox.Margin = new Padding(0); checkbox.Text = ""; // Add checkbox to datagrid cell myDataGrid.Controls.Add(checkbox); DataGridViewHeaderCell header = myDataGrid.Columns[myColumnWithCheckboxes.Index].HeaderCell; checkbox.Location = new Point( header.ContentBounds.Left + (header.ContentBounds.Right - header.ContentBounds.Left + checkbox.Size.Width) / 2, header.ContentBounds.Top + (header.ContentBounds.Bottom - header.ContentBounds.Top + checkbox.Size.Height) / 2 );
对我来说,最干净的解决方案来自“56ka”,这是我对它的升级。 通过这种方式,您可以保留排序和查看排序方向的function,并在复选框旁边添加标签,普通复选框以及它必须提供的所有内容。 在.NET Framework 4.0上为DataTable制作。 适用于DataTable和EF。
public static void AddSelectorColumn(this DataGridView dgv, int width = 50, 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; col.DisplayIndex = 0; if (addHeaderCheckBoxOverride != null) addHeaderCheckBoxOverride(col); else col.AddHeaderCheckBox(); col.Width = width; } public static CheckBox AddHeaderCheckBox(this DataGridViewColumn column, HorizontalAlignment align = HorizontalAlignment.Center, int leftBorderOffset = 0, int rightBorderOffset = 0, Func
56ka的答案对我来说是完美的。 我只是修复了位置(2px)
private CheckBox ColumnCheckbox(DataGridView dataGridView) { CheckBox checkBox = new CheckBox(); checkBox.Size = new Size(15, 15); checkBox.BackColor = Color.Transparent; // Reset properties checkBox.Padding = new Padding(0); checkBox.Margin = new Padding(0); checkBox.Text = ""; // Add checkbox to datagrid cell dataGridView.Controls.Add(checkBox); DataGridViewHeaderCell header = dataGridView.Columns[0].HeaderCell; checkBox.Location = new Point( (header.ContentBounds.Left + (header.ContentBounds.Right - header.ContentBounds.Left + checkBox.Size.Width) /2) - 2, (header.ContentBounds.Top + (header.ContentBounds.Bottom - header.ContentBounds.Top + checkBox.Size.Height) /2) - 2); return checkBox; }
public class DataGridViewEx : DataGridView { Dictionary dictionaryCheckBox = new Dictionary(); System.Drawing.Bitmap[] bmCheckBox = new System.Drawing.Bitmap[2]; bool executarValueChanged = true; public DataGridViewEx() : base() { #region CheckBox no header da coluna CheckBox chkTemp = new CheckBox(); chkTemp.AutoSize = true; chkTemp.BackColor = System.Drawing.Color.Transparent; chkTemp.Size = new System.Drawing.Size(16, 16); chkTemp.UseVisualStyleBackColor = false; bmCheckBox[0] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height); bmCheckBox[1] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height); chkTemp.Checked = false; chkTemp.DrawToBitmap(bmCheckBox[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height)); chkTemp.Checked = true; chkTemp.DrawToBitmap(bmCheckBox[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height)); #endregion } public void CheckBoxHeader(DataGridViewCheckBoxColumn column, bool enabled) { if (enabled == true) { if (dictionaryCheckBox.Any(f => f.Key == column) == false) { dictionaryCheckBox.Add(column, false); this.InvalidateCell(column.HeaderCell); } } else { dictionaryCheckBox.Remove(column); this.InvalidateCell(column.HeaderCell); } } protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e) { base.OnCellPainting(e); if (e.ColumnIndex >= 0 && e.RowIndex == -1 && dictionaryCheckBox.Any(f => f.Key == this.Columns[e.ColumnIndex]) == true) { Bitmap bmp = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0]; Rectangle imageBounds = new Rectangle(new Point(e.CellBounds.Location.X + (e.CellBounds.Width / 2) - (bmp.Size.Width / 2), e.CellBounds.Location.Y + (e.CellBounds.Height / 2) - (bmp.Size.Height / 2)), bmp.Size); e.PaintBackground(e.CellBounds, true); e.PaintContent(e.CellBounds); e.Graphics.DrawImage(bmp, imageBounds); e.Handled = true; } } protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e) { base.OnColumnHeaderMouseClick(e); if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true) { var header = this.Columns[e.ColumnIndex].HeaderCell; Bitmap img = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0]; if (e.Button == System.Windows.Forms.MouseButtons.Left && eY >= header.ContentBounds.Y + (header.Size.Height / 2) - (img.Height / 2) && eY <= header.ContentBounds.Y + (header.Size.Height / 2) + (img.Height / 2) && eX >= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) - (img.Width / 2) && eX <= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) + (img.Width / 2)) { dictionaryCheckBox[this.Columns[e.ColumnIndex]] = !dictionaryCheckBox[this.Columns[e.ColumnIndex]]; this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell); executarValueChanged = false; for (Int32 i = 0; i < this.Rows.Count; i++) { this.Rows[i].Cells[e.ColumnIndex].Value = dictionaryCheckBox[this.Columns[e.ColumnIndex]]; this.RefreshEdit(); } executarValueChanged = true; } } } protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e) { base.OnRowsAdded(e); List listColunas = this.Columns.Cast ().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList(); foreach (DataGridViewColumn coluna in listColunas) { if (dictionaryCheckBox.ContainsKey(coluna) == true) { if (dictionaryCheckBox[coluna] == true) { executarValueChanged = false; this.Rows[e.RowIndex].Cells[coluna.Index].Value = true; this.RefreshEdit(); executarValueChanged = true; } } } } protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e) { base.OnRowsRemoved(e); List listColunas = this.Columns.Cast ().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList(); foreach (DataGridViewColumn coluna in listColunas) { if (dictionaryCheckBox.ContainsKey(coluna) == true) { if (this.Rows.Count == 0) { dictionaryCheckBox[coluna] = false; this.InvalidateCell(coluna.HeaderCell); } else { Int32 numeroLinhas = this.Rows.Cast().Where(f => Convert.ToBoolean(f.Cells[coluna.Index].Value) == true).Count(); if (numeroLinhas == this.Rows.Count) { dictionaryCheckBox[coluna] = true; this.InvalidateCell(coluna.HeaderCell); } } } } } protected override void OnCellValueChanged(DataGridViewCellEventArgs e) { base.OnCellValueChanged(e); if (e.ColumnIndex >= 0 && e.RowIndex >= 0) { if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true) { if (executarValueChanged == false) { return; } Boolean existeFalse = this.Rows.Cast ().Any(f => Convert.ToBoolean(f.Cells[e.ColumnIndex].Value) == false); if (existeFalse == true) { if (dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true) { dictionaryCheckBox[this.Columns[e.ColumnIndex]] = false; this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell); } } else { dictionaryCheckBox[this.Columns[e.ColumnIndex]] = true; this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell); } } } } protected override void OnCurrentCellDirtyStateChanged(EventArgs e) { base.OnCurrentCellDirtyStateChanged(e); if (this.CurrentCell is DataGridViewCheckBoxCell) { this.CommitEdit(DataGridViewDataErrorContexts.Commit); } } }
使用:
dataGridViewEx1.CheckBoxHeader(dataGridViewEx1.Columns [0] as DataGridViewCheckBoxColumn,true);
您必须通过单击列来调用事件通过标识您单击的列,您可以访问所需的行并更改相应字段的值,例如:
private void dataGridViewOrderState_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == dataGridViewOrderState.Columns["selectedDataGridViewCheckBoxColumn"].Index) { var bid = dataGridViewOrderState.Rows[e.RowIndex]; var selectedRow = (OrderStateLocal)bid.DataBoundItem; if (selectedRow == null) return; selectedRow.Selected = !selectedRow.Selected; } }
我使用了dataGridView_CellPainting事件。
在那个事件中,我放入一个条件语句来设置我的复选框在标题单元格中的位置 – 例如第1列第0行。
CellBounds具有许多可用于设置位置的属性。 我取了单元格右边的“e.CellBounds.Right”,然后减去复选框的宽度,将复选框放在标题单元格的右上角。
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.ColumnIndex == 1 && e.RowIndex == 0) { TopCheckBox.Left = e.CellBounds.Right - 15; } }
当您删除列并在同一索引处添加另一列时,Hove错过了某些内容
在AddHeaderCheckBox函数中添加它
Action onColRemoved = () => { checkbox.Dispose(); }; dgv.ColumnRemoved += (s, e) => onColRemoved();
并修改这个:
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; } }
进入这个
foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection) dgv.Rows : dgv.SelectedRows) { if (dgv.Columns.Contains(column.Name)) { var val = row.Cells[column.Name].Value; if (!(val is bool) || !(bool) val) { allAreTrue = false; break; } } }