WinForms: How to handle DataGridViewButtonColumn click event

There’s not a direct way to handle the DataGridViewButtonColumn button click event.

Instead, you have to:

  • Handle the DataGridView.CellContentClick event.
  • Check if they clicked the button column.
  • Execute the button click handling logic, passing in the bound data item.

In this article I’ll show a step-by-step example of how to handle the button click.

Example DataGridView with a button column

When I click the button I want it to say Hi to the person.

Set the DataSource to BindingList<Person>

var people = new BindingList<Person>() { new Person() {FullName="Octavia Harris" }, new Person() {FullName="Thomas Noel" }, new Person() {FullName="Sama Weir" }, new Person() {FullName="Usamah Barclay" } }; dgvHelloWorld.DataSource = people;
Code language: C# (cs)

Add ClickHandler(Person p)

public void ClickHandler(Person p) { MessageBox.Show($"Hi {p.FullName}"); }
Code language: C# (cs)

Add DataGridViewButtonColumn to DataGridView

dgvHelloWorld.Columns.Add(new DataGridViewButtonColumn() { Text = "Say Hi", Tag = (Action<Person>)ClickHandler, UseColumnTextForButtonValue = true, AutoSizeMode = DataGridViewAutoSizeColumnMode.None });
Code language: C# (cs)

Notice I’m setting DataGridViewButtonColumn.Tag = a delegate object to the ClickHandler method. You’ll see why in the next step.

Handle the CellContentClick event

First wire up the CellContentClick handler.

dgvHelloWorld.CellContentClick += DgvHelloWorld_CellContentClick;
Code language: C# (cs)

Now implement the handler.

private void DgvHelloWorld_CellContentClick(object sender, DataGridViewCellEventArgs e) { var grid = (DataGridView)sender; if(e.RowIndex < 0) { //They clicked the header column, do nothing return; } if(grid[e.ColumnIndex, e.RowIndex] is DataGridViewButtonCell) { var clickHandler = (Action<Person>)grid.Columns[e.ColumnIndex].Tag; var person = (Person)grid.Rows[e.RowIndex].DataBoundItem; clickHandler(person); } }
Code language: C# (cs)

Notice that this does not know what method it’s calling. It’s just getting the Action<Person> delegate from the Tag and executing it. This makes the code easy to extend if I want to add another button column. Basically I would just add the button column and set its Tag property to another method. The CellContentClick would not need to be modified at all. This adheres to the Open-Closed Principle and is an example of the Strategy Pattern.

Leave a Comment