将可单击按钮添加到自定义DataGridViewCell控件

时间:2015-01-09 13:24:50

标签: vb.net winforms datagridview custom-controls

我使用DataGridViewCell控件创建了一个自定义DataGridViewColumn控件。 我们的想法是在数据绑定时动态创建单元格的内容,该单元格由一系列可单击的功能按钮组成。按钮的数量和种类取决于传递的数据值。

为此,我重写DataGridViewCell的Paint方法并检查其内容的formattedValue并相应地绘制按钮。但是,这些按钮已经死了"而不是可点击的,所以问题是如何使它们可点击,即如何为点击事件添加处理程序?

我是否必须覆盖单元格的OnClick方法,然后尝试确定哪个按钮完全被点击?这甚至可能吗?还有更好的方法吗?

这是我到目前为止所得到的:

    Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle, rowIndex As Integer, cellState As DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, paintParts As DataGridViewPaintParts)

    MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)

    Dim cellBackground As New SolidBrush(cellStyle.BackColor)
    graphics.FillRectangle(cellBackground, cellBounds)
    cellBackground.Dispose()

    PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)

    Dim sValue As String = formattedValue.ToString()

    If (sValue.Contains("ViewAsPDF")) Then

        Dim buttonArea As Rectangle = cellBounds
        Dim buttonAdjustment As Rectangle = Me.BorderWidths(advancedBorderStyle)
        buttonArea.X += buttonAdjustment.X
        buttonArea.Y += buttonAdjustment.Y
        buttonArea.Height -= buttonAdjustment.Height
        buttonArea.Width -= buttonAdjustment.Width
        buttonArea.Width = buttonArea.Width / 4
        ButtonRenderer.DrawButton(graphics, buttonArea, PushButtonState.Default)
        TextRenderer.DrawText(graphics, "PDF", Me.DataGridView.Font, buttonArea, SystemColors.ControlText)

    End If

   'etcetera 

End Sub

2 个答案:

答案 0 :(得分:1)

我想你可能走错了路。根据提供的代码,您只需将单元格绘制为看起来像它们包含按钮。由于它们实际上不是对象,因此它们无法引发事件。

I don't understand ButtonRenderer, if you can't create actual Buttons with it

ButtonRender创建一个新的按钮对象,它意味着通过按钮对象进行绘制。通常一个子类的按钮,不会使用它,因为它使用现有的主题和风格,这可能是你想要做的不同的事情(即使DataGridViewButtonCell不使用它 - 至少不是直接使用它。) / p>

从提供的代码中,它似乎每次都在运行每个按钮,而不是从某个集合或定义中绘制。如果“动作”列表需要根据行变化(例如,DOC,XLS或图像行的不同动作),该怎么办?这样做似乎会占用大量代码。


你当前的课程可能并非不可能,但它也不是微不足道的。您可能能够创建虚拟按钮的集合(基本上是绘制时的Rect)并按照您的方式渲染它们。然后在单元格单击事件中,翻译/调整X位置以查看哪个矩形包含thisPt.X以确定要采取的相关操作。

还有“问题”,例如用户调整列大小时会发生什么?当按钮列表因某个其他单元格值而变化时(DOC vs XLS vs IMG vs PDF)怎么办?这需要一组按钮集......以及相当数量的代码。

这并不是说它无法完成,但似乎需要大量代码才能使其更加灵活。


<强> Are there better ways?

我是这么认为的。

更简单的现有解决方案可能是使用现有的DataGridViewComboBoxColumn来存储“操作”或“活动”。它似乎有点混乱,更加用户友好:

enter image description here

只需少量代码即可为每只动物提供不同的列表:

' dogs like to go for walks
Private ActsCan() As String = {"Feed", "Pet", "Bathe", "Brush", "Take for Walk"}
' no walks or baths for cats
Private ActsFel() As String = {"Feed", "Pet", "Baby-Talk To", "Brush"}
' never bathe a Mugwai, comb rather than brush
Private ActsMug() As String = {"Feed", "Pet", "Baby-Talk To", "Comb"}
Private ActsGrem() As String = {"Hide From", "Strangle"}
...
Private Sub dgv_RowEnter(sender As Object, 
          e As DataGridViewCellEventArgs) Handles dgv.RowEnter

    Dim dgvCBO As DataGridViewComboBoxCell
    dgvCBO = CType(dgv.Rows(e.RowIndex).Cells("ColActs"), DataGridViewComboBoxCell)
    dgvCBO.Items.Clear()
    Select Case dgv.Rows(e.RowIndex).Cells("colSpecies").Value.ToString
        Case "Canine"
            dgvCBO.Items.AddRange(ActsCan)
        Case "Feline"
            dgvCBO.Items.AddRange(ActsFel)
        Case "Mugwai"
            dgvCBO.Items.AddRange(ActsMug)
        Case "Gremlin"
            dgvCBO.Items.AddRange(ActsGrem)
    End Select
End Sub

封装大部分 的类可能对未绑定的DGV很有用。当thisRow的触发值与最后一个触发值相同时,可以优化不重建列表。

答案 1 :(得分:1)

这种方法怎么样?只实现了ui。

enter image description here