It appears you have the CellContentClick set up properly, however, if there are other columns in the grid, then, it may be beneficial if you check to make sure that the cell whose content was clicked is actually one of the check box cells. Otherwise the code may be setting the cells value unnecessarily.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) {
string colName = dataGridView1.Columns[e.ColumnIndex].Name;
if (colName == "Yes" || colName == "No" || colName == "N/A") {
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
In the CellValueChanged event, again the code should check for only the check box values. In addition, I would assume that at least ONE (1) of the cells MUST be checked. Example, if the “N/A” cell is originally checked, then the user “unchecks” that cell, then the row would have NO check boxes checked. This is the final check in the code such that if the user “unchecks” the “N/A” cell AND this leaves ALL check boxes “unchecked”, then, the code will “check” the “N/A” cell. Also, it is important to “turn OFF” the CellValueChanged event before we change any of the check box values IN the CellValueChanged event to avoid reentrant. Something like…
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
if (e.RowIndex >= 0 && e.ColumnIndex >= 0) {
string colName = dataGridView1.Columns[e.ColumnIndex].Name;
bool checkValue;
dataGridView1.CellValueChanged -= new DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
switch (colName) {
case "Yes":
checkValue = (bool)dataGridView1.Rows[e.RowIndex].Cells["Yes"].Value;
if (checkValue == true) {
dataGridView1.Rows[e.RowIndex].Cells["No"].Value = false;
dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value = false;
}
else {
dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value = true;
}
break;
case "No":
checkValue = (bool)dataGridView1.Rows[e.RowIndex].Cells["No"].Value;
if (checkValue == true) {
dataGridView1.Rows[e.RowIndex].Cells["Yes"].Value = false;
dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value = false;
}
else {
dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value = true;
}
break;
case "N/A":
checkValue = (bool)dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value;
if (checkValue == true) {
dataGridView1.Rows[e.RowIndex].Cells["Yes"].Value = false;
dataGridView1.Rows[e.RowIndex].Cells["No"].Value = false;
}
else {
if ((bool)dataGridView1.Rows[e.RowIndex].Cells["Yes"].Value == false &&
(bool)dataGridView1.Rows[e.RowIndex].Cells["No"].Value == false) {
dataGridView1.Rows[e.RowIndex].Cells["N/A"].Value = true;
}
}
break;
default:
break;
}
dataGridView1.CellValueChanged += new DataGridViewCellEventHandler(this.dataGridView1_CellValueChanged);
}
Below is a simple example with the three columns “Yes”, “No” and “N/A” check box columns.
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
dataGridView1.DataSource = GetTable();
}
private DataTable GetTable() {
DataTable dt = new DataTable();
dt.Columns.Add("Yes", typeof(bool));
dt.Columns.Add("No", typeof(bool));
dt.Columns.Add("N/A", typeof(bool));
for (int i = 0; i < 10; i++) {
dt.Rows.Add(false, false, true);
}
return dt;
}
Hope this helps.
INotifyPropertyChannged? And/or, could this logic be implemented in the class object itself, so the Single Option is actually triggered internally and you don't bother the UI layer at all? If you can avoid working on the View side, it's a good thing. etc.