最近因為工作上需求,而將矛頭指向DataGridView的ColumnHeader
由於被要求要在上面增加CheckBox全選的功能,而開始了這次的戰鬥
這個要求根本是太有事情了啦!!!
在網路上雖然也有相關文章,但對於我想要的功能還差那一丁點
假如今天有10列資料,選擇10列的話,全選的CheckBox要呈現打勾
而取消了其中一筆,則要取消打勾,這樣比較合理嘛,這位客人,您說是吧?
不過最終還是成功完成這次很有事的任務
那麼廢話不多說,就PO上熱騰騰的程式碼給大家參考參考吧
Public Class dgvHeaderCheckBox
Private colCB AsNew DataGridViewCheckBoxColumn
Private chkHeader As New clsDataGridViewCheckBoxHeaderCell.DataGridViewCheckBoxHeaderCell
Private Sub dgvHeaderCheckBox_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
'添加CheckBox事件
AddHandler chkHeader.OnCheckBoxClicked, AddressOf chkHeader_OnCheckBoxClicked
'添加Checkbox到DataGridView内
colCB.HeaderCell = chkHeader
DataGridView.Columns.Insert(0, colCB)
DataGridView.Columns(0).Width = 130
DataGridView.Columns(0).HeaderText = String.Format(" 0 / {0} 全選", SupString(DataGridView.RowCount))
Catch ex As Exception
MessageBox.Show(ex.Message & System.Environment.NewLine & ex.StackTrace)
End Try
End Sub
'全選\取消全選
Private Sub chkHeader_OnCheckBoxClicked(ByVal state As Boolean)
For Each row As DataGridViewRow In Me.DataGridView.Rows
row.Cells(0).Value = state
Next
'取消選取
Me.DataGridView.CurrentCell = Nothing
End Sub
'委派事件
Public Delegate Sub DataGridViewCheckBoxClickedHandler(ByVal state As Boolean)
'HeaderCheckBox
Public Class DataGridViewCheckBoxHeaderCell
Inherits DataGridViewColumnHeaderCell
Private checkBoxLocation As Point
Private checkBoxSize As Size
Private blnChecked As Boolean = False
Private _cellLocation As New Point()
Private _cbState As System.Windows.Forms.VisualStyles.CheckBoxState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
Public Event OnCheckBoxClicked As DataGridViewCheckBoxClickedHandler
Protected Overridable Overloads Sub DataGridvewOnCheckBoxClicked(ByVal state As Boolean)
RaiseEvent OnCheckBoxClicked(state)
End Sub
'控制全選的CheckBox是否勾選
Public Property IsChecked() As Boolean
Get
Return blnChecked
End Get
Set(ByVal value As Boolean)
blnChecked = value
End Set
End Property
ProtectedOverloadsOverridesSub 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 DataGridViewElementStates, _
ByVal value As Object, _
ByVal formattedValue As Object, _
ByVal errorText As String, _
ByVal cellStyle As DataGridViewCellStyle, _
ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
ByVal paintParts As 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, System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal)
p.X = CInt(cellBounds.Location.X + (cellBounds.Width / 2) - (s.Width / 2))
p.Y = CInt(cellBounds.Location.Y + (cellBounds.Height / 2) - (s.Height / 2))
_cellLocation = cellBounds.Location
checkBoxLocation = p
checkBoxSize = s
If blnChecked Then
_cbState = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
Else
_cbState = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
End If
CheckBoxRenderer.DrawCheckBox(graphics, checkBoxLocation, _cbState)
End Sub
Protected Overloads Overrides Sub OnMouseClick(ByVal e As DataGridViewCellMouseEventArgs)
Dim p As New Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y)
If p.X >= checkBoxLocation.X AndAlso p.X <= checkBoxLocation.X + checkBoxSize.Width AndAlso _
p.Y >= checkBoxLocation.Y AndAlso p.Y <= checkBoxLocation.Y + checkBoxSize.Height Then
blnChecked = Not blnChecked
DataGridvewOnCheckBoxClicked(blnChecked)
Me.DataGridView.InvalidateCell(Me)
End If
MyBase.OnMouseClick(e)
End Sub
End Class
Private Sub DataGridView_CellContentClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView.CellContentClick
Dim blnCheck As Boolean
Dim intCheck As Integer = 0
If e.RowIndex <> -1 Then
blnCheck = CType(sender, DataGridView).Rows(e.RowIndex).Cells.Item(0).Value
CType(sender, DataGridView).Rows(e.RowIndex).Cells.Item(0).Value = Not blnCheck
For Each row As DataGridViewRow In Me.DataGridView.Rows
If row.Cells(0).Value = True Then
intCheck += 1
End If
Next
If intCheck <> DataGridView.RowCount Then
chkHeader.IsChecked = False
Else
chkHeader.IsChecked = True
End If
DataGridView.Columns(0).HeaderText = String.Format("{0} / {1} 全選", SupString(intCheck), SupString(DataGridView.RowCount))
End If
End Sub
Private Sub DataGridView_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView.CellValueChanged
Dim intCheck As Integer = 0
If e.RowIndex <> -1 Then
For Each row As DataGridViewRow In Me.DataGridView.Rows
If row.Cells(0).Value = True Then
intCheck += 1
End If
Next
DataGridView.Columns(0).HeaderText = String.Format("{0} / {1} 全選", SupString(intCheck), SupString(DataGridView.RowCount))
End If
End Sub
Private Function SupString(ByVal intStr As Integer) As String
Dim strRows As String
Try
strRows = intStr.ToString
If strRows.Length = 1 Then
strRows = strRows.Insert(0, " ")
End If
Return strRows
Catch ex As Exception
MessageBox.Show(ex.Message & System.Environment.NewLine & ex.StackTrace)
Return ""
End Try
End Function
End Class
~正所謂,客戶的需求,會讓我們發現,其實自己可以做到更多~