DataGridView with Button Control - Delete Row
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
- Show Image on Button
- Set Text of Button
- Handle Click Event of Button
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
- As mentioned by Ivan in comments, when you use
BindingList
you don't need to set datasource of grid to null and back to binding list with every change. TheBindingList
itself reflects changes to yourDataGridView
.
Delete Row from datagridview using button en each row
A delete command issued as constructor for a OleDbDataAdapter is not correct. However the adapter will execute the command nevertheless. But surely you cannot expect a delete command to be used to fill a datatable.
You still need a SELECT.
Usually this is done removing the row from the grid (this marks the underlying row as deleted then, when you want to save the changes to the database, you should use the orginal DataAdapter and the original DataTable used to initially fill the grid to issue the Update method
This is well explained here Using OleDbDataAdapter to Update a DataTable
Or you could do the update yourself using a separate command and reloading the datatable
// Delete the record on the db
empid = Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells["empid"].Value);
OleDbCommand cmd = new OleDbCommand("delete from apps where appsid= @id", con);
cmd.Parameters.Add("@id", OleDbType.VarWChar).Value = empid;
cmd.ExecuteNonQuery();
// reload the grid with the updated info from the db
OleDbDataAdapter da = new OleDbDataAdapter("Select * from apps", con);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
This of course has the drawback to hit two times the database and reloading everything each time you delete a row.
how to delete row from datagridview with a delete button?
The source must be this: "when the datagridview loses focus it changes the current row to the last data row". This is not the normal case, you must be doing something (keybd events?) to make that happen.
I have made delete buttons under a Grid and they worked fine.
Edit: After clarification, it is about the special status of the 'New Row', it is kind of virtual. I sort of see the reasoning behind that, suppose the selection didn't shift back when leaving the Grid. The CurrentRow would be null. In your case that would be OK, but often it wouldn't.
One idea: track the Current property (BindingSource) and disable the Delete button if no Row is current. Check how it works when a new row is (half) filled.
And otherwise, Jeff's idea looks good too. Or see BFree's answer on this question.
How to trap delete row ( from keyboard ) in datagridview?
Attach to the UserDeletingRow event, and cancel the deletion (when required) by setting e.Cancelled = true
C# Remove element from List in DataGridView with button works only once
I'm using only 2 columns and form my DataGridView Design MetroUI framework, so I don't need to check if my column index is 1, because it is impossible to click column 0, which is used to edit numbers.
So it's enough to delete my elements just right that:
private void DrawGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
return;
createdMap.RemoveAt(e.RowIndex);
DrawGrid.DataSource = createdMap.ToList();
}
According to @RezaAghaei answer this is better idea:
private void MultisetGrid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
return;
if (e.ColumnIndex == 1)
{
createdMap.RemoveAt(e.RowIndex);
DrawGrid.DataSource = null;
DrawGrid.DataSource = createdMap;
}
}
Creating DataGridViewButtonCell to delete item of DataGridView?
Done. Finally I did what I wanted.
I did.
private void setDataSource(){
//added column with image before set datasource
if (grid.Columns["Del"] == null) {
var col = new DataGridViewImageColumn();
col.HeaderText = "";
col.Name = "Del";
col.Image = TerminalControleDeVendas.Properties.Resources.trash;
grid.Columns.Add(col);
}
grid.DataSource = ivDAO.findAllItemVenda(venda);
grid.ClearSelection();
defineGrid();
}
private void defineGrid() {
//header
grid.Columns["produto"].HeaderText = "Produto";
grid.Columns["valorUn"].HeaderText = "Unit.R$";
grid.Columns["quantidade"].HeaderText = "Qtd.";
grid.Columns["total"].HeaderText = "Total R$";
//hide
grid.Columns["id"].Visible = false;
grid.Columns["venda"].Visible = false;
//width
grid.Columns["Del"].Width = 30;
grid.Columns["produto"].Width = 220;
grid.Columns["valorUn"].Width = 80;
grid.Columns["quantidade"].Width = 50;
grid.Columns["total"].Width = 80;
//align
grid.Columns["valorUn"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
grid.Columns["quantidade"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
grid.Columns["total"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
Finally I added the handler to delete item
private void grid_CellContentClick(object sender, DataGridViewCellEventArgs e) {
if (this.grid.Columns[e.ColumnIndex].Name == "Del") {
DialogResult confirma = MessageBox.Show("Deseja realmente excluir o item ?", "Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (confirma == DialogResult.Yes) {
ItemVenda iv = (ItemVenda)grid.CurrentRow.DataBoundItem;
ivDAO.delete(iv);
}
}
}
The result is
Delete a row in DataGridView Control in VB.NET
For Each row As DataGridViewRow In yourDGV.SelectedRows
yourDGV.Rows.Remove(row)
Next
This will delete all rows that had been selected.
Related Topics
Active Directory Com Exception - an Operations Error Occurred (0X80072020)
How to Detect the Original MAC Address After It Has Been Spoofed
Http Error 500.19 When Publish .Net Core Project into Iis with 0X80070005
How to Calculate the Average Rgb Color Values of a Bitmap
C# Image.Clone Out of Memory Exception
How to Use Class Name as Parameter in C#
How to Pass a Table-Value Parameter
How to Asynchronously Read the Standard Output Stream and Standard Error Stream at Once
Copy Values from One Object to Another
Entity Framework 4: How to Find the Primary Key
How to Implement Full Row Selecting in Gridview Without Select Button
Variable Declarations Following If Statements
How to Print PDF on Default Network Printer Using Ghostscript (Gswin32C.Exe) Shell Command