我读了几篇关于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
任何想法接下来要尝试什么?
答案 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
//...
}