VB.NET学习笔记:winForm扩展DataGridView控件实现一列多操作(如查看详情、修改、删除等)按钮

使用DataGridView控件时需要每一行都有一个查看、修改、删除按钮,可以添加按钮列来实现,可是每一列只能有一个按钮,怎么看都不够美观,于是想能不能在单元格把按钮给画上去。
实例下载链接:https://download.csdn.net/download/zyjq52uys/12456524
效果图如下:
VB.NET学习笔记:winForm扩展DataGridView控件实现一列多操作(如查看详情、修改、删除等)按钮_第1张图片
VB.NET学习笔记:winForm扩展DataGridView控件实现一列多操作(如查看详情、修改、删除等)按钮_第2张图片
VB.NET学习笔记:winForm扩展DataGridView控件实现一列多操作(如查看详情、修改、删除等)按钮_第3张图片

直接上代码:
DataGridViewEx:

Public Class DataGridViewEx
    Inherits DataGridView
        ''' 
    ''' 修改按钮点击事件
    ''' 
    ''' 
    ''' 
    
    Public Event CellButtonModifyClicked(ByVal sender As Object, ByVal e As EventArgsEx.DataGridViewClickEventArgsEx)
    ''' 
    ''' 删除按钮点击事件
    ''' 
    ''' 
    ''' 
    
    Public Event CellButtonDeleteClicked(ByVal sender As Object, ByVal e As EventArgsEx.DataGridViewClickEventArgsEx)
#Region "按钮事件"
    ''' 
    ''' 引发CellButtonModifyClicked事件
    ''' 
    ''' 
    ''' 
    ''' 
    Friend Sub OnCellButtonModifyClicked(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As Object)
        RaiseEvent CellButtonModifyClicked(Me, New EventArgsEx.DataGridViewClickEventArgsEx(columnIndex, rowIndex, value))
    End Sub
    ''' 
    ''' 引发CellButtonDeleteClicked事件
    ''' 
    ''' 
    ''' 
    ''' 
    Friend Sub OnCellButtonDeleteClicked(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As Object)
        RaiseEvent CellButtonDeleteClicked(Me, New EventArgsEx.DataGridViewClickEventArgsEx(columnIndex, rowIndex, value))
    End Sub
#End Region
End Class

DataGridViewButtonColumnEx:

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms.VisualStyles

    Public Class DataGridViewButtonColumnEx
        Inherits DataGridViewColumn

        Shared DefaultButtonSize As Size = New Size(35, 24)
        Private _ButtonSize As Size = DefaultButtonSize
        ''' 
        ''' 按钮大小模板Size
        ''' 
        ''' 
        
        Public Property ButtonSize As Size
            Get
                Return _ButtonSize
            End Get
            Set(ByVal value As Size)
                _ButtonSize = value
            End Set
        End Property

        Shared ReadOnly DefaultButtonBack As Color = Color.Gainsboro
        ''' 
        ''' 鼠标移到按钮时的背景色
        ''' 
        ''' 
        
        Public Property ButtonBack As Color = DefaultButtonBack

        Shared ReadOnly DefaultButtonTextDownColor As Color = Color.Red
        ''' 
        ''' 按钮按下时文本色
        ''' 
        ''' 
        
        Public Property ButtonTextDownColor As Color = DefaultButtonTextDownColor

        Shared ReadOnly DefaultButtonTextFace As Color = Color.Blue
        ''' 
        ''' 默认按钮文本色
        ''' 
        ''' 
        
        Public Property ButtonTextFace As Color = DefaultButtonTextFace
        Shared ReadOnly DefaultButtonSpacingWidth As Int32 = 3
        Private _ButtonSpacingWidth As Int32 = DefaultButtonSpacingWidth
        ''' 
        ''' 按钮间距
        ''' 
        ''' 
        
        Public Property ButtonSpacingWidth As Int32
            Get
                Return _ButtonSpacingWidth
            End Get
            Set(value As Int32)
                If value > 0 Then
                    _ButtonSpacingWidth = value
                End If
            End Set
        End Property
        ''' 
        ''' 修改按钮文本
        ''' 
        ''' 
        
        Public Property ButtonModifyText As String = "修改"
        ''' 
        ''' 删除按钮文本
        ''' 
        ''' 
        
        Public Property ButtonDeleteText As String = "删除"

        Public Overrides Function Clone() As Object
            Dim column As DataGridViewButtonTwoColumnEx = CType(MyBase.Clone(), DataGridViewButtonTwoColumnEx)
            column.ButtonModifyText = ButtonModifyText
            column.ButtonDeleteText = ButtonDeleteText
            Return column
        End Function

        Public Sub New()
            MyBase.New()
            Me.CellTemplate = New DataGridViewButtonTwoCellEx()
            Me.HeaderText = "操作"
            Me.MinimumWidth = DefaultButtonSize.Width * 2 + DefaultButtonSpacingWidth * 3
        End Sub
    End Class

