2
votes

I have a DataGridView which has a bunch of columns plus a checkBoxColumn called IsChecked.

I want to raise an event whenever a row's checked state changes. Checking or Unchecking a row may be done either when user clicks the checkBox or when they press space key on a row.

this is how I added checkBoxColumn to my grid:

dgvMain.Columns.Add(new DataGridViewCheckBoxColumn { 
            Name = "IsChecked" , 
            Width = 20, 
            Visible = false,
            HeaderText = "",
            SortMode = DataGridViewColumnSortMode.NotSortable,
            DisplayIndex = Columns.Count, //to be displayed as last column
            ValueType = typeof(bool),
            FalseValue = false,
            TrueValue = true
        });

and this is how I check the cell when space key is pressed:

private void dgvMain_KeyDown(object sender, KeyEventArgs e)
{
     foreach (DataGridViewRow row in dgvMain.SelectedRows)
     {
         bool? checkState = (bool?)row.Cells["IsChecked"].Value;
         if (checkState == null || checkState == false)
             checkState = true;
         else
             checkState = false;
         row.Cells["IsChecked"].Value = checkState;
     }

}

Attempt # 1:
I tried using CellEndEdit event which only helped when you check the cell using mouse, but when I press space and the cell checks/unchecks CellEndEdit does not fire.

Attempt # 2:
I tried using CellValueChanged event, which works fine when I press space, and also when I check the box using mouse and leave the row but when I check and uncheck the box multiple times, nothing happens. It seems like CellValueChanged raises when the cell is finished editing by mouse.

Attempt # 3:
I Also tried using CurrentCellDirtyStateChanged which responds to first checked change caused by mouse but does not respond to rapid checked changes bu mouse, only the first one and also when you leave the row. I want to catch all checked changes, even if user changes the checked state rapidly by clicking on the checkBox, that counts too.

I'm not sure if there is any event already for this purpose or not. If not, how can I add an eventHandler for this column programmatically?

3
If your grid is bound to a DataTable (or DataSet), then put the event on its ColumnChanged or ColumnChanging event. - DonBoitnott
If your grid is not DataBound, when you create the cell, add a handler to it. - user959631
@user959631 how can I add a handler to the cell when creating it? - Mahdi Tahsildari
Please see Mohamed Salemyan's answer. - user959631

3 Answers

4
votes

In the CurrentCellDirtyStateChanged event handler, trigger EndEdit so that the value changed event is triggered.

void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dataGridView1.IsCurrentCellDirty && dataGridView1.CurrentCell.ColumnIndex == CheckColumnIndex)
    {
        dataGridView1.EndEdit();
    }
}

In the CellValueChanged event handler get the value from the CheckBoxColumn.

void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == CheckColumnIndex)
    {
        DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        bool achecked = Convert.ToBoolean(checkCell.Value);
    }
}
2
votes

you can use CellValueChanged event for getting checkbox value:

private void dgvMain_CellValueChanged(object sender, 
                                          DataGridViewCellEventArgs e)
{
    foreach (DataGridViewRow row in dgvMain.Rows) 
    {
       if (row.Cells["RowWithCheckBox"].Value != null &&(bool)row.Cells["RowWithCheckBox"].Value)
       {
          //do something
       }
    }
}
0
votes

Take a look at CellValidating and CellValueChanged events if it suits you.