Find control that caused ContextMenuStrip menu to be shown

无人久伴 提交于 2019-12-13 02:11:57

问题


I've read a few articles on SO:

How to detrmine the control that cause ContextMenuStrip Getting the control of a context menu

and a couple others that suggested use of the SourceControl property.. but none work in this context:

I have a ContextMenuStrip that has a child ToolStripMenuItem - this code from the windows forms designer generated section:

        // _tileContextMenuStrip
        // 
        this._tileContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
        this.tileKindToolStripMenuItem,
        this.forceWidthScalingToolStripMenuItem,
        this.forceHeightScalingToolStripMenuItem});
        this._tileContextMenuStrip.Name = "_tileContextMenuStrip";
        this._tileContextMenuStrip.Size = new System.Drawing.Size(184, 70);
        // 
        // tileKindToolStripMenuItem
        // 
        this.tileKindToolStripMenuItem.Name = "tileKindToolStripMenuItem";
        this.tileKindToolStripMenuItem.Size = new System.Drawing.Size(183, 22);
        this.tileKindToolStripMenuItem.Text = "Tile Kind";

So the context menu strip and the menu item first in the list are fixed at design time. At runtime, the TSMI has child TSMIs added to it in a loop based on an enum:

        foreach(TileKind t in typeof(TileKind).GetEnumValues()) {

            ToolStripMenuItem tsmi = new ToolStripMenuItem(t.ToString("g"));
            tsmi.Tag = t;
            tsmi.Click += tsmi_Click; 

            tileKindToolStripMenuItem.DropDownItems.Add(tsmi);
        }

Later I have 20 checkboxes on my form and I set their .ContextMenuStrip to be the same thing:

foreach(Thing t in someDataSource){
  CheckBox c = new CheckBox();
  c.Text = t.SomeData;
  c.ContextMenuStrip = this._tileContextMenuStrip;
  myPanelBlah.Controls.Add(c);
}

Great, so now I have all my checkboxes and they all show the context menu when I right click them, but when I choose one the sub-menu items, I just can't find out the control that fired the context menu...

    //this the click handler for all the menu items dynamically added
    void tsmi_Click(object sender, EventArgs e)
    {
        ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
        (tsmi.OwnerItem                   //the parent node in the menu tree hierarchy
            .Owner as ContextMenuStrip)   //it's a ContextMenuStrip so the cast succeeds
            .SourceControl                //it's always null :(
    }

I can reliably get ahold of the contextmenustrip either by routing up from the event handler sender, or even just by referencing the ContextMenuStrip itself as a form instance variable, but SourceControl is always null

Any ideas what to try next?


回答1:


I see the problem, quacks loudly like a bug. There's a workaround, you can subscribe the ContextMenuStrip's Opening event. At that point, well before you start navigating into the sub-items, the SourceControl property is still valid. So store it in a field of the class so you'll have it available in the Click event handler. Roughly:

private Control _tileCmsSource;

private void _tileContextMenuStrip_Opening(object sender, CancelEventArgs e) {
    _tileCmsSource = _tileContextMenuStrip.SourceControl;
}

void tsmi_Click(object sender, EventArgs e)
{
    ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
    // Use _tileCmsSource here
    //...
}


来源:https://stackoverflow.com/questions/21850511/find-control-that-caused-contextmenustrip-menu-to-be-shown

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!