Enable / Disable Button according to Checkbox value in a DataGridView

3

A form in an application Windows Forms with C# displays a DataGridView with Checkbox . When one of the Checkbox is checked I want to enable a certain button. If no Checkbox is checked, I want to disable it.

Try this:

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    bool marcado = false;
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell)dataGridView1.CurrentRow.Cells["chk"];
        if (chk.Value == chk.TrueValue)
        {
            marcado = true;
            break;
        }
    }

    if (marcado)
        button1.Enabled = true;
    else
        button1.Enabled = false;
}

And it did not work.

I've tried using CellValueChanged and it's not working either.

How to solve this problem.

    
asked by anonymous 04.01.2015 / 22:07

2 answers

2

You can do this by using the CellValueChanged event like this:

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // se a célula alterada for a célula de interesse (1.)
    if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("chk"))
    {
        bool marcado = false;
        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell)row.Cells["chk"]; // (2.)
            // se a célula estiver marcada
            if ((bool)(chk.Value ?? false) == true) // (3.) e (4.)
            {
                marcado = true;
                break;
            }
        }

        if (marcado)
            button1.Enabled = true;
        else
            button1.Enabled = false;
    }
}

Here are a few things to keep in mind:

  • I used a if before checking the values of DataGridViewCheckBoxCell to prevent the check from occurring in all columns.
  • As I said in the comments, it was necessary to change dataGridView1.CurrentRow to row , otherwise your for would not go through all the lines, but only the current line (referring to the changed cell).
  • The ?? is used to check if the operator on the left is null, if it returns the value on the right, otherwise, it returns the value on the left, to know more see What is the meaning of the "??" operator.
  • The TrueValue quer property should be used differently, as I'm not exactly sure how you're using DataGridView , I'd rather not use it, but you might see an example here .
  • I'm not sure exactly how much data you'll be working on, but doing this for every time a cell is checked / unchecked, you probably will not perform well, I thought of another solution, you might need to better, but it already serves as a starting point.

    Create a global variable private int numeroCelulasMarcadas = 0; , this variable will serve as a counter of marked cells, in event RowsAdded of DataGridView , do so:

    private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        DataGridViewCheckBoxCell chk =
            (DataGridViewCheckBoxCell)dataGridView1.Rows[e.RowIndex].Cells["chk"];
    
        if ((bool)(chk.Value ?? false) == true)
        {
            numeroCelulasMarcadas++;
        }
    }
    

    Now in event CellValueChanged put this:

    private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        // se a célula alterada for a célula de interesse
        if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("chk"))
        {
            DataGridViewCheckBoxCell chk = 
                (DataGridViewCheckBoxCell)dataGridView1.Rows[e.RowIndex].Cells["chk"];
    
            if ((bool)chk.Value == true)
            {
                numeroCelulasMarcadas++;
            }
            else
            {
                numeroCelulasMarcadas--;
            }
    
            if (numeroCelulasMarcadas == 0)
            {
                button1.Enabled = false;
            }
            else
            {
                button1.Enabled = true;
            }
        }
    }
    

    Remember that this last solution is a starting point, it may be necessary to adjust something to work correctly in the context of your application.

        
    05.01.2015 / 03:28
    0

    The solution that Matthew proposed works, but you have to press Enter , in my case the user just wanted to click on CheckBox , so I used the following solution:

    private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("chk"))
        {
            ManipulaBotao();
        }
    }
    
    private void dataGridView1_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
        if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("chk"))
        {
            ManipulaBotao();
        }
    }
    
    private void ManipulaBotao()
    {
        button1.Enabled = false;
        foreach (DataGridViewRow dr in dataGridView1.Rows)
        {
            if (bool.Parse(dr.Cells["chk"].EditedFormattedValue.ToString()))
            {
                button1.Enabled = true;
                break;
            }
        }
    }
    

    So just by clicking on CheckBox the control is enabled / disabled.

    It's worth mentioning that in my case the number of lines is small so it does not affect the performance, as was well remembered in the post of Matthew.

    Note the use of the CellContentDoubleClick method, otherwise it will not work as expected.

        
    05.01.2015 / 18:17