4

DataGridView.CellContentClick is not firing if I mouse click a DataGridViewCheckBoxCell very fast. How can I solve this? I need to know when CheckBox's check state changes

Cornel
  • 4,652
  • 15
  • 48
  • 57
  • I handled CellContentDoubelClick to solve this problem – Cornel Dec 19 '08 at 14:36
  • 3
    Yea, but DoubleClick doesn't feel intuitive to the user, because people normally aren't used to having to double click a checkbox. – BFree Dec 19 '08 at 14:43

4 Answers4

6

Try handling the CellMouseUp event.
You can check which colum the MouseUp event occurred in to see if it is your checkbox column.
You can also find out if it is in edit mode and end the edit mode programmatically, which in turn will fire the CellValueChanged event.

In the example below, I have a DataGridView with two colums.
The first is a DataGridViewTextBoxColumn and the second is a DataGridViewCheckBoxColumn.
When the checkbox changes, the first column wil reflect its check state, without having to move from the row or cell.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        dataGridView1.Rows.Add("False", false);
        dataGridView1.Rows.Add("True", true);
    }

    private void dataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.ColumnIndex == 1 && e.RowIndex >-1 && dataGridView1.Rows[e.RowIndex].Cells[1].IsInEditMode)
        {
            dataGridView1.EndEdit();
        }
    }

    private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (e.RowIndex != -1)
        {
            dataGridView1.Rows[e.RowIndex].Cells[0].Value =
               dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString(); 
        }
    }
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
Colby Africa
  • 1,356
  • 9
  • 13
5

Regardless of how fast the user clicks in the checkbox cell, the value won't change from true to false or vise versa until they click out of that row, and the DataGridView goes out of edit mode.

What I've done in the past, is set that column to ReadOnly = true. Then, in the CellContentClick event handler, if that column was clicked, I manually flipped the bool like this:

bool b = (bool)this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = !b;

Then, you can do your logic at this point that you would normally do for the CheckChanged.

BFree
  • 102,548
  • 21
  • 159
  • 201
2

I'm a little late to the party, but msdn has a very good answer to this problem here.

'Ends Edit Mode So CellValueChanged Event Can Fire
Private Sub EndEditMode(sender As System.Object, e As EventArgs) _
    Handles DataGridView1.CurrentCellDirtyStateChanged
    'if current cell of grid is dirty, commits edit
    If DataGridView1.IsCurrentCellDirty Then
        DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
    End If
End Sub

I also wrote up a very detailed elaboration of the msdn fix and those found here on the post Firing The DataGridView CellValueChanged Event Immediately

KyleMit
  • 30,350
  • 66
  • 462
  • 664
1

It's better to handle the event CellContentClick (if you click accidentally outside the box itself, it won't work properly):

grid.CellContentClick += delegate(object obj, DataGridViewCellEventArgs args)
{
    var cell = (settings_grid[args.ColumnIndex,args.RowIndex] as DataGridViewCheckBoxCell);

    if (cell != null)
    {
        bool new_value = !(bool)cell.Value;                                        
        RecordTheNewState(new_value); // you record the new checkbox state
    }
};
davmos
  • 9,324
  • 4
  • 40
  • 43
Mikhail Semenov
  • 953
  • 8
  • 8