TransWikia.com

¿Cómo puedo acceder a un control creado dinámicamente en un datagridview?

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 CheckBoxde 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;
    }
}

One Answer

Una solución es almacenar una referencia al CheckBoxen 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 DataGridViewyo 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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP