Button in a column, getting the row from which it came on the Click event handler
Basically your button will inherit the datacontext of a row data object. I am calling it as MyObject and hope MyObject.ID is what you wanted.
private void Button_Click(object sender, RoutedEventArgs e)
{
MyObject obj = ((FrameworkElement)sender).DataContext as MyObject;
//Do whatever you wanted to do with MyObject.ID
}
How to get the row and column of button clicked, in the grid event handler?
See InputHitTest():
UIelement element = (UIelement) Grid.InputHitTest(e.GetPosition(Grid));
row= Grid.GetRow(element);
Button in a DataGrid column, getting the cell values of row from which it came on the Click event handler
Use these helper functions;
http://techiethings.blogspot.com/2010/05/get-wpf-datagrid-row-and-cell.html
On your Update button, hook up Click event, and in the handler, do something like this:
//youll need to google for GetVisualParent function.
DataGridRow row = GetVisualParent<DataGridRow>(button);
for(int j = 0; j < dataGrid.Columns.Count; j++)
DataGridCell cell = GetCell(dataGrid, row, j);
I didn't completely understand what you wanted to do, but this should help.
Isolate click listener in overlapping row and button
You can use event.stopPropagation()
to contain event handling at button-level.
var r1cell2 = document.getElementById('r1cell2');
var r1c2Button = document.createElement("button")
r1c2Button.innerHTML = "R1C2"
r1cell2.appendChild(r1c2Button)
let r1 = document.getElementById("r1")
r1.addEventListener("click", () => {
console.log("R1 clicked")
})
r1c2Button.addEventListener("click", (e) => {
e.stopPropagation();
// ^^^^^ Here you can stop event being passed to upper level event listener
console.log("R1C2 Button clicked")
})
<table id="tableId">
<tr id="r1">
<td id="r1cell1">Cell R1C1</td>
<td id="r1cell2"></td>
</tr>
<tr id="r2">
<td id="r2cell1">Cell R2C1</td>
<td id="r2cell2"></td>
</tr>
</table>
How to handle click event in Button Column in Datagridview?
You've added a button to your DataGridView
and you want to run some code when it's clicked.
Easy peasy - just follow these steps:
Don'ts
First, here's what NOT to do:
I would avoid the suggestions in some of the other answers here and even provided by the documentation at MSDN to hardcode the column index or column name in order to determine if a button was clicked. The click event registers for the entire grid, so somehow you need to determine that a button was clicked, but you should not do so by assuming that your button lives in a particular column name or index... there's an easier way...
Also, be careful which event you want to handle. Again, the documentation and many examples get this wrong. Most examples handle the CellClick
event which will fire:
when any part of a cell is clicked.
...but will also fire whenever the row header is clicked. This necessitates adding extra code simply to determine if the e.RowIndex
value is less than 0
Instead handle the CellContentClick
which only occurs:
when the content within a cell is clicked
For whatever reason, the column header is also considered 'content' within a cell, so we'll still have to check for that below.
Dos
So here's what you should do:
First, cast the sender to type DataGridView
to expose it's internal properties at design time. You can modify the type on the parameter, but that can sometimes make adding or removing handlers tricky.
Next, to see if a button was clicked, just check to make sure that the column raising the event is of type DataGridViewButtonColumn
. Because we already cast the sender to type DataGridView
, we can get the Columns
collection and select the current column using e.ColumnIndex
. Then check if that object is of type DataGridViewButtonColumn
.
Of course, if you need to distinguish between multiple buttons per grid, you can then select based on the column name or index, but that shouldn't be your first check. Always make sure a button was clicked first and then handle anything else appropriately. In most cases where you only have a single button per grid, you can jump right off to the races.
Putting it all together:
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
Update 1 - Custom Event
If you wanted to have a little bit of fun, you can add your own event to be raised whenever a button is clicked on the DataGrid. You can't add it to the DataGrid itself, without getting messy with inheritance etc., but you can add a custom event to your form and fire it when appropriate. It's a little more code, but the upside is that you've separated out what you want to do when a button is clicked with how to determine if a button was clicked.
Just declare an event, raise it when appropriate, and handle it. It will look like this:
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
Update 2 - Extended Grid
What would be great is if we were working with a grid that just did these things for us. We could answer the initial question easily: you've added a button to your DataGridView and you want to run some code when it's clicked
. Here's an approach that extends the DataGridView
. It might not be worth the hassle of having to deliver a custom control with every library, but at least it maximally reuses the code used for determining if a button was clicked.
Just add this to your assembly:
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
That's it. Never touch it again. Make sure your DataGrid is of type DataGridViewExt
which should work exactly the same as a DataGridView. Except it will also raise an extra event that you can handle like this:
Private Sub DataGridView1_ButtonClick(sender As DataGridView, e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellButtonClick
'TODO - Button Clicked - Execute Code Here
End Sub
Finding the click event of DGV button column and transferring to another form
This is answered on the MSDN page for the DataGridViewButtonColumn.
You need to handle either the CellClick or CellContentClick events of the DataGridView.
To attach the handler:
dataGridView1.CellClick += new DataGridViewCellEventHandler(dataGridView1_CellClick);
And the code in the method that handles the evend
void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
// Check that the button column was clicked
if (dataGridView1.Columns[e.ColumnIndex].Name == "MyButtonColumn")
{
// Here you call your method that deals with the row values
// you can use e.RowIndex to find the row
// I also use the row's databounditem property to get the bound
// object from the DataGridView's datasource - this only works with
// a datasource for the control but 99% of the time you should use
// a datasource with this control
object item = dataGridView1.Rows[e.RowIndex].DataBoundItem;
// I'm also just leaving item as type object but since you control the form
// you can usually safely cast to a specific object here.
YourMethod(item);
}
}
Get Grid Row and Grid column of button pressed
From the documentation of RoutedEventHandler
, which is used for the Click
event:
public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);
sender
- The object where the event handler is attached.
Consequently, cast the sender
parameter to Button
and retrieve the row and column from the attached properties using its wrapper methods Grid.GetRow(...)
and Grid.GetColumn(...)
.
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
var row = Grid.GetRow(button);
var column = Grid.GetColumn(button);
// ...other code.
}
Related Topics
Visual Studio Installer > How to Launch App at End of Installer
C#: Getting Names of Properties in a Chain from Lambda Expression
How to Use Async to Increase Winforms Performance
Wcf - Design Parameter Decision
Mvvm Show New Window from Vm When Seperated Projects
JSON Deserialization - Map Array Indices to Properties with JSON.Net
How to Fix the Error:"Unreachable Code Detected"
How to Fill Part of Image with Color
Why Are There System.*.* Dlls in My Bin Release Directory
ASP.NET Gridview: How to Edit and Delete Data Records
Run the Current Application as Single Instance and Show the Previous Instance
How to Redirect to Index from Another Controller
.Net (3.5) Formats Times Using Dots Instead of Colons as Timeseparator for It-It Culture
How to Use Transactionscope in C#
.Net Core 3 Yields Different Floating Point Results from Version 2.2
How to Change the Button Text for 'Yes' and 'No' Buttons in the Messagebox.Show Dialog