C# = MenuItem.Click handler - Get the object the context menu belongs to?

16,072

Solution 1

Use the ContextMenu.SourceControl property, it gives you a reference to the Button instance back.

Solution 2

If you are using ContextMenuStrip and ToolStripItem, rather than ContextMenu and MenuItem, you'll need:

private void myToolStripMenuItem_Click(object sender, EventArgs e)
{
   Button parent = (Button)((ContextMenuStrip)((ToolStripItem)sender).Owner).SourceControl;
   ...

With a regular ContextMenu and MenuItem (from trycatch's comment on Hans Passant's post):

Button parent = (Button)((ContextMenu)((MenuItem)sender).Parent).SourceControl; 

Solution 3

In the above code excerpt, when you call the show method of buttonContextMenu, you pass the button object to buttonContextMenu when you right-click on the button.

To access the button in the OnFooClicked method simply cast the 'sender' back to a button.

public void OnFooClicked(object sender, EventArgs e)
{
     ((MenuItem)sender).Parent //This is the button
}

*I don't know if MenuItem is the correct cast but it should be along those lines.

Share:
16,072
trycatch
Author by

trycatch

Updated on June 04, 2022

Comments

  • trycatch
    trycatch almost 2 years

    This might be incredibly simple and I'm not seeing it because it's the end of a long day, and if it is I apologize in advance.

    I've got a set of Buttons that when right-clicked pop up a ContextMenu. The menu has two MenuItems, both of which have a Click handler function assigned. I'm triggering the ContextMenu to pop up on the right click of a button like so:

    Overly simplified example:

    
    public void InitiailizeButtonContextMenu()
    {
        buttonContextMenu = new ContextMenu();
        MenuItem foo = new MenuItem("foo");
        foo.Click += OnFooClicked;
    
        MenuItemCollection collection = new MenuItemCollection(buttonContextMenu);
        collection.Add(foo);
    }
    
    public void OnButtonMouseClick(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
            // left click stuff handling
        if (e.Button == MouseButtons.Right)
            buttonContextMenu.Show((Button)sender, new Point(e.X, e.Y));
    }
    
    
    public void OnFooClicked(object sender, EventArgs e)
    {
        // Need to get the Button the ContextMenu .Show'd on in
        // OnButtonMouseClick...  thoughts?
    }
    
    
    ContextMenu buttonContextMenu; 
    

    I need to be able to get the Button that triggered the ContextMenu to pop up IN the Click handler for the MenuItem, or get it to it somehow. MenuItem.Click takes EventArgs, so nothing useful there. I can cast object sender back to MenuItem but I can't find anything that tells me what made it pop up. Is this possible?

  • trycatch
    trycatch about 13 years
    I'm away from my code now, but I'm 90% sure I tried this, and it threw an exception because sender was a MenuItem because it's a MenuItem.Click handler.
  • Kyle Uithoven
    Kyle Uithoven about 13 years
    Oops, sorry. Yea, that won't work. You should be able to reference the Parent, and that will be your button. Sorry.
  • trycatch
    trycatch about 13 years
    Worth noting (in case someone with this same problem comes across this question) that you have to do: Button parent = (Button)((ContextMenu)((MenuItem)sender).Parent).SourceContr‌​ol; to get all the way back to the button from the MenuItem, but this works! Thanks.
  • SepehrM
    SepehrM over 10 years
    In case someone like me needs this for wpf, should use PlacementTarget property: Button btn = (Button)((ContextMenu)((MenuItem)sender).Parent).PlacementTa‌​rget;