WinForms: How to handle DataGridViewButtonColumn click event

Here’s how to handle the DataGridViewButtonColumn button click event:

  • Add an event handler for 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.

WinForm with DataGridView containing a button column

1 – 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)

2 – Add ClickHandler(Person p)

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

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

4 – 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.