简体   繁体   中英

How do I change the properties of a ContextMenuItem from inside an event handler

I'm slowly getting the hang of C# and this question is probably a result of bad design but here goes.

I have dynamic menus being generated thusly:

public Form1()
{
    InitializeComponent();
    AddContextMenu();
}
public void AddContextMenu()
{
    ContextMenuStrip mnuContextMenu = new ContextMenuStrip();
    mnuContextMenu.ItemClicked+=
              new ToolStripItemClickedEventHandler(mnuContextMenu_ItemClicked);

    this.ContextMenuStrip = mnuContextMenu;

    ToolStripMenuItem mnuItemEnable = new ToolStripMenuItem("Enable");
    mnuContextMenu.Items.Add(mnuItemEnable);
}

and the event handler:

private void mnuContextMenu_ItemClicked (Object sender,
                                         ToolStripItemClickedEventArgs e)
{
     //do stuff here
}

How do I change mnuContextMenu.Text (or any other property) from inside the event handler? VS says :

mnuContextMenu does not exist in the current context

mnuContextMenu only existed in the scope of AddContextMenu .

You have a couple of options:

this.ContextMenuStrip.Text = "Hello World";

or:

((ContextMenuStrip) sender).Text = "Hello World";

The first works because you stored the local mnuContextMenu in the class propery ContextMenuStrip . The second way casts the sender paramater (object raising the event) to a ContextMenuStrip.

There's a reason that all event handler methods have the exact same signature in the .NET world. You've probably noticed that the sender and e arguments are always there, no matter which event you're handling. They provide all the information you need.

In this particular case, you're looking for the sender parameter, which is a reference to the specific control that raised the event.

Of course, it's typed as an Object , so you'll have to cast it to a more derived type in order to use it like you want to. That's straight-forward enough—since you know that an ItemClicked event is only going to be raised by a ContextMenuStrip object, just cast it directly:

private void mnuContextMenu_ItemClicked (Object sender, ToolStripItemClickedEventArgs e)
{
    ((ContextMenuStrip)sender).Text = "Your text";
}

Or, if you want to play it safe (and you probably do), follow the standard idiom:

private void mnuContextMenu_ItemClicked (Object sender, ToolStripItemClickedEventArgs e)
{
    // Try to cast the object to a ContextMenuStrip
    ContextMenuStrip cmnu = sender as ContextMenuStrip;

    // Verify that the cast was successful
    // (if it failed, the cmnu variable will be null and this test will fail,
    // preventing your code from being executed and your app from crashing)
    if (cmnu != null)
    {
        cmnu.Text = "Your text";
    }
}

There's absolutely no reason to litter your code with maintaining class-level references to these objects when there's a perfectly good, built-in way of obtaining references to exactly the ones that you want, when you want them.

Clearly it fails because you declare the context menu object inside the AddContextMenu method as local method variable instead of having it as private member of the containing class. the solution MegaHerz has suggested would probably work, or you keep a reference to your object as private member of the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM