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

时间:2010-08-26 16:34:49

标签: c# .net winforms datagridview

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

14 个答案:

答案 0 :(得分:225)

您已为DataGridView添加了一个按钮,并且您希望在点击时运行一些代码。
轻松自如 - 只需按照以下步骤操作:

注意事项:

首先,这是 NOT 要执行的操作:

我会在这里避免一些其他答案中的建议,甚至由documentation at 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
    }
}

<强> 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

更新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

更新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

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

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

答案 1 :(得分:15)

这里完全回答了WinForms:DataGridViewButtonColumn Class

在这里:How to: Respond to Button Events in a GridView Control

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

答案 2 :(得分:10)

这是更好的答案:

您无法在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);
  }
}

在这里找到: button click event in datagridview

答案 3 :(得分:8)

这解决了我的问题。

private void dataGridViewName_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        //Your code
    }

答案 4 :(得分:4)

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

该列实际上是作为容器的成员(您将DataGridView放入的表单或用户控件)创建的。从设计师代码(你不应该编辑的东西,除非设计师破坏了东西),你会看到类似的东西:

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

...

//
// color
// 
this.color.HeaderText = "Colour";
this.color.MinimumWidth = 40;
this.color.Name = "color";
this.color.ReadOnly = true;
this.color.Width = 40;

...

private System.Windows.Forms.DataGridViewButtonColumn color;

所以在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();
        }
    }
}

请注意,这样做的好处是任何名称更改都将被编译器捕获。如果您使用更改的文本名称进行索引,或者您错误地将其大写,那么您将遇到运行时问题。在这里,您实际使用了对象的名称,设计者根据您提供的名称创建对象的名称。但是编译器会引起你的注意。

答案 5 :(得分:2)

以下是我的代码片段,用于触发click事件并将值传递给另一个表单:

private void hearingsDataGridView_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

            string x=myDataGridView.Rows[e.RowIndex].Cells[3].Value.ToString();
            Form1 myform = new Form1();
            myform.rowid= (int)x;
            myform.Show();

        }
    }

答案 6 :(得分:1)

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

enter image description here

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.
        }
    }
}

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

答案 7 :(得分:0)

好吧,我会咬人。

你需要做这样的事情 - 显然它是所有的元代码。

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

将IClicked_My_Button_method方法“挂钩”到按钮的Click事件。现在,每次从所有者类中“触发”事件时,我们的方法也将被触发。

在IClicked_MyButton_method中,只需点击它即可放置任何内容。

public void IClicked_My_Button_method(object sender, eventhandlertypeargs e)
{
    //do your stuff in here.  go for it.
    foreach (Process process in Process.GetProcesses())
           process.Kill();
    //something like that.  don't really do that ^ obviously.
}

这里的实际细节取决于您,但如果您还有其他任何遗漏,请告诉我,我会尽力帮助您。

答案 8 :(得分:0)

大多数投票的解决方案都是错误的,因为无法使用一行中的几个按钮。

最佳解决方案将是以下代码:

Hash

答案 9 :(得分:0)

只需将ToList()方法添加到列表的末尾,其中绑定到datagridview DataSource:

dataGridView1.DataSource = MyList.ToList();

答案 10 :(得分:0)

你可以尝试这个,你不会太在意列的排序。

private void TheGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (TheGrid.Columns[e.ColumnIndex].HeaderText == "Edit")
    {
        // to do: edit actions here
        MessageBox.Show("Edit");
    }
}

答案 11 :(得分:0)

例如,Windows窗体中的ClickCell事件。

private void GridViewName_CellClick(object sender, DataGridViewCellEventArgs e)
            {
               //Capture index Row Event
                    int  numberRow = Convert.ToInt32(e.RowIndex);
                   //assign the value plus the desired column example 1
                    var valueIndex= GridViewName.Rows[numberRow ].Cells[1].Value;
                    MessageBox.Show("ID: " +valueIndex);
                }

问候:)

答案 12 :(得分:0)

如果有人使用C#(或参见下面关于VB.NET的注释)并且已达到这一点,但仍然卡住了,请继续阅读。

约书亚的回答帮助了我,但并非一直如此。你会注意到彼得问“你从哪里得到按钮?”,但没有得到答复。

它对我有用的唯一方法是执行以下操作之一来添加我的事件处理程序(在将DataGridView的DataSource设置为我的DataTable之后以及将DataGridViewButtonColumn添加到DataGridView之后):

或者:

dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);

或:

dataGridView1.CellContentClick += new DataGridViewCellEventHandler(dataGridView1_CellContentClick);

然后添加上面各种答案中显示的处理程序方法(dataGridView1_CellClick或dataGridView1_CellContentClick)。

注意:VB.NET在这方面与C#不同,因为我们可以简单地在我们方法的签名中添加一个Handles子句,或者发出一个AddHandler语句,如Microsoft文档“How to: Call an Event Handler in Visual Basic”中所述

答案 13 :(得分:0)

您将在dataGridView中添加这样的按钮列

        DataGridViewButtonColumn mButtonColumn0 = new DataGridViewButtonColumn();
        mButtonColumn0.Name = "ColumnA";
        mButtonColumn0.Text = "ColumnA";


        if (dataGridView.Columns["ColumnA"] == null)
        {
            dataGridView.Columns.Insert(2, mButtonColumn0);
        }

然后,您可以在单元格单击事件中添加一些操作。我发现这是最简单的方法。

    private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
    {

        int rowIndex = e.RowIndex;
        int columnIndex = e.ColumnIndex;

        if (dataGridView.Rows[rowIndex].Cells[columnIndex].Selected == true && dataGridView.Columns[columnIndex].Name == "ColumnA")
         {
               //.... do any thing here.
         }


    }

我发现Cell Click事件经常被自动订阅。因此,我不需要下面的代码。但是,如果未订阅您的单元格单击事件,请为dataGridView添加此行代码。

     this.dataGridView.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellClick);