Hi,
I'm trying to render a checkbox in a datagridview column header so that when the checkbox is checked/unchecked all the cells in that column should be checked/unchecked accordingly. The datagridview is bound to a database table but the column containing the checkbox header cell is unbound. The problem is, whenever i click the header checkbox, all the cells in that column are checked but the header checkbox itself gets invisible.
If I click the HEADER (though the checkbox is invisible, still I can click the header) again, all the cells in the column below are unchecked and the header checkbox becomes visible and unchecked. Everything is happening as expected except the visibility of the header checkbox. Why is it so? Please suggest how to get rid of it. Regards.
My code follows below:

''' <summary>
''' The custom class for checkbox header cell.
''' </summary>
Imports System.Drawing

Public Delegate Sub CheckBoxClickedHandler(ByVal state As Boolean)

Public Class DataGridViewCheckBoxHeaderCellEventArgs
    Inherits EventArgs
    Private _bChecked As Boolean

    Public Sub New(ByVal bChecked As Boolean)
        _bChecked = bChecked
    End Sub

    Public ReadOnly Property Checked As Boolean
        Get
            Return _bChecked
        End Get
    End Property
End Class

Public Class DataGridViewCheckBoxHeaderCell
    Inherits DataGridViewColumnHeaderCell
    Private checkBoxLocation As Point
    Private checkBoxSize As Size
    Private _checked As Boolean = False
    Private _cellLocation As New Point
    Private _cbState As Windows.Forms.VisualStyles.CheckBoxState = VisualStyles.CheckBoxState.UncheckedNormal
    Public Event OnCheckBoxClicked As CheckBoxClickedHandler

    Public Sub New()
    End Sub

    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 dataGridViewElementState 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, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)

        Dim p As New Point
        Dim s As Size = CheckBoxRenderer.GetGlyphSize(graphics, Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal)
        p.X = cellBounds.Location.X + (cellBounds.Width / 2) - (s.Width / 2)
        p.Y = cellBounds.Location.Y + (cellBounds.Height / 2) - (s.Height / 2)
        _cellLocation = cellBounds.Location
        checkBoxLocation = p
        checkBoxSize = s

        If _checked Then
            _cbState = Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
        Else
            _cbState = Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
            CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState)
        End If
    End Sub

    Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
        Dim p As New Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y)
        If p.X >= checkBoxLocation.X And p.X <= checkBoxLocation.X + checkBoxSize.Width And p.Y >= checkBoxLocation.Y And p.Y <= checkBoxLocation.Y + checkBoxSize.Height Then
            _checked = Not _checked
            RaiseEvent OnCheckBoxClicked(_checked)
            Me.DataGridView.InvalidateCell(Me)
        End If

        MyBase.OnMouseClick(e)
    End Sub
End Class

''' <summary>
''' Actual class where the custom class is used.
''' dgvContacts is the name of the datagridview.
''' colCheck is the name of the column containing the checkbox header cell.
''' </summary>
Public Class ContactList
'Other declarations...
......................
......................
Private WithEvents _cbHeader As DataGridViewCheckBoxHeaderCell

Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
	_cbHeader = New DataGridViewCheckBoxHeaderCell
        colCheck.HeaderCell = _cbHeader
        colCheck.HeaderText = ""
        colCheck.Visible = True
End Sub

'Other definitions...
.....................
.....................

Private Sub _cbHeader_OnCheckBoxClicked(ByVal state As Boolean) Handles _cbHeader.OnCheckBoxClicked
        For i As Integer = 0 To dgvContacts.RowCount - 1
            dgvContacts("colCheck", i).Value = state
        Next

        dgvContacts.EndEdit()
End Sub
End Class

Hmm... seen a few of these - I guess it must be assignment time...

Without looking into this too much - I'm not going to do this for you, Not sure what checkbox renderer actually does, but it looks like you only call that renderer when the state of the checkbox is unchecked?

To invalidate the checkbox you need to draw it in he first place, which I'm not sure where you're doing that. I think that if I was doing this, I'd be creating a new checkbox control within the header, then the standard stuff happens with invalidate and events through the object graph.

Really difficult to see how you are trying to make this work, so that I can help you to be honest.

Hope that something in there helps...

Thanks @MartinPlatt
Here's my mistake. I overlooked it.

If _checked Then
 _cbState = Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
Else
 _cbState = Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
 CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState)
End If

It should be:

If _checked Then
 _cbState = Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
Else
 _cbState = Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
End If

CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState)
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.