C# – Why does the WinForms context menu not appear where the mouse is

ccontextmenuwinforms

In my application I have a DataGridView that is meant for configuring some options. The idea is that you can enter whatever text you want in the first column, but if you right click it will give you explicitly supported values. I need this to be a textbox rather than a dropdown list because I need to support editing invalid (or old) configurations.

What I want is the user to right click in the field name column and have a context menu that is valid based on what type of configuration this is. Therefore, I coded the following event

    private void grvFieldData_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        // If this is a right click on the Field name column, create a context menu 
        //   with recognized options for that field
        if (e.Button == MouseButtons.Right && grvFieldData.Columns[e.ColumnIndex].Name == "clmFieldName")
        {
            ContextMenu menu = new ContextMenu();

            if (_supportedDataGrids.ContainsKey((cmbDataGrid.SelectedItem as DataGridFieldList).GridName))
            {
                // Loop through all the fields and add them to the context menu
                List<string> fields = _supportedDataGrids[((cmbDataGrid.SelectedItem as DataGridFieldList).GridName)];
                fields.Sort();

                foreach (string field in fields)
                    menu.MenuItems.Add(new MenuItem(field));

                // Make sure there is at least one field before displaying the context menu
                if (menu.MenuItems.Count > 0)
                    menu.Show(this, e.Location, LeftRightAlignment.Right);
            }
        }
    }

This works "correctly", but the context menu is appearing at the top of the form, not where the mouse pointer is. If I change the Show() call to use the DataGridView instead of the form, I have the same issue but instead it appears at the top-left hand corner of the grid, not where the mouse is.

Oddly enough, if I change this event to a MouseClick event (instead of a CellMouseclick event) everything works and the context menu appears exactly where the mouse pointer is. The problem with this option is that the user might not be right clicking on the cell that is currently selected, which means that when they click on a menu item, the selected cell will be changed and not the cell they right clicked on.

Does anyone have any hints why context menus created with the CellMouseClick are not showing at the correct spot?

Best Answer

 menu.Show(this, e.Location, LeftRightAlignment.Right);

The 2nd argument is the mouse location, relative to the cell's upper left corner. As programmed, you make that offset relative from this, the form, which will make the menu appear in the upper left corner of the form. Use the DGV as the 1st argument doesn't work either, now it is in the upper left corner of the grid.

A couple of ways to fix this, but this is the easy way:

 Point pos = this.PointToClient(Cursor.Position);
 menu.Show(this, pos, LeftRightAlignment.Right);

You can arbitrarily replace this with grvFieldData.