DataGridView checkbox column header cell (.Net 4.0).

Sep 13 2011 11:26 AM
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



Answers (1)