Stack Overflow en español Asked by Miguel Angel on November 29, 2021
Necesitaba crear una columna de CheckBox
en un DataGridView
y en la cabecera de esta un CheckBox
de seleccionar todos.
Lo hice en forma de métodos en una clase estática a los que le paso el DataGridView
y me lo montan.
Los metodos en cuestion son:
//Añade la columna de checkboxs en la primera posicion.
public static void AddCheckColumn(DataGridView dgv)
{
DataGridViewCheckBoxColumn chkCol = new DataGridViewCheckBoxColumn();
chkCol.Name = "colCheck";
chkCol.HeaderText = "";
chkCol.Width = 30;
chkCol.ReadOnly = false;
dgv.Columns.Insert(0,chkCol);
}
//Crea un objeto CheckBox, lo asocia a la colección de controles del DataGridView y lo mueve al lugar del header.
public static void CheckHeader(DataGridView dgv, EventHandler HeaderCheck_Clicked)
{
CheckBox chkHead = new CheckBox();
Point headerCellLocation = dgv.GetCellDisplayRectangle(0, -1, true).Location;
int cellWidth = dgv.GetCellDisplayRectangle(0, -1,true).Width;
int cellHeight = dgv.GetCellDisplayRectangle(0, -1, true).Height;
chkHead.Location = new Point(headerCellLocation.X + 8, headerCellLocation.Y + 2);
chkHead.BackColor = Color.White;
chkHead.FlatStyle = FlatStyle.Standard;
chkHead.BackColor = Color.Transparent;
chkHead.Size = new Size(18, 18);
chkHead.Click += HeaderCheck_Clicked;
dgv.Controls.Add(chkHead);
}
Para controlar la propiedad checked del CheckBox creado dinamicamente en el header, accedo a su propiedad desde el sender del evento:
private void frmOfertes_Load(object sender, EventArgs e)
{
string queryCmbFam = "SELECT codigo,nombre from " + DB.SQLDatabase("GESTION", "familias");
cmbSubfam.Enabled = false;
funcions.EmplenaCombo(queryCmbFam, cmbFam);
funcions.AddCheckColumn(ewgrid1);
funcions.FiltreGridArticles(cmbFam, cmbSubfam, ewgrid1);
funcions.CheckHeader(ewgrid1, HeaderCheck_Clicked);
Dictionary<string, int> ampleCamps = new Dictionary<string, int>()
{
{"codigo",80 },
{"nombre",200 }
};
funcions.ColumnSize(ampleCamps, ewgrid1);
}
private void HeaderCheck_Clicked(object sender, EventArgs e)
{
CheckBox chkHead = (CheckBox)sender;
ewgrid1.EndEdit();
foreach(DataGridViewRow row in ewgrid1.Rows)
{
DataGridViewCheckBoxCell chkbox = (row.Cells["colCheck"] as DataGridViewCheckBoxCell);
chkbox.Value = chkHead.Checked;
}
}
Lo que hago en este evento, es igualar los CheckBox
de la columna del DataGridView
al estado del CheckBox
del header
.
Ahora necesito hacerlo a la inversa, es decir, si selecciono todos los registro mediante el checkBox
del header
, necesito que al deseleccionar uno de ellos, se deseleccione también el checkBox
del header
.
Pero no sé cómo acceder a este control.
private void ewgrid1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if(e.RowIndex >=0 && e.ColumnIndex ==0)
{
bool isChecked = true;
foreach(DataGridViewRow row in ewgrid1.Rows)
{
if (Convert.ToBoolean(row.Cells["colCheck"].EditedFormattedValue) == false)
{
isChecked = false;
break;
}
}
}
chkHead.Checked = isChecked;---> ¿Cómo accedo a chkHead ?
}
EDIT:
Por si a alguien le ayuda, he conseguido acceder al checkbox
de la cabecera mediante la colección de controles del dataGridView
, aunque debo decir que a pesar de que el control del checkbox
del header
es correcto, el comportamiento del la función que uso para activar o desactivarlo según el estado de los checkboxs
de la columna no es el esperado, pero ese ya es otro tema.
private void ewgrid1_CellClick(object sender, DataGridViewCellEventArgs e)
{
CheckBox chkHead = (CheckBox)ewgrid1.Controls["chkHead"];
if (e.RowIndex >= 0 && e.ColumnIndex == 0)
{
//Loop to verify whether all row CheckBoxes are checked or not.
bool isChecked = true;
foreach (DataGridViewRow row in ewgrid1.Rows)
{
if (Convert.ToBoolean(row.Cells["colCheck"].EditedFormattedValue) == false)
{
isChecked = false;
break;
}
}
chkHead.Checked = isChecked;
}
}
Una solución es almacenar una referencia al CheckBox
en una variable que puedas recuperar adecuadamente, para esto lo mas apropiado es la propiedad Tag
de la propia columna DataGridViewCheckBoxColumn
, para ello en el evento CheckHeader
en ves de pasar como argumento el DataGridView
yo pasaría como argumento la columna asociada, así como aparece a continuación.
//Crea un objeto CheckBox, lo asocia a la colección de controles del DataGridView y lo mueve al lugar del header.
public static void CheckHeader(DataGridViewColumn col_dgv, EventHandler HeaderCheck_Clicked)
{
CheckBox chkHead = new CheckBox();
chkHead.Bounds = col_dgv.HeaderCell.ContentBounds;
chkHead.BackColor = Color.White;
chkHead.FlatStyle = FlatStyle.Standard;
chkHead.BackColor = Color.Transparent;
chkHead.Size = new Size(18, 18);
chkHead.Click += HeaderCheck_Clicked;
col_dgv.DataGridView.Controls.Add(chkHead);
//Agregas una referencia al control chkHead en la propiedad Tag de la columna asociada
col_dgv.Tag = chkHead;
}
En el evento ewgrid1_CellClick
, lo que tendrías que hacer es recuperar el control CheckBox
asociado desde la propiedad Tag
de la columna, siempre haciendo la debida conversión, pues la propiedad Tag
es de tipo object
.
private void ewgrid1_CellClick(object sender, DataGridViewCellEventArgs e)
{
bool isChecked = true;
if (e.RowIndex >= 0 && e.ColumnIndex == 0)
{
foreach (DataGridViewRow row in ewgrid1.Rows)
{
if (Convert.ToBoolean(row.Cells["colCheck"].EditedFormattedValue) == false)
{
isChecked = false;
break;
}
}
}
//Recuperamos el control CheckBox, desde la referencia almacenada en la propiedad Tag de la columna.
CheckBox chkHead = (CheckBox)ewgrid1.Columns[e.ColumnIndex].Tag;
chkHead.Checked = isChecked;
}
Espero que la respuesta te resulte satisfactoria, pruebala y mucha suerte.
Answered by Eduardo Reyes on November 29, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP