VB.NET: CheckBoxColumn Select All Demo
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