close

最近因為工作上需求,而將矛頭指向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

 

~正所謂,客戶的需求,會讓我們發現,其實自己可以做到更多~

arrow
arrow
    文章標籤
    VB.NET datagridview checkbox
    全站熱搜
    創作者介紹
    創作者 Bruce 的頭像
    Bruce

    小小菜鳥闖蕩數碼世界

    Bruce 發表在 痞客邦 留言(0) 人氣()