I have a Windows Forms app that displays a list of objects in a DataGridView.
This control renders bool values as checkboxes.
There\'s a set of three checkboxe
private void dataGridViewProduit_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if ((sender as DataGridView).CurrentCell is DataGridViewCheckBoxCell)
{
if (Convert.ToBoolean(((sender as DataGridView).CurrentCell as DataGridViewCheckBoxCell).Value))
{
foreach (DataGridViewRow row in (sender as DataGridView).Rows)
{
if (row.Index != (sender as DataGridView).CurrentCell.RowIndex && Convert.ToBoolean(row.Cells[e.ColumnIndex].Value) == true)
{
row.Cells[e.ColumnIndex].Value = false;
}
}
}
}
}
private void dataGridViewClient_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (this.dataGridViewClient.IsCurrentCellDirty)
{
dataGridViewClient.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
The one you want is CellContentClick, on the DGV itself. Attach a handler that checks to see if that column of the DGV is a CheckBoxCell, and if so, uncheck all other checkboxes on the row.
Just a note though, for a CheckBoxCell, this event fires before the checkbox value actually changes. This means that regardless of what you do to the current cell, it will be overridden by events that fire later. The behavior that will shake out of this is that you can have none of the cells on a row checked, by checking one box on the row and then checking it again (whether you try to set the checkbox value in the handler or not, the checkbox will end up cleared after the second click). To overcome that and force one of the checkboxes to be checked, you can handle CellValueChanged instead, and if the cell that changed is the current cell and is unchecked, check it.
Thanks to KeithS for the helpful answer.
When I looked in the doc for CellValueChanged, I found this helpful bit:
The DataGridView.CellValueChanged event occurs when the user-specified value is committed, which typically occurs when focus leaves the cell.
In the case of check box cells, however, you will typically want to handle the change immediately. To commit the change when the cell is clicked, you must handle the DataGridView.CurrentCellDirtyStateChanged event. In the handler, if the current cell is a check box cell, call the DataGridView.CommitEdit method and pass in the Commit value.
This is the code I used to get the radio behavior:
void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
// Manually raise the CellValueChanged event
// by calling the CommitEdit method.
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
public void dataGridView1_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
// If a check box cell is clicked, this event handler sets the value
// of a few other checkboxes in the same row as the clicked cell.
if (e.RowIndex < 0) return; // row is sometimes negative?
int ix = e.ColumnIndex;
if (ix>=1 && ix<=3)
{
var row = dataGridView1.Rows[e.RowIndex];
DataGridViewCheckBoxCell checkCell =
(DataGridViewCheckBoxCell) row.Cells[ix];
bool isChecked = (Boolean)checkCell.Value;
if (isChecked)
{
// Only turn off other checkboxes if this one is ON.
// It's ok for all of them to be OFF simultaneously.
for (int i=1; i <= 3; i++)
{
if (i != ix)
{
((DataGridViewCheckBoxCell) row.Cells[i]).Value = false;
}
}
}
dataGridView1.Invalidate();
}
}
It would get too easy here:
Conisder your checkbox column is the 2nd column in your datagridview.
private void YourDatagridview_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (IsHandleCreated)
{
if (YourDatagridview.CurrentCell == YourDatagridview.Rows[e.RowIndex].Cells[1])
{
if (Convert.ToBoolean(YourDatagridview.CurrentCell.Value) == true)
{
for (int i = 0; i < YourDatagridview.RowCount; i++)
{
if (YourDatagridview.Rows[i].Cells[1] != YourDatagridview.CurrentCell)
{
YourDatagridview.Rows[i].Cells[1].Value = false;
}
}
}
}
}
}
And call this too:
private void YourDatagridview_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (this.YourDatagridview.IsCurrentCellDirty)
{
YourDatagridview.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
and Voila!!