Search code examples
c#checkboxdatagridcomboboxcolumn

How to handle event of combobox in datagridview?


I have a checkbox[All] and a datagridview as below:

enter image description here

I would like:

  • The inside datagridview, if all checkbox is checked, the checkbox[All] is checked and otherwise if all checkbox is unchecked, the checkbox[All] is unchecked
  • The inside datagridview, there is a checkbox that is unchecked, the checkbox[All] is unchecked

I tried it but I am not able to do it:

private void dataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    bool isAllCheck = false;

    if (e.ColumnIndex == 0)
    {
        foreach (DataGridViewRow row in dataGridView.Rows)
        {
            DataGridViewCheckBoxCell chk = row.Cells[0] as DataGridViewCheckBoxCell;

            isAllCheck = Convert.ToBoolean(chk.Value);
            if (!isAllCheck)
            {
                break;
            }
        }

        if (chkAllItem.Checked && !isAllCheck)
        {
            chkAllItem.Checked = false;
        }

        if (!chkAllItem.Checked && isAllCheck)
        {
            chkAllItem.Checked = true;
        }
    }
}

private void dataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (this.dataGridView.IsCurrentCellDirty)
    {
        this.dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
}

Any tips on these will be great help. Thanks in advance.


Solution

  • Setting the TrueValue, FalseValue and IndeterminateValue is a good start.

    I found that I also need to do a bit more for this to work; in addition to your CurrentCellDirtyStateChanged event I also coded these:

    This sets all CheckBoxCells:

    private void cbx_all_CheckedChanged(object sender, EventArgs e)
    {
        if (cbx_all.Tag == null) for (int i = 0; i < dataGridView.RowCount; i++)
        {
            dataGridView.Tag = "busy";
            dataGridView[yourCheckBoxcolumnIndex, i].Value = cbx_all.Checked;
            dataGridView.Tag = null;
        }
    }
    

    I coded the CellValueChanged instead of the CellContentClick event:

    private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == yourCheckBoxcolumnIndex &&  dataGridView.Tag == null)
        {
           cbx_all.Tag = "busy";
           cbx_all.Checked = testChecks(e.ColumnIndex);
           cbx_all.Tag = null;
        }
    }
    

    I used the Tag property of the DGV and the CheckBox as a flag, that I am busy changing values by code. Some other means to avoid an endless-loop are just as fine.

    This is the test function:

    bool testChecks(int index)
    {
        for (int r = 0; r < dataGridView.RowCount; r++)
            if  ( !(bool)dataGridView[index, r].Value ) return false;
        return true;
    }