DataGridViewButtonCellEx:

Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
Imports System.Windows.Forms.VisualStyles

    Public Class DataGridViewButtonCellEx
        Inherits DataGridViewButtonCell
        ''' 
        ''' 按键类型枚举
        ''' 
        Public Enum ButtonType
            ''' 
            ''' 修改按钮
            ''' 
            ButtonModify = 1
            ''' 
            ''' 删除按钮
            ''' 
            ButtonDelete = 2
        End Enum
        ''' 
        ''' 按钮状态枚举
        ''' 
        Public Enum ButtonState
            ''' 
            ''' 默认状态
            ''' 
            ButtonDefault = 1
            ''' 
            ''' 热状态
            ''' 
            ButtonHot = 2
            ''' 
            ''' 鼠标按下状态
            ''' 
            ButtonDown = 3
        End Enum
        
        Public ReadOnly Property OwningColumnEx As DataGridViewButtonTwoColumnEx
            Get
                Return TryCast(Me.OwningColumn, DataGridViewButtonTwoColumnEx)
            End Get
        End Property

        
        Public ReadOnly Property DataGridViewEx As DataGridViewEx
            Get
                Return TryCast(Me.DataGridView, DataGridViewEx)
            End Get
        End Property

        '修改按钮状态标志
        Private m_ButtonModifyState As ButtonState = ButtonState.ButtonDefault
        '删除按钮状态标志
        Private m_ButtonDeleteState As ButtonState = ButtonState.ButtonDefault

        Protected Overrides Sub Paint(ByVal graphics As Graphics,
                                      ByVal clipBounds As Rectangle,
                                      ByVal cellBounds As Rectangle,
                                      ByVal rowIndex As Integer,
                                      ByVal elementState 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)
            '是否需要重绘单元格的背景颜色
            'm_brushCellBack = If(Me.DataGridView.SelectedCells.Contains(Me), New SolidBrush(cellStyle.SelectionBackColor), New SolidBrush(cellStyle.BackColor))
            '单元格背景色
            Dim brushCellBack As Brush = New SolidBrush(cellStyle.BackColor)
            graphics.FillRectangle(brushCellBack, cellBounds.X, cellBounds.Y, cellBounds.Width, cellBounds.Height)

            '绘制Modify按钮
            Me.InternalDrawButton(graphics, cellBounds, OwningColumnEx.ButtonModifyText, ButtonType.ButtonModify, m_ButtonModifyState)
            '绘制Delete按钮
            Me.InternalDrawButton(graphics, cellBounds, OwningColumnEx.ButtonDeleteText, ButtonType.ButtonDelete, m_ButtonDeleteState)

            '填充单元格的边框
            MyBase.PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
        End Sub

        ''' 
        ''' 绘制按钮
        ''' 
        ''' 
        ''' 
        ''' 按钮类型枚举
        ''' 按钮状态枚举
        Protected Sub InternalDrawButton(ByVal graphics As Graphics,
                                         ByVal cellBounds As Rectangle,
                                         ByVal buttonText As String,
                                         ByVal buttonType As ButtonType,
                                         ByVal buttonState As ButtonState)
            ' 当前按钮位置大小
            Dim absBtnRegion As Rectangle = Rectangle.Empty
            '按钮背景色画笔
            Dim solidBrushButton As SolidBrush = New SolidBrush(OwningColumnEx.ButtonBack)

            ' 当前按钮绝对位置大小
            Dim buttonRegion As Rectangle = RectangleCommon.GetSmallRectOfRectangle(cellBounds, OwningColumnEx.ButtonSize, OwningColumnEx.ButtonSpacingWidth, buttonType, absBtnRegion)
            '单元格列宽太小则不绘制
            If Not cellBounds.Contains(buttonRegion.X + buttonRegion.Width, buttonRegion.Y) Then Return

            '绘制按钮
            Select Case buttonState
                Case ButtonState.ButtonHot
                    graphics.FillRectangle(solidBrushButton, buttonRegion)
                    TextRenderer.DrawText(graphics, buttonText, Me.DataGridView.Font, buttonRegion, OwningColumnEx.ButtonTextFace)
                Case ButtonState.ButtonDown
                    graphics.FillRectangle(solidBrushButton, buttonRegion)
                    TextRenderer.DrawText(graphics, buttonText, Me.DataGridView.Font, buttonRegion, OwningColumnEx.ButtonTextDownColor)
                Case Else
                    TextRenderer.DrawText(graphics, buttonText, Me.DataGridView.Font, buttonRegion, OwningColumnEx.ButtonTextFace)
            End Select
        End Sub

        Protected Overrides Sub OnMouseMove(ByVal e As DataGridViewCellMouseEventArgs)
            MyBase.OnMouseMove(e)

            If IsInRegion(e.Location, ButtonType.ButtonModify, e.ColumnIndex, e.RowIndex) Then
                m_ButtonModifyState = ButtonState.ButtonHot
                m_ButtonDeleteState = ButtonState.ButtonDefault
                Me.DataGridView.Cursor = Cursors.Hand
            ElseIf IsInRegion(e.Location, ButtonType.ButtonDelete, e.ColumnIndex, e.RowIndex) Then
                m_ButtonModifyState = ButtonState.ButtonDefault
                m_ButtonDeleteState = ButtonState.ButtonHot
                Me.DataGridView.Cursor = Cursors.Hand
            Else
                m_ButtonModifyState = ButtonState.ButtonDefault
                m_ButtonDeleteState = ButtonState.ButtonDefault
                Me.DataGridView.Cursor = Cursors.Default
            End If

            Me.DataGridView.InvalidateCell(Me)
        End Sub

        Protected Overrides Sub OnMouseLeave(ByVal rowIndex As Integer)
            MyBase.OnMouseLeave(rowIndex)
            m_ButtonModifyState = ButtonState.ButtonDefault
            m_ButtonDeleteState = ButtonState.ButtonDefault
            Me.DataGridView.Cursor = Cursors.Default
            Me.DataGridView.InvalidateCell(Me)
        End Sub

        Protected Overrides Sub OnMouseDown(ByVal e As DataGridViewCellMouseEventArgs)
            MyBase.OnMouseDown(e)

            If IsInRegion(e.Location, ButtonType.ButtonModify, e.ColumnIndex, e.RowIndex) Then
                m_ButtonModifyState = ButtonState.ButtonDown
                m_ButtonDeleteState = ButtonState.ButtonDefault
                Me.DataGridView.Cursor = Cursors.Hand
            ElseIf IsInRegion(e.Location, ButtonType.ButtonDelete, e.ColumnIndex, e.RowIndex) Then
                m_ButtonModifyState = ButtonState.ButtonDefault
                m_ButtonDeleteState = ButtonState.ButtonDown
                Me.DataGridView.Cursor = Cursors.Hand
            Else
                m_ButtonModifyState = ButtonState.ButtonDefault
                m_ButtonDeleteState = ButtonState.ButtonDefault
                Me.DataGridView.Cursor = Cursors.Default
            End If

            Me.DataGridView.InvalidateCell(Me)
        End Sub

        Protected Overrides Sub OnMouseClick(ByVal e As DataGridViewCellMouseEventArgs)
            MyBase.OnMouseClick(e)

            If e.Button = MouseButtons.Left Then
                If Me.DataGridViewEx IsNot Nothing Then
                    If IsInRegion(e.Location, ButtonType.ButtonModify, e.ColumnIndex, e.RowIndex) Then
                        Me.DataGridViewEx.OnCellButtonModifyClicked(e.ColumnIndex, e.RowIndex, Me.Value)
                    ElseIf IsInRegion(e.Location, ButtonType.ButtonDelete, e.ColumnIndex, e.RowIndex) Then
                        Me.DataGridViewEx.OnCellButtonDeleteClicked(e.ColumnIndex, e.RowIndex, Me.Value)
                    End If
                End If
            End If
        End Sub

        Protected Function IsInRegion(ByVal p As Point, ByVal buttonType As ButtonType, ByVal columnIndex As Integer, ByVal rowIndex As Integer) As Boolean
            Dim cellBounds As Rectangle = DataGridView(columnIndex, rowIndex).ContentBounds
            Dim absBtnRegion As Rectangle = Rectangle.Empty
            RectangleCommon.GetSmallRectOfRectangle(cellBounds, OwningColumnEx.ButtonSize, OwningColumnEx.ButtonSpacingWidth, buttonType, absBtnRegion)
            Return absBtnRegion.Contains(p)
        End Function
    End Class

