DataGridViewCheckBoxCell Needs Help

March 31, 2009

So I have spent that past 4 hrs trying to implement an event in a DataGridView to tell me when the value of a DataGridViewCheckBoxCell in any row changes. Easy enough right? After all Microsoft gives you very complete instructions on MSDN.

http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellclick.aspx

In my case, it wasn’t so easy.

The problem is this line from the documentation, “this event occurs before the check box changes value”. So I wanted my event to call back and inform the owner of the DataGridView that a checkbox was clicked (and therefore the value changed). The owner would then count how many check boxes were checked by extracting the value like this:
var isChecked = (((row.Cells[CheckBoxColIndex]).Value != null) && (bool) (row.Cells[CheckBoxColIndex]).Value);

return isChecked;
At this point I would just like to ask why can’t I just write this?
return ((DataGridViewCheckBoxCell)(row.Cells[CheckBoxColIndex])).Checked;
How can a checkbox be null? It is either on or off. I understand that it can have an indeterminant or middle value if the state of the check box represents the states of more than one other objects but isn’t that the point of the TriState property?

Because you can’t get the actual value of the check box until the CellClick event returns there is no way to get an accurate count of how many check boxes are checked in the call back that is called from CellClick.

The solution: I ended up using a List to store references to the rows that were checked. Each time the CellClicked event got fired by clicking the check box cell I would check to see if the row was in the list by calling List.Contains() in order to determine the state of the row. If was in the list I removed it and if it wasn’t I added it. This is an inefficient implementation for tracking the state of check box but it pays off a little when I want to get the number of checked rows because I simply need to call List.Count.

Here is the final event handler:
internal void CheckBoxCellClicked(object sender, DataGridViewCellEventArgs e)
{
var row = Rows[e.RowIndex];

if(!(row.Cells[e.ColumnIndex] is DataGridViewCheckBoxCell))
return;

bool isChecked = CheckedRows.Contains(row);

if(isChecked)
{
CheckedRows.Remove(row);
}
else
{
CheckedRows.Add(row);
}

row.Cells[_CheckboxColIndex].Value = !isChecked;

var eventArgs = new CheckBoxCellClickedEventArgs
{
DGVName = Name,
IsChecked = !isChecked,
RowNumber = e.RowIndex,
ValueChanged = true
};

OnCheckBoxCellClicked(sender, eventArgs);
}

Another thing:

Do this little experiment. Make a DataGridViewCheckBoxCell and click in the cell but not in the checkbox. The CellClicked event gets fired but no check appears in the checkbox. In order to get the check box to be checked when the cell is clicked you have to do this in the CellClicked event:
row.Cells[_CheckboxColIndex].Value = !isChecked;
You also need to have this method registered with the CellValueChanged event.

void CheckBoxCellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if(CurrentCell is DataGridViewCheckBoxCell)
{
EndEdit(DataGridViewDataErrorContexts.Commit);
}
}

Setting the value of the cell value sets the check box value to what you would expect it to be after clicking the cell. The actual check doesn’t show up in the check box until the EndEdit() is called from the CellValueChanged event. Does that seem right to you? Definitely not how I would have envisioned a DataGridViewCheckBoxCell working. No wonder it took me so long to get it implimented. I had to finish Microsoft’s implementation first.

Advertisements

One Response to “DataGridViewCheckBoxCell Needs Help”

  1. Grateful Dev said

    I spent hours trying to find out why the *click on a cell but not the checkbox* would update the value but not the display. EndEdit worked. Thanks for your post!!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: