Overview

Sometimes when using a DataGridView with a DataGridViewCheckBoxColumn, you might need the ability to select or deselect all of the CheckBoxes in that column of your DataGridView by checking or unchecking one CheckBox in the DataGridViewColumn's HeaderCell. There are several ways to achieve this, but placing a control box CheckBox control on the HeaderCell causes scrolling and rendering problems and is ultimately a very unsatisfactory solution.

A more professional method is to extend the DataGridViewColumnHeaderCell, overriding the Paint and OnMouseClick events to draw a custom CheckBox on the DataGridViewColumnHeaderCell, and to respond to clicks on the CheckBox. An additional isChecked Property keeps track of the CheckBox CheckState.





 


The extended DataGridViewColumnHeaderCell

This is the extended DataGridViewColumnHeaderCell:

The isChecked Property holds the current CheckedState of the CheckBox. When this Property changes, all of the CheckBoxes in the DataGridViewCheckBoxColumn, with the exception of the new row, are assigned the new value.

The Paint event draws a standard HeaderCell with the Text offset to the right, which leaves space to draw a CheckBox at the left. The CheckedState of the CheckBox drawn is dependent on the value of the Boolean isChecked Property.

The OnMouseClick event captures clicks in the rectangle occupied by the CheckBox and toggles the Boolean isChecked Property.



 

Public Class checkHeaderCell
    Inherits DataGridViewColumnHeaderCell
    Dim l As New Point(6, 5)
    Dim s As New Size(12, 12)
 
    Private _isChecked As Boolean
 
    Public Property isChecked() As Boolean
        Get
            Return _isChecked
        End Get
        Set(ByVal value As Boolean)
            _isChecked = value
            Me.DataGridView.EndEdit()
            For x As Integer = 0 To Me.DataGridView.Rows.Count - 1
                If Me.DataGridView.Rows(x).IsNewRow Then Continue For
                Me.DataGridView.Rows(x).Cells(Me.OwningColumn.Index).Value = value
            Next
        End Set
    End Property
  
    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)
        Dim spaces As New String(" "c, 6)
        MyBase.Paint(
                graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState,
                spaces & value.ToString.Trim, spaces & formattedValue.ToString.Trim, errorText, cellStyle, advancedBorderStyle, paintParts)
        CheckBoxRenderer.DrawCheckBox(graphics, New Point(cellBounds.X + 6, 5), If(isChecked, VisualStyles.CheckBoxState.CheckedNormal, VisualStyles.CheckBoxState.UncheckedNormal))
    End Sub
  
    Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs)
        If New Rectangle(l, s).Contains(e.Location) Then
            isChecked = Not isChecked
        End If
        MyBase.OnMouseClick(e)
    End Sub
End Class



  The Form Code

The checkHeaderCell Class is a fully reusable custom component. You just need to add the class to your project, and add one line of code to wire it up to your DataGridViewCheckBoxColumn.

In your Form code, you simply assign a HeaderCell:



Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        DataGridView1.Rows.Add(6)
        For r As Integer = 0 To 5
            DataGridView1.Rows(r).SetValues(String.Format("R{0}C1", r), _
                                            String.Format("R{0}C2", r), _
                                            String.Format("R{0}C3", r), _
                                            False)
        Next
        DataGridView1.Columns(3).HeaderCell = New checkHeaderCell
    End Sub
End Class
 



Other Resources