68

I have few columns in my DataGridView, and there is data in my rows. I saw few solutions in here, but I can not combine them!

Simply a way to right-click on a row, it will select the whole row and show a menu with an option to delete the row and when the option selected it will delete the row.

I made few attempts but none is working and it looks messy. What should I do?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Data-Base
  • 8,418
  • 36
  • 74
  • 98
  • Your question is too vague. Add more details where you having a problem. What you are trying to do, is not very difficult. – leppie Jun 14 '10 at 06:11

12 Answers12

118

I finally solved it:

  • In Visual Studio, create a ContextMenuStrip with an item called "DeleteRow"

  • Then at the DataGridView link the ContextMenuStrip

Using the code below helped me getting it work.

this.MyDataGridView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MyDataGridView_MouseDown);
this.DeleteRow.Click += new System.EventHandler(this.DeleteRow_Click);

Here is the cool part

private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Right)
    {
        var hti = MyDataGridView.HitTest(e.X, e.Y);
        MyDataGridView.ClearSelection();
        MyDataGridView.Rows[hti.RowIndex].Selected = true;
    }
}

private void DeleteRow_Click(object sender, EventArgs e)
{
    Int32 rowToDelete = MyDataGridView.Rows.GetFirstRow(DataGridViewElementStates.Selected);
    MyDataGridView.Rows.RemoveAt(rowToDelete);
    MyDataGridView.ClearSelection();
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
Data-Base
  • 8,418
  • 36
  • 74
  • 98
  • Hi what control you use in DeleteRow_Click? – Crimsonland Feb 22 '11 at 23:40
  • This answer does not seems to work when a `ContextMenuStripNeeded` event is present on the grid. Using `CellMouseDown` works. – JB. Apr 25 '13 at 14:59
  • 4
    Very helpful, thanks! If you're using `AllowUserToAddRows`, you might want to check if `MyDataGridView.Rows[rowToDelete].IsNewRow` before doing the `RemoveAt()`, just in case the user has right clicked a new row. – Henrik Heimbuerger Nov 08 '13 at 18:10
  • Thanks for sharing this! I would suggest checking the hit type as well: if (hit.Type == DataGridViewHitTestType.Cell) { ... } See: https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.hittest(v=vs.110).aspx – Ben Keene Nov 01 '17 at 17:27
  • Thanks. I would add a "if (hti.RowIndex != -1)" check after setting hti, to care for user click on an empty area. – Sohail Nov 30 '22 at 08:12
44

For completness of this question, better to use a Grid event rather than mouse.

First Set your datagrid properties:

SelectionMode to FullRowSelect and RowTemplate / ContextMenuStrip to a context menu.

Create the CellMouseDown event:-

private void myDatagridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        int rowSelected = e.RowIndex;
        if (e.RowIndex != -1)
        {
            this.myDatagridView.ClearSelection();
            this.myDatagridView.Rows[rowSelected].Selected = true;
        }
        // you now have the selected row with the context menu showing for the user to delete etc.
    }
}
Jeroen Heier
  • 3,520
  • 15
  • 31
  • 32
27k1
  • 2,212
  • 1
  • 22
  • 22
  • This answer works when a `ContextMenuStripNeeded` is present. The `MouseDown` based solutions does not. – JB. Apr 25 '13 at 14:58
  • @peter How to get the index of rows if multiple rows are selected ? – Vbp Dec 22 '13 at 19:53
  • Hi vbp, I think you will need to raise a new question if not already answered, this question refers to selecting only 1 row. – 27k1 Dec 29 '13 at 10:48
11
private void dgvOferty_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e)
    {
        dgvOferty.ClearSelection();
        int rowSelected = e.RowIndex;
        if (e.RowIndex != -1)
        {
            this.dgvOferty.Rows[rowSelected].Selected = true;
        }
        e.ContextMenuStrip = cmstrip;
    }

TADA :D. The easiest way period. For custom cells just modify a little.

Cooler
  • 111
  • 1
  • 2
  • 2
    Best method, also works when using keyboard only. However be warned: only works if a DataSource is attached. MSDN about DataGridView.CellContextMenuStripNeeded Event: "The CellContextMenuStripNeeded event occurs only when the DataGridView control DataSource property is set or its VirtualMode property is true." – Harald Coppoolse Feb 12 '16 at 08:27
  • What's the `cmstrip` variable referencing? – reformed Apr 06 '16 at 20:50
  • @reformed it's referencing the ContextMenuStrip that has been added from toolbox. – Mirwise Khan Nov 16 '18 at 10:31
3

It's much more easier to add only the event for mousedown:

private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        var hti = MyDataGridView.HitTest(e.X, e.Y);
        MyDataGridView.Rows[hti.RowIndex].Selected = true;
        MyDataGridView.Rows.RemoveAt(rowToDelete);
        MyDataGridView.ClearSelection();
    }
}

This is easier. Of cource you have to init your mousedown-event as already mentioned with:

this.MyDataGridView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MyDataGridView_MouseDown);

in your constructor.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

