如何在Datagridview中的Button列中处理click事件?

Him*_*dri 126 .net c# datagridview winforms

我正在使用C#开发一个Windows应用程序.我DataGridView用来显示数据.我在其中添加了一个按钮列.我想知道如何在DataGridView中处理该按钮上的click事件.

Kyl*_*Mit 238

您已经为自己添加了一个按钮,DataGridView并且想要在单击时运行一些代码.
容易腻 - 只需按照以下步骤操作:

注意事项:

首先,这是不该做的事情:

我会在这里避免一些其他答案中的建议,甚至由MSDN上的文档提供硬编码列索引或列名以确定是否单击了一个按钮.click事件为整个网格注册,因此您需要确定单击了一个按钮,但是您不应该通过假设您的按钮位于特定的列名称或索引中而这样做...这是一种更简单的方法...

另外,请注意您要处理的事件.同样,文档和许多示例都错了.大多数示例处理CellClick将触发的事件:

单击单元格的任何部分时.

...但是每当单击标题时也会触发.这需要添加额外的代码以确定该e.RowIndex值是否小于0

而是处理CellContentClick只发生的事情:

单击单元格中的内容时

无论出于何种原因,标题在单元格中也被视为"内容",因此我们仍需要检查以下内容.

DOS:

所以这就是你应该做的:

首先,发送者强制转换DataGridView为在设计时公开其内部属性.您可以修改参数的类型,但这有时会使添加或删除处理程序变得棘手.

接下来,要查看是否单击了按钮,只需检查以确保引发事件的列是类型DataGridViewButtonColumn.因为我们已经将发送者强制转换为类型DataGridView,所以我们可以获取Columns集合并使用选择当前列e.ColumnIndex.然后检查该对象是否是类型DataGridViewButtonColumn.

当然,如果您需要区分每个网格的多个按钮,则可以根据列名称或索引进行选择,但这不应该是您的第一次检查.始终确保先单击一个按钮,然后再适当地处理其他任何操作.在大多数情况下,每个网格只有一个按钮,您可以直接跳到比赛.

把它们放在一起:

C#:

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    var senderGrid = (DataGridView)sender;

    if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
        e.RowIndex >= 0)
    {
        //TODO - Button Clicked - Execute Code Here
    }
}
Run Code Online (Sandbox Code Playgroud)

VB:

Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) _
                                           Handles DataGridView1.CellContentClick
    Dim senderGrid = DirectCast(sender, DataGridView)

    If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso
       e.RowIndex >= 0 Then
        'TODO - Button Clicked - Execute Code Here
    End If

End Sub
Run Code Online (Sandbox Code Playgroud)

更新1 - 自定义事件

如果您想获得一些乐趣,只要在DataGrid上单击一个按钮,就可以添加自己的事件.您无法将其添加到DataGrid本身,也不会使继承变得混乱,但您可以在表单中添加自定义事件并在适当时触发它.这是一个更多的代码,但好处是你已经分离出单击按钮时想要做什么以及如何确定是否单击了一个按钮.

只需声明一个事件,在适当时提高它并处理它.它看起来像这样:

Event DataGridView1ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)

Private Sub DataGridView1_CellContentClick(sender As System.Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
    Dim senderGrid = DirectCast(sender, DataGridView)
    If TypeOf senderGrid.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
        RaiseEvent DataGridView1ButtonClick(senderGrid, e)
    End If
End Sub

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) Handles Me.DataGridView1ButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
Run Code Online (Sandbox Code Playgroud)

更新2 - 扩展网格

如果我们正在为我们做这些事情的网格工作,那将是多么伟大的事情.我们可以轻松回答最初的问题:you've added a button to your DataGridView and you want to run some code when it's clicked.这是一种扩展的方法DataGridView.可能不值得为每个库提供自定义控件的麻烦,但至少它最大限度地重用用于确定是否单击按钮的代码.

只需将其添加到您的程序集:

Public Class DataGridViewExt : Inherits DataGridView

    Event CellButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs)

    Private Sub CellContentClicked(sender As System.Object, e As DataGridViewCellEventArgs) Handles Me.CellContentClick
        If TypeOf Me.Columns(e.ColumnIndex) Is DataGridViewButtonColumn AndAlso e.RowIndex >= 0 Then
            RaiseEvent CellButtonClick(Me, e)
        End If
    End Sub

End Class
Run Code Online (Sandbox Code Playgroud)

而已.切勿再次触摸它.确保您的DataGrid的类型DataGridViewExt应与DataGridView完全相同.除了它还会引发一个额外的事件,你可以像这样处理:

Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
                                      Handles DataGridView1.CellButtonClick
    'TODO - Button Clicked - Execute Code Here
