Alex
Alex

Reputation: 4948

DataGridView CheckBox Display ThreeState But Have The User Work with Two State

Current Situation

I display a list of conveyors that contain custom options. When multiple conveyors are selected, I show the uncommon options as an indeterminate state like so:

Conveyor Options

This demonstrates that the conveyors EB-1 and EB-3 do not have the same custom options (Test and Test2).

Goal

I'd like the user to be able to click on the indeterminate state and set it to false or true. When the user interaction occurs, I don't want the indeterminate state to happen.

Option Load with ThreeState Mapping

Public Enum TriState
    Common
    TurnedOn
    TurnedOff
End Enum

Private Sub LoadCustomOptions()
    ViewOptions.Table = DataSet1.CustomOptions

    With dgvOptions
        .DataSource = ViewOptions

        'Add checkbox
        Dim ChkBox As New DataGridViewCheckBoxColumn
        ChkBox.Name = "ColChk"
        ChkBox.HeaderText = ""
        ChkBox.MinimumWidth = 20
        ChkBox.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
        ChkBox.ThreeState = True
        ChkBox.TrueValue = TriState.TurnedOn
        ChkBox.FalseValue = TriState.TurnedOff
        ChkBox.IndeterminateValue = TriState.Common
        ChkBox.ValueType = GetType(TriState)
        ChkBox.DisplayIndex = 0

        'Width
        .Columns("Name").AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
        .Columns("Description").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill

        'Minimum Width
        .Columns("Description").MinimumWidth = 150

        .Columns.Add(ChkBox)
    End With
End Sub

Attempt

Here's what I tried:

Private Sub dgvOptions_CellContentClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvOptions.CellContentClick
    If e.RowIndex < 0 Then Exit Sub

    If dgvOptions.Columns(e.ColumnIndex).Name = "ColChk" Then
        If dgvOptions.Rows(e.RowIndex).Cells("ColChk").Value = TriState.TurnedOn Or dgvOptions.Rows(e.RowIndex).Cells("ColChk").Value = TriState.Common Then
            dgvOptions.Rows(e.RowIndex).Cells("ColChk").Value = TriState.TurnedOff
        Else
            dgvOptions.Rows(e.RowIndex).Cells("ColChk").Value = TriState.TurnedOn
        End If
    End If
End Sub

I still get the indeterminate state when the user clicks on the custom options checkbox. Is there an another way to approach this that I'm ignoring?

Upvotes: 1

Views: 1764

Answers (1)

Alex
Alex

Reputation: 4948

Finally figured it out. Keep in mind I am using my TriState Enum mapping in the CurrentCellDirtyStateChanged.

The problem is the DataGridView.CurrentCell.Value property (which is the only link to the current setting of the checkbox) is normally only updated when the user causes the DataGridView to commit the change to the checkbox by moving to another cell. Doesn't matter how many times the user clicks the same checkbox, the Value property is not updated.

Private Sub dgvOptions_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As EventArgs) Handles dgvOptions.CurrentCellDirtyStateChanged
    If TypeOf dgvOptions.CurrentCell.OwningColumn Is DataGridViewCheckBoxColumn AndAlso dgvOptions.IsCurrentCellDirty Then

        dgvOptions.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)

        If DirectCast(dgvOptions.CurrentCell.Value, TriState) = TriState.Common Then
            dgvOptions.CurrentCell.Value = TriState.TurnedOff
            dgvOptions.EndEdit()
        End If
    End If
End Sub

So, the solution is to set the ThreeState property of your DataGridViewCheckBoxColumn to True and force the DataGridView to immediately commit the change to the checkbox, so you can test for the Indeterminate setting and change the Value property to Unchecked instead.

For more information, this link helped me a lot.

Upvotes: 1

Related Questions