DataGridViewCheckBoxCell click handling issue

Ron picture Ron · Dec 26, 2013 · Viewed 7.5k times · Source

I created a DataGridView control where the first column is a checkbox. When I click inside the check box, the code correctly executes. HOWEVER, when the click occurs in the cell but not in the checkbox, the code correctly handles the state of the checkbox but does not update the checkbox itself, so it remains in the state it was before the click.

How do I correct this?

   private void myDataGrid_CellClick(object sender, DataGridViewCellEventArgs e)
   {
       if (e.RowIndex == -1) return; //check if row index is not selected
       DataGridViewCheckBoxCell ch1 = new DataGridViewCheckBoxCell();
       ch1 = (DataGridViewCheckBoxCell)myDataGrid.Rows[e.RowIndex].Cells[0];

       if (ch1.Value == null)
           ch1.Value = false;
       switch (ch1.Value.ToString())
       {
           case "False":

               ch1.Value = true;

               break;
           case "True":

               ch1.Value = false;
               break;
       }
      //BUT doesn't seem to matter what I do with ch1.Value. Inside the checkbox all is OK but
      //outside, no.

   }

If I click in another cell on the row, the check box is handled correctly. ONLY when I click in the check box cell but NOT in the checkbox itself.

What I mean is (and apologies), the code correctly executes but the UI does not update correctly to reflect the change. So, if the checkbox is unchecked before it appears to unchecked afterenter image description herewards as well, even though it is actually checked.

Thanks RON

Answer

Anthony picture Anthony · Dec 26, 2013

I'm not 100% sure what causing this behavior, but I believe it has to do with the check box cell entering edit mode the moment you click inside of it. Confirmed, this issue is definitely caused by entering edit mode the moment you click inside the cell. See edit at the end of the post.

Because you are setting the value of the cell yourself, you can get around this issue by just making the check-box column readonly as well.

The following code worked fine for me in using LINQPad (I look liberties to simplify the handler logic):

void Main()
{
    var dataGridView = new DataGridView();
    dataGridView.Columns.Add(new DataGridViewCheckBoxColumn());
    dataGridView.Columns.Add(new DataGridViewTextBoxColumn());
    dataGridView.Columns.Add(new DataGridViewTextBoxColumn());

    dataGridView.Columns[0].ReadOnly = true;
    dataGridView.Columns[1].ReadOnly = true;
    dataGridView.Columns[2].ReadOnly = true;

    dataGridView.CellClick += this.DataGridView_CellClick;

    dataGridView.Dump();
}

void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex < 0) return;

    var dataGridView = (DataGridView) sender;
    var cell = dataGridView[0, e.RowIndex];

    if (cell.Value == null) cell.Value = false;
    cell.Value = !(bool)cell.Value;
}

The only oddity I noticed is the second click in a double-click doesn't get routed to the CellClick event handler. If you really want this behavior you can tie the same handler to the CellDoubleClick event.

Edit:

If you don't like making the first column read-only, then you can simply add a call to EndEdit after you change the value:

void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex < 0) return;

    var dataGridView = (DataGridView) sender;
    var cell = dataGridView[0, e.RowIndex];

    if (cell.Value == null) cell.Value = false;
    cell.Value = !(bool)cell.Value;
    dataGridView.EndEdit();
}

This was hinted at by a comment on another question by user NeverHopeless.