I want a Delete button at the end of each row of DataGridView
and by clicking that I want to remove the desired row from the binding list which is data source o
To show a button on DataGridView
rows, you should add a DataGridViewButtonColumn to columns of your grid. Here is some common tasks which you should know when using button column:
Add Button Column to DataGridView
To show a button on each row of your grid, you can add a DataGridViewButtonColumn to columns of your grid programmatically or using designer:
var deleteButton=new DataGridViewButtonColumn();
deleteButton.Name="dataGridViewDeleteButton";
deleteButton.HeaderText="Delete";
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
this.dataGridView1.Columns.Add(deleteButton);
Show Image on Button
If you prefer to draw image on button, you should have an image in a resource and then handle CellPainting event of your grid:
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
if (e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
var image = Properties.Resources.DeleteImage; //An image
e.Paint(e.CellBounds, DataGridViewPaintParts.All);
var x = e.CellBounds.Left + (e.CellBounds.Width - image.Width) / 2;
var y = e.CellBounds.Top + (e.CellBounds.Height - image.Height) / 2;
e.Graphics.DrawImage(image, new Point(x, y));
e.Handled = true;
}
}
Set Text of Button
You can use either of these options:
You can set Text
property of your DataGridViewButtonColumn
and also set its UseColumnTextForButtonValue
to true
, this way the text will display on each cells of that column.
deleteButton.Text="Delete";
deleteButton.UseColumnTextForButtonValue=true;
Also you can use Value
property of cell:
this.dataGridView1.Rows[1].Cells[0].Value = "Some Text";
Also as another option, you can handle CellFormatting event of your grid. This way may be useful when you want to set different texts for buttons.
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
//If this is header row or new row, do nothing
if (e.RowIndex < 0 || e.RowIndex == this.dataGridView1.NewRowIndex)
return;
//If formatting your desired column, set the value
if (e.ColumnIndex=this.dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
e.Value = "Delete";
}
}
Handle Click Event of Button
To hanlde clicks on button, you can handle CellClick or CellContentClick event of your grid. Both events fires by click and by pressing Space key.
void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
//if click is on new row or header row
if( e.RowIndex == dataGridView1.NewRowIndex || e.RowIndex < 0)
return;
//Check if click is on specific column
if( e.ColumnIndex == dataGridView1.Columns["dataGridViewDeleteButton"].Index)
{
//Put some logic here, for example to remove row from your binding list.
//yourBindingList.RemoveAt(e.RowIndex);
// Or
// var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// do something
}
}
Get data of the record on Click event
You have e.RowIndex
, then you can get the data behind the row:
var data = (Product)dataGridView1.Rows[e.RowIndex].DataBoundItem;
// then you can get data.Id, data.Name, data.Price, ...
You need to cast it to the data type of the recore, for example let's say Product
.
If the data binding has been setup to use a DataTable, the the type to cast is DataRowView
.
You can also use dataGridView1.Rows[e.RowIndex].Cells[some cell index].Value
to get value of a specific cell, however DataBoundItem
makes more sense.
Note
BindingList
you don't need to set datasource of grid to null and back to binding list with every change. The BindingList
itself reflects changes to your DataGridView
.