I'm buidling an application like this:
Within each row in the table:
User can check or uncheck value in the
Option 1
andOption 2
column.
After that, the value of checkbox inAll option
column with be updated to:
- "Checked": if bothOption 1
andOption 2
is checked
- "Unchecked": if bothOption 1
andOption 2
is unchecked
- "Indeterminate": other casesUser can check or uncheck value in the
All option
column.
After that, both value ofOption 1
andOption 2
will be updated based on current value ofAll option
.
In this case, user cannot change the value ofAll option
column to Indeterminate (only toggle between Checked and Unchecked).
I'm implementing the above application using DataGridView in Winforms. Following is my code:
public partial class Form1 : Form
{
DataTable dataTable;
public Form1()
{
InitializeComponent();
dataTable = new DataTable();
dataTable.Columns.Add("Item");
dataTable.Columns.Add("All option", typeof(CheckState));
dataTable.Columns.Add("Option 1", typeof(bool));
dataTable.Columns.Add("Option 2", typeof(bool));
dataTable.Rows.Add("Item 1", CheckState.Unchecked, false, false);
dataTable.Rows.Add("Item 2", CheckState.Unchecked, false, false);
dataGrid.DataSource = dataTable;
}
private void dataGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dataGrid.CurrentCell is DataGridViewCheckBoxCell)
{
dataGrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
bool isUnderUpdateAll = false;
private void dataGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if ((dataGrid.CurrentCell is DataGridViewCheckBoxCell) == false) return;
// This is column "All option"
if (e.ColumnIndex == 1)
{
// Avoid stackoverflow exception
if (isUnderUpdateAll) return;
CheckState allOption = (CheckState)dataGrid["All option", e.RowIndex].Value;
// Don't allow user select 'indeterminate' value
if (allOption == CheckState.Indeterminate)
{
allOption = CheckState.Unchecked;
// These code didn't work
dataTable.Rows[e.RowIndex]["All option"] = CheckState.Unchecked;
dataGrid["All option", e.RowIndex].Value = CheckState.Unchecked;
dataGrid.UpdateCellValue(e.ColumnIndex, e.RowIndex);
dataGrid.NotifyCurrentCellDirty(true);
dataGrid.Refresh();
dataGrid.Update();
}
dataGrid["Option 1", e.RowIndex].Value = allOption;
dataGrid["Option 2", e.RowIndex].Value = allOption;
}
// This is column "Option 1" or "Option 2"
else
{
bool option1 = (bool)dataGrid["Option 1", e.RowIndex].Value;
bool option2 = (bool)dataGrid["Option 2", e.RowIndex].Value;
isUnderUpdateAll = true;
dataGrid["All option", e.RowIndex].Value = (option1 && option2) ? CheckState.Checked
: (!option1 && !option2 ? CheckState.Unchecked : CheckState.Indeterminate );
isUnderUpdateAll = false;
}
}
}
The code seem works, but there is 1 incomplete point: user still able to switch to Indeterminate state in the All option
column. In my code, I already add many thing like:
// Don't allow user select 'indeterminate' value
if (allOption == CheckState.Indeterminate)
{
allOption = CheckState.Unchecked;
// These code didn't work
dataTable.Rows[e.RowIndex]["All option"] = CheckState.Unchecked;
dataGrid["All option", e.RowIndex].Value = CheckState.Unchecked;
dataGrid.UpdateCellValue(e.ColumnIndex, e.RowIndex);
dataGrid.NotifyCurrentCellDirty(true);
dataGrid.Refresh();
dataGrid.Update();
}
But these code didn't work. When click on All option
checkbox, the state still switch between Checked -> indeterminate -> Unchecked -> Checked -> ...
So, could someone help suggest how to remove the indeterminate state from above?
I want it to be: Checked -> Unchecked -> Checked -> Unchecked ...