获取按钮位置:

Public Class RectangleCommon
         ''' 
        ''' 获取在大的Rectangle中的小矩形
        ''' 
        ''' 单元格Rectangle
        ''' 绘制按钮的Size
        ''' 两按钮的间距
        ''' 按钮类型
        ''' 输出的按钮相对单元格的Rectangle
        ''' 返回按钮的绝对Rectangle
        Public Shared Function GetSmallRectOfRectangle(ByVal rectangle As Rectangle, ByVal smallSize As Size, ByVal SpacingWidth As Int32, ByVal buttonType As Int32, ByRef absRectangle As Rectangle) As Rectangle
            Dim rect As Rectangle = New Rectangle()
            absRectangle = New Rectangle()
            absRectangle.Size = smallSize
            absRectangle.X = SpacingWidth + (SpacingWidth + smallSize.Width) * (buttonType - 1)
            absRectangle.Y = (rectangle.Height - smallSize.Height) \ 2
            rect.Size = smallSize
            rect.X = absRectangle.X + rectangle.X
            rect.Y = absRectangle.Y + rectangle.Y
            Return rect
        End Function
    End Class

单击链接单元格内容事件数据:

    Public Class DataGridViewClickEventArgsEx
        Inherits EventArgs
        Public Property ColumnIndex As Integer
        Public Property RowIndex As Integer
        Public Property Value As Object

        Public Sub New(ByVal columnIndex As Integer, ByVal rowIndex As Integer, ByVal value As Object)
            Me.ColumnIndex = columnIndex
            Me.RowIndex = rowIndex
            Me.Value = value
        End Sub
    End Class

你可能感兴趣的:(VB.NET扩展控件)