Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# DataGridView opening ContextMenu at location of Right Click

I've looked around for quite a while now trying to find a working solution but am resorting to asking a question:

I have a DataGridView in a Dialog Form in my app, that I want a ContextMenu to appear on Right-Click of Cell.

I have the right-click and the ContextMenu appearing fine, however no matter what solution on StackExchange I attempt, it is always offset quite alot.

Is this to do with the form and/or it's parent? Or am I just stupidly missing something here?

Thanks Jamie

Form.cs

private void dataGridContents_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        if (e.RowIndex > -1 && e.ColumnIndex > -1)
        {
            Debug.WriteLine("Cell right clicked!");

            DataGridViewCell cell = (sender as DataGridView)[e.ColumnIndex, e.RowIndex];

            contextCell.Show(cell.DataGridView, PointToClient(Cursor.Position));

            if (!cell.Selected)
            {
                cell.DataGridView.ClearSelection();
                cell.DataGridView.CurrentCell = cell;
                cell.Selected = true;
            }
        }
    }
}

Edit

Sorry, I have tried:

  • new Point(e.X, e.Y)
  • new Point(e.Location.X, e.Location.Y)
  • new Point(MousePosition.X, MousePosition.Y)
  • PointToClient(e.X, e.Y)
  • new Point(Cursor.Position.X, Cursor.Position.Y)
  • Control.MousePosition
  • Cursor.Position

and probably a few others.

Edit 2

This is what I mean by offset -- some of the solutions cause this offset to vary in certain magnitudes (some really far away etc) -- but all are offset like those from the actual Cursor.

enter image description here

Edit 3

My contextCell is a new ContextMenu()

like image 609
Jamie Poole Avatar asked Mar 12 '23 15:03

Jamie Poole


1 Answers

Option 1: The most simple solution for showing a context menu for rows is assigning the context menu to RowTemplate.ContextMenuStrip property of DataGridView:

dataGridView1.RowTemplate.ContextMenuStrip = contextMenuStrip1;

Option 2: Also if you want to select the cell before showing the ContextMenuStrip, it's enough to handle CellContextMenuStripNeeded event:

private void dataGridView1_CellContextMenuStripNeeded(object sender,
    DataGridViewCellContextMenuStripNeededEventArgs e)
{
    if (e.RowIndex > -1 && e.ColumnIndex > -1)
    {
        dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        e.ContextMenuStrip = contextMenuStrip1;
    }
}

What was your mistake?

You are calculating the mouse position on the DataGridView in a wrong way. You are using PointToClient which means this.PointToClient, while you need to use the method of DataGridView, for example dataGridView1.PointToClient:

myContextMenu.Show(dataGridView1,dataGridView1.PointToClient(Cursor.Position));

Just for your information you can simply show ContextMenu using this code and there is no need to use ContextMenuStrip.

But I strongly recommend you to use ContextMenuStrip.

like image 84
Reza Aghaei Avatar answered Apr 17 '23 01:04

Reza Aghaei