C# – Prevent context menu from appearing when clicking on blank part of datagrid

cdatagridview

When right clicking on the empty part of a DataGridView in C# (clicking on a part of the grid that contains no rows) the context menu still appears with it's row based options. How can I only have the context menu appear when the click falls over a row?

This is as far as I have gotten:

    private void f_context_select_row(object sender, MouseEventArgs e)
    {

            if (e.Button == MouseButtons.Right)
            {

                var hti = jobs_datagrid.HitTest(e.X, e.Y);
                if (hti.RowIndex >= 0)
                {
                    jobs_datagrid.ClearSelection();
                    jobs_datagrid.Rows[hti.RowIndex].Selected = true;
                }
                else
                {
                    //what can I do here to collapse the context menu?
                }
            }

    }

I am programatically building the Datagrid and context menu like this:

                    //on right click select row
                    jobs_datagrid.MouseDown += new MouseEventHandler(f_context_select_row);

                    //generate context menu
                    ContextMenuStrip m = new ContextMenuStrip();

                    ToolStripMenuItem context_datagrid_run = new ToolStripMenuItem("Run All Selected Campaigns");
                    ToolStripMenuItem context_datagrid_edit = new ToolStripMenuItem("Edit This Campaign");
                    ToolStripMenuItem context_datagrid_delete = new ToolStripMenuItem("Delete This Campaign");
                    context_datagrid_delete.Click += f_context_datagrid_delete;
                    context_datagrid_run.Click += f_run_selected_campaigns;
                    context_datagrid_edit.Click += f_context_datagrid_edit;

                    m.Items.Add(context_datagrid_delete);
                    m.Items.Add(context_datagrid_run);
                    m.Items.Add(context_datagrid_edit);
                    jobs_datagrid.ContextMenuStrip = m;

                    splitContainer3.Panel2.Controls.Add(jobs_datagrid);

Best Answer

what about the ContextMenuStrip.Opening event?

private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            var cms = sender as ContextMenuStrip;
            var mousepos = Control.MousePosition;
            if (cms != null)
            {
                var rel_mousePos = cms.PointToClient(mousepos);
                if (cms.ClientRectangle.Contains(rel_mousePos))
                {
                    //the mouse pos is on the menu ... 
                    //looks like the mouse was used to open it
                    var dgv_rel_mousePos = dataGridView1.PointToClient(mousepos);
                    var hti = dataGridView1.HitTest(dgv_rel_mousePos.X, dgv_rel_mousePos.Y);
                    if (hti.RowIndex == -1)
                    { 
                        // no row ...
                        e.Cancel = true;
                    }
                }
                else
                {
                    //looks like the menu was opened without the mouse ...
                    //we could cancel the menu, or perhaps use the currently selected cell as reference...
                    e.Cancel = true;
                }
            }
        }
Related Topic