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

使用DataGridView控件时需要每一行都有一个查看、修改、删除按钮,可以添加按钮列来实现,可是每一列只能有一个按钮,怎么看都不够美观,于是想能不能在单元格把按钮给画上去。
实例下载链接:https://download.csdn.net/download/zyjq52uys/12456524
效果图如下:
一列多操作按钮
在这里插入图片描述
在这里插入图片描述

直接上代码:
DataGridViewEx:

Public Class DataGridViewEx
    Inherits DataGridView
        ''' <summary>
    ''' 修改按钮点击事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    <Category("自定义事件"), Description("修改按钮点击事件")>
    Public Event CellButtonModifyClicked(ByVal sender As Object, ByVal e As EventArgsEx.DataGridViewClickEventArgsEx)
    ''' <summary>
    ''' 删除按钮点击事件
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    <Category("自定义事件"), Description("删除按钮点击事件")>
    Public Event CellButtonDeleteClicked(ByVal sender As Object, ByVal e As EventArgsEx.DataGridViewClickEventArgsEx)
#Region "按钮事件"
    ''' <summary>
    ''' 引发CellButtonModifyClicked事件
    ''' </summary>
    ''' <param name="columnIndex"></param>
    ''' <param name="rowIndex"></param>
    ''' <param name="value"></param>
    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
    ''' <summary>
    ''' 引发CellButtonDeleteClicked事件
    ''' </summary>
    ''' <param name="columnIndex"></param>
    ''' <param name="rowIndex"></param>
    ''' <param name="value"></param>
    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
        ''' <summary>
        ''' 按钮大小模板Size
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("按钮大小模板。")>
        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
        ''' <summary>
        ''' 鼠标移到按钮时的背景色
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("按钮背景色")>
        Public Property ButtonBack As Color = DefaultButtonBack

        Shared ReadOnly DefaultButtonTextDownColor As Color = Color.Red
        ''' <summary>
        ''' 按钮按下时文本色
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("按钮按下时文本色")>
        Public Property ButtonTextDownColor As Color = DefaultButtonTextDownColor

        Shared ReadOnly DefaultButtonTextFace As Color = Color.Blue
        ''' <summary>
        ''' 默认按钮文本色
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("按钮文本前景色")>
        Public Property ButtonTextFace As Color = DefaultButtonTextFace
        Shared ReadOnly DefaultButtonSpacingWidth As Int32 = 3
        Private _ButtonSpacingWidth As Int32 = DefaultButtonSpacingWidth
        ''' <summary>
        ''' 按钮间距
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("按钮间距")>
        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
        ''' <summary>
        ''' 修改按钮文本
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("修改按钮文本")>
        Public Property ButtonModifyText As String = "修改"
        ''' <summary>
        ''' 删除按钮文本
        ''' </summary>
        ''' <returns></returns>
        <Category("zyjq"), Browsable(True), Localizable(True), Description("删除按钮文本")>
        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
        ''' <summary>
        ''' 按键类型枚举
        ''' </summary>
        Public Enum ButtonType
            ''' <summary>
            ''' 修改按钮
            ''' </summary>
            ButtonModify = 1
            ''' <summary>
            ''' 删除按钮
            ''' </summary>
            ButtonDelete = 2
        End Enum
        ''' <summary>
        ''' 按钮状态枚举
        ''' </summary>
        Public Enum ButtonState
            ''' <summary>
            ''' 默认状态
            ''' </summary>
            ButtonDefault = 1
            ''' <summary>
            ''' 热状态
            ''' </summary>
            ButtonHot = 2
            ''' <summary>
            ''' 鼠标按下状态
            ''' </summary>
            ButtonDown = 3
        End Enum
        <Category("Jonson Design"), Browsable(True), Localizable(True), Description("所属列")>
        Public ReadOnly Property OwningColumnEx As DataGridViewButtonTwoColumnEx
            Get
                Return TryCast(Me.OwningColumn, DataGridViewButtonTwoColumnEx)
            End Get
        End Property

        <Category("Jonson Design"), Browsable(True), Localizable(True), Description("所属表格")>
        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

        ''' <summary>
        ''' 绘制按钮
        ''' </summary>
        ''' <param name="graphics"></param>
        ''' <param name="cellBounds"></param>
        ''' <param name="buttonType">按钮类型枚举</param>
        ''' <param name="buttonState">按钮状态枚举</param>
        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
         ''' <summary>
        ''' 获取在大的Rectangle中的小矩形
        ''' </summary>
        ''' <param name="rectangle">单元格Rectangle</param>
        ''' <param name="smallSize">绘制按钮的Size</param>
        ''' <param name="SpacingWidth">两按钮的间距</param>
        ''' <param name="buttonType">按钮类型</param>
        ''' <param name="absRectangle">输出的按钮相对单元格的Rectangle</param>
        ''' <returns>返回按钮的绝对Rectangle</returns>
        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
相关推荐

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

zyjq52uys

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值