Actually I have solved the problem of having checkbox in the header of a DGV, here is the code
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);
Actually First I add a column to my DGV which is a DataGridViewCheckBoxColumn and then in the load of the form adding the code above, my problem is as you can see below for the first column it works great since I can set the rect.X in the code for that column but what about the notifier column how can I know where is the position of the header of this column programmatically since the log column can change through maximizing and this stuffs.
Finally, How can I know for example what is the position of the header of the column[3] programatically.... Thanks in advance
try this
#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);
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(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;
/// <summary>
/// The max height of the popup
/// </summary>
public int MaxHeight = 300;
/// <summary>
/// The width of the popup
/// </summary>
public int Width = 200;
/// <summary>
/// Gets or sets the DataGridView to which the DataGridViewColumnSelector is attached
/// </summary>
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(e.X, e.Y)));
}
}
// 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
This solution works for me, it adds the checkbox to the header cell. You just have to implement the "check all" method and eventually a "on column resize" method (for replace checkbox in the center)
// 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
);
The Answer of 56ka is perfekt for me. I just fix the location (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;
}
To me, cleanest solution is from "56ka" and this is my upgrade on it. With this, you retain an ability to sort and see the sort direction and to have a label next to the checkbox, normal checkbox and all it has to offer. Made on .NET Framework 4.0 for DataTable. Works with DataTable and EF.
public static void AddSelectorColumn(this DataGridView dgv, int width = 50, string columnName = "Selected", Action<DataGridViewColumn> 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<object, bool> getValue = null, Action<object, bool> setValue = null)
{
if (column.DataGridView == null) throw new ArgumentNullException("First you need to add the column to grid.");
// Creating checkbox without panel
CheckBox checkbox = new CheckBox();
checkbox.Name = "chk" + column.Name;
checkbox.Size = new Size(15, 15);
checkbox.BackColor = Color.Transparent;
checkbox.Enabled = !column.ReadOnly;
// Reset properties
checkbox.Padding = new Padding(0);
checkbox.Margin = new Padding(0);
checkbox.Text = "";
var changedByUser = true;
var dgv = column.DataGridView;
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<DataGridViewRow>((dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows).Cast<DataGridViewRow>());
if (column.IsDataBound)
{
//adding to list because of BindingSource sort by that column
var boundItems = new List<object>();
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<object> 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
{
checkbox.Checked = allAreTrue;
}
finally { checkbox.Tag = tag; }
}
finally
{
changedByUser = true;
}
};
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);
return checkbox;
}
public class DataGridViewEx : DataGridView
{
Dictionary<DataGridViewColumn, bool> dictionaryCheckBox = new Dictionary<DataGridViewColumn, bool>();
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 &&
e.Y >= header.ContentBounds.Y + (header.Size.Height / 2) - (img.Height / 2) &&
e.Y <= header.ContentBounds.Y + (header.Size.Height / 2) + (img.Height / 2) &&
e.X >= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) - (img.Width / 2) &&
e.X <= 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<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().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<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().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<DataGridViewRow>().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<DataGridViewRow>().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);
}
}
}
use:
dataGridViewEx1.CheckBoxHeader(dataGridViewEx1.Columns[0] as DataGridViewCheckBoxColumn, true);
You must call the event click on the column By identifying the column you clicked, you can access the desired row and change the value of the corresponding field for example:
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;
}
}
private void AddHeaderCheckbox()
{
CheckBox cb = new CheckBox();
// your checkbox size
cb.Size = new Size(15, 15);
// datagridview checkbox header column cell size
var cell = dgv.Columns[0].HeaderCell.Size;
// calculate location
cb.Location = new Point((cell.Width - cb.Size.Width) / 2, (cell.Height - cb.Size.Height) / 2);
dgv.Controls.Add(cb);
}
I used the dataGridView_CellPainting event.
On that event I put in a conditional statement to set the location of my checkbox within the header cell - eg column 1 row 0.
CellBounds has a number of properties that can be used in setting the location. I took the right of the cell "e.CellBounds.Right" and then subtracted the width of the checkbox to put the checkbox in the right corner of the header cell.
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 1 && e.RowIndex == 0)
{
TopCheckBox.Left = e.CellBounds.Right - 15;
}
}
Hove missed something when you remove a column and add another at the same index
add this in the AddHeaderCheckBox function
Action onColRemoved = () =>
{
checkbox.Dispose();
};
dgv.ColumnRemoved += (s, e) => onColRemoved();
and modify this :
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;
}
}
into this
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;
}
}
}
this is another solution for the same problem. All you have to do is calling the constructor like showed following.
new ColocarHeaderCheckBox(dataGridView1, colActivo.Index);
Saludos.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Util
{
public class ColocarHeaderCheckBox
{
CheckBox headerCheckBox = new CheckBox();
int columnIndex = 0;
DataGridView dgv;
/// <summary>
/// Coloca un CheckBox en el Header del Datagriview para seleccionar o
/// deseleccionar todas las filas a la vez.
/// </summary>
/// <param name="dgv"></param>
/// <param name="columnIndex"></param>
/// (2022-08-29) Editado por Kong Fan
/// TODO
/// Falta hacer que el cuadro de checkbox pueda cambiar de tamano
public ColocarHeaderCheckBox(DataGridView dgv, int columnIndex)
{
// *** Asegurarse de que sea posible utilizar el HeaderCheckBox
if (!dgv.ColumnHeadersVisible) return;
if (!dgv.Columns[columnIndex].Visible) return;
if (dgv.Columns[columnIndex].CellType != typeof(DataGridViewCheckBoxCell)) return;
// *** Recibir parámetros
this.columnIndex = columnIndex;
this.dgv = dgv;
// *** Crear el HeaderCheckBox y enlazar eventos
CrearCheckBox();
// *** Muestra el estado inicial del HeaderCheckBox
CambiarEstadoHeaderCheckBox(this.dgv);
// *** Evento para controlar el scroll horizontal
dgv.Scroll += new ScrollEventHandler(Dgv_Scrolled);
}
private void Dgv_Scrolled(object sender, ScrollEventArgs e)
{
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
{
// *** Si se mueve el scroll vuelve a crear el control
dgv.Controls.Remove(headerCheckBox);
if (!CrearCheckBox()) dgv.Controls.Remove(headerCheckBox);
}
}
private bool CrearCheckBox()
{
int anchoCuadro = 14;
int altoCuadro = 14;
int anchoCelda = dgv.Columns[columnIndex].Width;
int altoCelda = dgv.ColumnHeadersHeight;
// *** Determinar la ubicación de la esquina superior izquierda de las columnas adyacentes
Point columnaUbicacion = dgv.GetColumnDisplayRectangle(columnIndex, true).Location;
Point columnaAntesUbicacion = new Point();
Point columnaDespuesUbicacion = new Point();
// *** Tomar ubicaciones de columnas antes y despues de la columna designada
bool tieneAntes = false;
bool tieneDespues = false;
for (int i = 0; i < dgv.Columns.Count; i++)
{
if (dgv.Columns[i].Visible && i < columnIndex && !tieneAntes)
{
columnaAntesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
tieneAntes = true;
}
if (dgv.Columns[i].Visible && i > columnIndex && !tieneDespues)
{
columnaDespuesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
tieneDespues = true;
}
}
// *** Comprobar si hay espacio para crear el control
if ((columnaDespuesUbicacion.X - columnaUbicacion.X) < (anchoCelda + anchoCuadro) / 2
&& dgv.FirstDisplayedScrollingColumnIndex != columnIndex)
return false;
if ((dgv.Width - columnaAntesUbicacion.X) < ((anchoCelda + anchoCuadro) / 2))
return false;
// *** Centrar la posición del headerCheckBox y el alto de la casilla
int posicionX = 0;
if (columnaDespuesUbicacion.X != 0)
posicionX = columnaDespuesUbicacion.X - (anchoCelda + anchoCuadro) / 2;
else
posicionX = columnaUbicacion.X + (anchoCelda - anchoCuadro) / 2;
if (altoCelda < (altoCuadro - 1)) altoCuadro = altoCelda - 2;
int posicionY = (altoCelda - altoCuadro) / 2 + 1;
// *** Agregar el control a la DataGridView
headerCheckBox.Location = new Point(posicionX, posicionY);
headerCheckBox.BackColor = Color.White;
headerCheckBox.Size = new Size(anchoCuadro, altoCuadro);
headerCheckBox.ThreeState = true;
dgv.Controls.Add(headerCheckBox);
// *** Asignar evento Click al headerCheckBox
headerCheckBox.Click += new EventHandler(HeaderCheckBox_Clicked);
// *** Asignar evento Click a las casillas de datos del DataGridView
dgv.CellContentClick += new DataGridViewCellEventHandler(DataGridView_CellClick);
return true;
}
private void HeaderCheckBox_Clicked(object sender, EventArgs e)
{
// *** Extraer del parámetro el sender.Parent la DataGriView
DataGridView dgv = (DataGridView)((CheckBox)sender).Parent;
// *** Necesario para finalizar cualquier edición
dgv.EndEdit();
// *** Recorrer todas las filas de la columna para checkar todos o ninguno
foreach (DataGridViewRow row in dgv.Rows)
{
if (headerCheckBox.CheckState == CheckState.Checked)
{
(row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = true;
headerCheckBox.Checked = true;
}
else
{
(row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = false;
headerCheckBox.Checked = false;
}
}
}
private void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = sender as DataGridView;
// *** Comprobar si está haciendo Click en la fila correcta
if (e.RowIndex >= 0 && e.ColumnIndex == columnIndex)
// *** Cambiar el estado del headerCheckBox
CambiarEstadoHeaderCheckBox(dgv);
}
private void CambiarEstadoHeaderCheckBox(DataGridView dgv)
{
int positivos = 0;
int negativos = 0;
int totalFilas = dgv.RowCount;
int contador = 0;
// *** Recorrer todas las filas y determinar uno de los 3 estados del headerCheckBox
foreach (DataGridViewRow fila in dgv.Rows)
{
contador++;
if ((bool)fila.Cells[columnIndex].EditedFormattedValue == true)
{
positivos++;
}
if ((bool)fila.Cells[columnIndex].EditedFormattedValue == false)
{
negativos++;
}
}
if (totalFilas == contador)
{
if (totalFilas == negativos)
{
headerCheckBox.CheckState = CheckState.Unchecked;
}
else if (totalFilas == positivos)
{
headerCheckBox.CheckState = CheckState.Checked;
}
else
{
headerCheckBox.CheckState = CheckState.Indeterminate;
}
}
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.