End Sub
Run Code Online (Sandbox Code Playgroud)

  • +1.但是,在我们的例子中,列是一个通用的DataGridViewColumn,我必须检查单元格类型:`TypeOf senderGrid.Rows(e.RowIndex).Cells(e.ColumnIndex)是DataGridViewButtonCell` (3认同)
  • 在 VB.net 中,您不必检查列索引。我将这个确切的示例用于具有两列的 dgv。一列可编辑,第二列带有删除按钮。我点击整个 dgv,只有当我点击按钮时才会触发事件。 (2认同)
  • 更新 2 的 C# 代码 `public class DataGridViewExt : DataGridView { public event DataGridViewCellEventHandler CellButtonClick; 公共 DataGridViewExt() { this.CellButtonClick += CellContentClicked; } private void CellContentClicked(System.Object sender, DataGridViewCellEventArgs e) { if (this.Columns[e.ColumnIndex].GetType() == typeof(DataGridViewButtonColumn) && e.RowIndex >= 0 ) { CellButtonClick.Invoke(this, e );} } }` (2认同)

Dav*_*vid 15

这里完全回答了WinForms:DataGridViewButtonColumn类

在这里:如何:响应GridView控件中的按钮事件

对于Asp.Net,取决于您实际使用的控件.(你的问题是DataGrid,但是你正在开发一个Windows应用程序,所以你在那里使用的控件是一个DataGridView ...)


小智 9

这是更好的答案:

您无法在DataGridViewButtonColumn中为按钮单元格实现按钮单击事件.而是使用DataGridView的CellClicked事件,并确定是否为DataGridViewButtonColumn中的单元格触发了事件.使用事件的DataGridViewCellEventArgs.RowIndex属性来查找单击的行.

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  // Ignore clicks that are not in our 
  if (e.ColumnIndex == dataGridView1.Columns["MyButtonColumn"].Index && e.RowIndex >= 0) {
    Console.WriteLine("Button on row {0} clicked", e.RowIndex);
  }
}
Run Code Online (Sandbox Code Playgroud)

在此处找到: datagridview中的按钮单击事件


Him*_*dri 8

这解决了我的问题.

private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        //Your code
    }
Run Code Online (Sandbox Code Playgroud)


Aru*_*nas 5

这里的表格有点晚了,但是在 c# (vs2013) 中,您也不需要使用列名,事实上,有些人提出的许多额外工作是完全没有必要的。

该列实际上是作为容器的成员创建的(窗体或您已将 DataGridView 放入的用户控件)。从设计器代码(除非设计器破坏某些东西,否则您不应该编辑的内容),您会看到如下内容:

this.curvesList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
        this.enablePlot,
        this.desc,
        this.unit,
        this.min,
        this.max,
        this.color});
Run Code Online (Sandbox Code Playgroud)

...

//
// color
// 
this.color.HeaderText = "Colour";
this.color.MinimumWidth = 40;
this.color.Name = "color";
this.color.ReadOnly = true;
this.color.Width = 40;
Run Code Online (Sandbox Code Playgroud)

...

private System.Windows.Forms.DataGridViewButtonColumn color;
Run Code Online (Sandbox Code Playgroud)

因此,在 CellContentClick 处理程序中,除了确保行索引不为 0 外,您只需通过比较对象引用来检查单击的列是否实际上是您想要的列:

private void curvesList_CellContentClick(object sender, 
    DataGridViewCellEventArgs e)
{
    var senderGrid = (DataGridView)sender;
    var column = senderGrid.Columns[e.ColumnIndex];
    if (e.RowIndex >= 0)
    {
        if ((object)column == (object)color)
        {
            colorDialog.Color = Color.Blue;
                colorDialog.ShowDialog();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这样做的好处在于任何名称更改都会被编译器捕获。如果您使用更改的文本名称或大小写不正确的文本名称进行索引,则必然会出现运行时问题。在这里,您实际上使用了一个对象的名称,该名称是设计人员根据您提供的名称创建的。但是编译器会提醒您注意任何不匹配。


小智 5

假设例如DataGridView具有如下所示的列,并且其数据绑定项属于PrimalPallet您可以使用下面给出的解决方案的类型。

在此输入图像描述

private void dataGridView1_CellContentClick( object sender, DataGridViewCellEventArgs e )
{
    if ( e.RowIndex >= 0 )
    {
        if ( e.ColumnIndex == this.colDelete.Index )
        {
            var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
            this.DeletePalletByID( pallet.ID );
        }
        else if ( e.ColumnIndex == this.colEdit.Index )
        {
            var pallet = this.dataGridView1.Rows[ e.RowIndex ].DataBoundItem as PrimalPallet;
            // etc.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

直接访问列比使用列更安全dataGridView1.Columns["MyColumnName"],并且不需要解析,sender因为DataGridView不需要。