如何处理 Datagridview 按钮列中的单击事件?

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

331789 次浏览

对于 WinForms: ,这里已经给出了完整的回答

这里是 如何: 在 GridView 控件中响应 Button 事件

为了阿斯帕。Net 取决于您实际使用的控件。(您的问题是 DataGrid,但是您正在开发一个 Windows 应用程序,因此您将使用的控件是 DataGridView...)

好吧,我上钩了。

你需要做一些类似的事情——显然这些都是元代码。

button.Click += new ButtonClickyHandlerType(IClicked_My_Button_method)

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

在 IClicks _ MyButton _ 方法中,当您单击它时,您只需放置任何您想要发生的事情。

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

这里的实际细节取决于你,但是如果你在概念上还有什么遗漏的话,请让我知道,我会尽力帮助你。

这解决了我的问题。

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

更好的答案是:

不能为 DataGridViewButtonColumn 中的按钮单元格实现按钮单击事件。相反,可以使用 DataGridView 的 CellClicks 事件并确定是否为 DataGridViewButtonColumn 中的单元格激发了事件。使用事件的 DataGridViewCellEventArgs。属性查找单击了哪一行。

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);
}
}

在这里可以找到: 按钮单击 datagridview 中的事件

你已经添加了一个按钮到你的 DataGridView,你想运行一些代码时,它被点击。

小菜一碟——只要按照以下步骤:

别说了

首先,这是 没有要做的:

我会避免在这里的其他一些答案的建议,甚至由 文件提供的硬编码列索引或列名,以确定是否按钮被点击。点击事件注册整个网格,所以你需要确定一个按钮被点击,但是你不应该这样做,假设你的按钮生活在一个特定的列名或索引... 有一个更简单的方法..。

另外,要小心处理要处理的事件。同样,文档和许多示例都弄错了。大多数示例处理将触发的 CellClick事件:

当单击单元格的任何部分时。

... 但也会在点击 划船标题时触发。这就需要添加额外的代码来确定 e.RowIndex值是否小于0

相反,处理只发生的 CellContentClick:

当单击单元格中的内容时

不管出于什么原因,专栏头也被认为是单元格中的“内容”,因此我们仍然需要在下面检查它。

两个

所以你应该这么做:

首先,演员发送方键入 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

下面是我用来激发 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();


}
}

这里的表格有点晚了,但是在 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();
}
}
}

注意,这样做的好处是,编译器将捕获 任何名称的更改。如果使用更改过的文本名进行索引,或者大写不正确,那么肯定会出现运行时问题。这里您实际上使用了一个对象的名称,该对象是设计器根据您提供的名称创建的。但是任何不匹配都会引起编译器的注意。

大多数投票的解决方案是错误的,因为不能与少数按钮在一行中工作。

最好的解决方案是以下代码:

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


if (e.ColumnIndex == senderGrid.Columns["Opn"].Index && e.RowIndex >= 0)
{
MessageBox.Show("Opn Click");
}


if (e.ColumnIndex == senderGrid.Columns["VT"].Index && e.RowIndex >= 0)
{
MessageBox.Show("VT Click");
}
}

你可以试试这个,你不会太关心列的顺序。

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

例如 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);
}

问候:)

例如,假设 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,因为不需要。

如果有人正在使用 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 子句,或者像 Microsoft 文档的“ 如何: 在 VisualBasic 中调用事件处理程序”中描述的那样发出一个 AddHandler 语句

您将在 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);

我没有使用标题按钮列,但是当客户机单击第一个列标题(不是行标题列,而是我的第一个数据字段)时,我会触发一个事件。

使用与 kylemit 的答案相同的事件(CellContentClick) ,但方法不同。

RowIndex = = -1,捕捉用户在任何头上循环的时候,使用 e.ColumnIndex 你知道哪个头正在单击(0表示第一个头,1表示第二个头,等等)

private void grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
var senderGrid = (DataGridView)sender;
if(e.ColumnIndex == 0 && e.RowIndex == -1)
{
//code for clicking over the first data header.
}
}

问候