DataGridViewCheckBoxColumn - Disable Cell

RobA2345

New member
Joined
Dec 22, 2007
Messages
3
Location
Manchester, England
Programming Experience
1-3
Hi All,

I'm really struggling with this problem now and like many others I bet it's so simple to solve.

I have a DataGridView with a DataGridViewCheckBoxColumn, I want to disable certain cells in the CheckBoxColumn from being checked. Does anyone know how to do this?

Example: I have two columns one a number and one a CheckBoxColumn. If the number is 1 then I don't want the user to be able to Check the cell on that row.

I'd really appreciate any help you can offer.

Thanks,
Rob
 
ReadOnly of DataGridView will enable/disable editing for all cells, you have to set ReadOnly for each cell (depending on the other cell value), this can for example be done from CellEndEdit event:
VB.NET:
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
Handles DataGridView1.CellEndEdit
    If e.ColumnIndex = 0 Then
        If ("1").Equals(Me.DataGridView1.Rows(e.RowIndex).Cells(0).Value) Then
            Me.DataGridView1.Rows(e.RowIndex).Cells(1).ReadOnly = True
        Else
            Me.DataGridView1.Rows(e.RowIndex).Cells(1).ReadOnly = False
        End If
    End If
End Sub
If you databind it is easiest to initially iterate existing rows and set ReadOnly accordingly. (sample For Each below)
String "1" was used here, you might have a Integer column where the value is 1.

That Readonly checkbox cells have same appearance as editable is not what I favour, I think they should look "disabled", this can be done by inheriting a DataGridViewCheckBoxCell and overriding Paint to draw appropriate checkboxes, like this:
VB.NET:
Class dgvcbcell
    Inherits DataGridViewCheckBoxCell

    Protected Overrides Sub Paint(ByVal graphics As System.Drawing.Graphics, _
                                  ByVal clipBounds As System.Drawing.Rectangle, _
                                  ByVal cellBounds As System.Drawing.Rectangle, _
                                  ByVal rowIndex As Integer, _
                                  ByVal elementState As System.Windows.Forms.DataGridViewElementStates, _
                                  ByVal value As Object, _
                                  ByVal formattedValue As Object, _
                                  ByVal errorText As String, _
                                  ByVal cellStyle As System.Windows.Forms.DataGridViewCellStyle, _
                                  ByVal advancedBorderStyle As System.Windows.Forms.DataGridViewAdvancedBorderStyle, _
                                  ByVal paintParts As System.Windows.Forms.DataGridViewPaintParts)

        MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, _
                      formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
        If Me.ReadOnly Then
            Dim cbsz As Size = CheckBoxRenderer.GetGlyphSize(graphics, VisualStyles.CheckBoxState.CheckedDisabled)
            Dim pt As Point = cellBounds.Location
            pt.Offset((cellBounds.Width - cbsz.Width - 1) / 2, (cellBounds.Height - cbsz.Height - 1) / 2)
            If (True).Equals(Me.Value) Then
                CheckBoxRenderer.DrawCheckBox(graphics, pt, VisualStyles.CheckBoxState.CheckedDisabled)
            Else
                CheckBoxRenderer.DrawCheckBox(graphics, pt, VisualStyles.CheckBoxState.UncheckedDisabled)
            End If
        End If
    End Sub
  
End Class
Again, depending on if you are databinding or not there are different ways of using this type cell, for unbound it is easiest to add the column in code and set CellTemplate:
VB.NET:
Dim cbcol As New DataGridViewCheckBoxColumn
cbcol.CellTemplate = New dgvcbcell
Me.DataGridView1.Columns.Add(cbcol)
For bound columns it is easiest to add the columns in designer, then in code something like this:
VB.NET:
Me.DataGridView1.AutoGenerateColumns = False
Me.DataGridView1.Columns(1).CellTemplate = New dgvcbcell
Me.DataGridView1.DataSource = datasource()
Me.DataGridView1.DataMember = "table1"
For Each row As DataGridViewRow In Me.DataGridView1.Rows
    row.Cells(1).ReadOnly = (row.Cells(0).Value = "1")
Next
I had some difficulties getting the DGV to make first correct paint, therefore had to add this also:
VB.NET:
Private Sub frmDiv_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
    Me.DataGridView1.Update()
    Me.DataGridView1.Refresh()
End Sub
 
Thinking about it, adding a Enabled property to the cell and checking condition "If Not Me.Enabled.." would make a clearer case. From another perspective for instance when one have a fully readonly DGV for display purposes only it would have looked very dull with all cells greyed out if this was default appearance for readonly cells. But in this context it makes sense to give user this indication about which checkboxes are interactive and not.
 
Back
Top