查找导致显示ContextMenuStrip菜单的控件

时间:2014-02-18 10:14:24

标签: winforms event-handling contextmenustrip

我读了几篇关于SO的文章:

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

以及其他一些建议使用SourceControl属性的人......但是在这种情况下都不起作用:

我有一个ContextMenuStrip,它有一个子ToolStripMenuItem - 这个代码来自windows窗体设计器生成的部分:

        // _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";

因此,设计时固定上下文菜单条和列表中的第一个菜单项。在运行时,TSMI在基于枚举的循环中添加了子TSMI:

        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);
        }

后来我的表单上有20个复选框,我将它们的.ContextMenuStrip设置为同样的东西:

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

很好,所以现在我拥有了所有的复选框,当我右键单击它们时它们都会显示上下文菜单,但当我选择一个子菜单项时,我只是找不到触发上下文菜单的控件...

    //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 :(
    }

我可以通过从事件处理程序发送者路由,或者甚至仅通过将ContextMenuStrip本身作为表单实例变量引用来可靠地获取contextmenustrip,但SourceControl始终为null

任何想法接下来要尝试什么?

1 个答案:

答案 0 :(得分:1)

我看到了问题,像小虫一样大声嘎嘎叫。有一个解决方法,您可以订阅ContextMenuStrip的Opening事件。此时,在开始导航到子项之前,SourceControl属性仍然有效。因此,将其存储在类的字段中,以便您可以在Click事件处理程序中使用它。大致是:

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
    //...
}
相关问题