All the answers posed in to this question are based on a mouse click event. You can also assign a ContenxtMenuStrip to your DataGridview and check if there is a row selected when the user RightMouseButtons on the DataGridView and decide whether you want to view the ContenxtMenuStrip or not. You can do so by setting the CancelEventArgs.Cancel value in the the Opening event of the ContextMenuStrip

    private void MyContextMenuStrip_Opening(object sender, CancelEventArgs e)
    {
        //Only show ContextMenuStrip when there is 1 row selected.
        if (MyDataGridView.SelectedRows.Count != 1) e.Cancel = true;
    }

But if you have several context menu strips, with each containing different options, depending on the selection, I would go for a mouse-click-approach myself as well.

Mike de Klerk
  • 11,906
  • 8
  • 54
  • 76
2

base on @Data-Base answer it will not work until make selection mode FullRow

  MyDataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

but if you need to make it work in CellSelect Mode

 MyDataGridView.SelectionMode = DataGridViewSelectionMode.CellSelect;

 // for cell selection
 private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
 {
  if(e.Button == MouseButtons.Right)
    {
       var hit = MyDataGridView.HitTest(e.X, e.Y);
       MyDataGridView.ClearSelection();

       // cell selection
       MyDataGridView[hit.ColumnIndex,hit.RowIndex].Selected = true;
   }
}

private void DeleteRow_Click(object sender, EventArgs e)
{
   int rowToDelete = MyDataGridView.Rows.GetFirstRow(DataGridViewElementStates.Selected);
   MyDataGridView.Rows.RemoveAt(rowToDelete);
   MyDataGridView.ClearSelection();
}
Hisham
  • 1,279
  • 1
  • 17
  • 23
1
private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Right)
    {
        MyDataGridView.ClearSelection();
        MyDataGridView.Rows[e.RowIndex].Selected = true;
    }
}

private void DeleteRow_Click(object sender, EventArgs e)
{
    Int32 rowToDelete = MyrDataGridView.Rows.GetFirstRow(DataGridViewElementStates.Selected);
    MyDataGridView.Rows.RemoveAt(rowToDelete);
    MyDataGridView.ClearSelection();
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nosic
  • 11
  • 1
1
private void dataGridView1_CellContextMenuStripNeeded(object sender, 
DataGridViewCellContextMenuStripNeededEventArgs e)
{            
    if (e.RowIndex != -1)
    {
        dataGridView1.ClearSelection();
        this.dataGridView1.Rows[e.RowIndex].Selected = true;
        e.ContextMenuStrip = contextMenuStrip1;
    }
}
vavtech
  • 41
  • 3
1

It is work for me without any errors:

this.dataGridView2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MyDataGridView_MouseDown); 
this.dataGridView2.Click += new System.EventHandler(this.DeleteRow_Click);

And this

private void MyDataGridView_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        var hti = dataGridView2.HitTest(e.X, e.Y);
        dataGridView2.ClearSelection();
        dataGridView2.Rows[hti.RowIndex].Selected = true;
    }

}


private void DeleteRow_Click(object sender, EventArgs e)
{
    Int32 rowToDelete = dataGridView2.Rows.GetFirstRow(DataGridViewElementStates.Selected);
    if (rowToDelete == -1) { }
    else 
    {
        dataGridView2.Rows.RemoveAt(rowToDelete);
        dataGridView2.ClearSelection();
    }
}
Dmitry Dronov
  • 350
  • 3
  • 11
0

You can also make this a little simpler by using the following inside the event code:

private void MyDataGridView_MouseDown(object sender, MouseEventArgs e) 
{     
    if (e.Button == MouseButtons.Right)     
    {         
        rowToDelete = e.RowIndex;
        MyDataGridView.Rows.RemoveAt(rowToDelete);         
        MyDataGridView.ClearSelection();     
    } 
}
Josh Darnell
  • 11,304
  • 9
  • 38
  • 66
JoBaxter
  • 710
  • 2
  • 12
  • 23
  • This would just delete the row with no warning or confirmation. I'm sure the OP doesn't want that. – ProfK Sep 28 '12 at 08:18
0

See here it can be done using the DataGridView RowTemplate property.

Note: This code isn't tested but I've used this method before.

// Create DataGridView
DataGridView gridView = new DataGridView();
gridView.AutoGenerateColumns = false;
gridView.Columns.Add("Col", "Col");

// Create ContextMenu and set event
ContextMenuStrip cMenu = new ContextMenuStrip();
ToolStripItem mItem = cMenu.Items.Add("Delete");
mItem.Click += (o, e) => { /* Do Something */ };           

// This makes all rows added to the datagridview use the same context menu
DataGridViewRow defaultRow = new DataGridViewRow();
defaultRow.ContextMenuStrip = cMenu;

And there you go, as easy as that!

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Zach Johnson
  • 682
  • 7
  • 14
0

I have a new workaround to come in same result, but, with less code. for Winforms... That's example is in portuguese Follow up step by step

  1. Create a contextMenuStrip in your form and create one item
  2. Sign one event click (OnCancelarItem_Click) for this contextMenuStrip enter image description here
  3. Create a event 'UserDeletingRow' on gridview enter image description here and now... you've simulating on key press del from user

    you don't forget to enable delete on the gridview, right?!

enter image description here enter image description here and finally... enter image description here

Marinpietri
  • 112
  • 3
  • 8