Search code examples
c#datagridviewdatagridviewcheckboxcell

Is there a way to stop DataGridViewCheckBoxColumn auto checking on click?


I am using the DataGridView and have a few DataGridViewCheckBoxColumns setup, two of which have the ThreeState property set to True.

For some rows in my grid, I only want the checkbox to be either Checked or Indeterminate. Unchecked should never be available to the user. But if the user clicks the checkbox repeatedly, it goes from checked to Indeterminate to unchecked. I just want it to go checked, indeterminate, checked, indeterminate etc.

Is there a way to turn stop a checkbox from being checked/unchecked when clicked (similar to the AutoCheck property on the standard windows forms Checkbox control), or is there an event I can use to cancel the checked change of the DataGridViewCheckBoxCell?

I have tried to programatically force the checked cell from unchecked to checked or indeterminate, but the UI never reflects this.


Solution

  • Assuming any DataGridViewCheckBoxColumn you've added has followed the pattern:

    DataGridViewCheckBoxColumn cbc = new DataGridViewCheckBoxColumn();
    cbc.ThreeState = true;
    this.dataGridView1.Columns.Add(cbc);
    

    Then all you need to do is add the following event handler to your DataGridView for clicking and double-clicking the CheckBox:

    this.dataGridView1.CellContentClick += ThreeState_CheckBoxClick;
    this.dataGridView1.CellContentDoubleClick += ThreeState_CheckBoxClick;
    
    private void ThreeState_CheckBoxClick(object sender, DataGridViewCellEventArgs e)
    {
        DataGridViewCheckBoxColumn col = this.dataGridView1.Columns[e.ColumnIndex] as DataGridViewCheckBoxColumn;
    
        if (col != null && col.ThreeState)
        {
            CheckState state = (CheckState)this.dataGridView1[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
    
            if (state == CheckState.Unchecked)
            {
                this.dataGridView1[e.ColumnIndex, e.RowIndex].Value = CheckState.Checked;
                this.dataGridView1.RefreshEdit();
                this.dataGridView1.NotifyCurrentCellDirty(true);
            } 
        }
    }
    

    Essentially, the toggle order by default is: Checked => Indeterminate => Unchecked => Checked. So when the click event triggers an Uncheck value, you set it to Checked and force the grid to refresh with the new value.