Button in a Column, Getting the Row from Which It Came on the Click Event Handler

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



Leave a reply



Submit