C# 确定在哪个控件上使用了ContextMenuStrip
我有一个ContextMenuStrip,分配给几个不同的列表框。我试图找出ContextMenuStrip何时被单击,它在什么列表框上使用。我尝试了下面的代码作为开始,但它不工作。发件人具有正确的值,但当我尝试将其分配给menuSubmitted时,该值为nullC# 确定在哪个控件上使用了ContextMenuStrip,c#,.net,winforms,contextmenustrip,C#,.net,Winforms,Contextmenustrip,我有一个ContextMenuStrip,分配给几个不同的列表框。我试图找出ContextMenuStrip何时被单击,它在什么列表框上使用。我尝试了下面的代码作为开始,但它不工作。发件人具有正确的值,但当我尝试将其分配给menuSubmitted时,该值为null private void MenuViewDetails_Click(object sender, EventArgs e) { ContextMenu menuSubmitted = sender as ContextMe
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ContextMenu menuSubmitted = sender as ContextMenu;
if (menuSubmitted != null)
{
Control sourceControl = menuSubmitted.SourceControl;
}
}
任何帮助都会很好。谢谢
通过下面的帮助,我找到了答案:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
if (menuItem != null)
{
ContextMenuStrip calendarMenu = menuItem.Owner as ContextMenuStrip;
if (calendarMenu != null)
{
Control controlSelected = calendarMenu.SourceControl;
}
}
}
对于上下文菜单:
问题是sender参数指向上下文菜单上已单击的项目,而不是上下文菜单本身
不过,这是一个简单的解决方案,因为每个MenuItem都会公开一个菜单项,告诉您哪个ContextMenu包含该菜单项
将代码更改为以下内容:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a MenuItem
MenuItem menuItem = sender as MenuItem;
if (menuItem != null)
{
// Retrieve the ContextMenu that contains this MenuItem
ContextMenu menu = menuItem.GetContextMenu();
// Get the control that is displaying this context menu
Control sourceControl = menu.SourceControl;
}
}
对于ContextMenuStrip:
如果您使用ContextMenuStrip而不是ContextMenu,它会稍微改变一些事情。这两个控件彼此不相关,不能将一个控件的实例强制转换为另一个控件的实例
与以前一样,被单击的项目仍然会在sender参数中返回,因此您必须确定拥有此单个菜单项的ContextMenuStrip。你可以用这个。最后,您将使用确定哪个控件显示上下文菜单
按如下方式修改代码:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a ToolStripItem
ToolStripItem menuItem = sender as ToolStripItem;
if (menuItem != null)
{
// Retrieve the ContextMenuStrip that owns this ToolStripItem
ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;
if (owner != null)
{
// Get the control that is displaying this context menu
Control sourceControl = owner.SourceControl;
}
}
}
较旧的帖子,但万一像我这样的人遇到: 对于一个ContextMenuStrip来说,上面的内容对我来说不起作用,但它让我找到了真正起作用的东西
void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
Control sourceControl = menu.SourceControl;
MessageBox.Show(sourceControl.Name);
}
这给了我预期控件的名称。您可以使用if语句进行验证等,我只是想说明问题。我很难让这些代码正常工作。这是我能找到的最简单的解决方案: 对于ContextMenuStrip:
最简单的解决办法是:
Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;
将发送者强制转换为ToolStripItem以到达所有者,该所有者将是不具有SourceControl属性的ToolStrip 将所有者强制转换为ContextMenuStrip以访问SourceControl
Control sc = ((ContextMenuStrip)((ToolStripItem)sender).Owner).SourceControl;
在本例中,使用C1网格中的ActiveForm.ActiveControl如何:
C1.Win.FlexGrid.C1FlexGrid fg = frmMain.ActiveForm.ActiveControl as C1.Win.FlexGrid.C1FlexGrid;
@蓝脚:那么你又出了什么问题。我刚刚用三个不同的列表框测试了这段代码,一切都按预期进行了。发布更多的复制代码。@bluefeet:我已经在我的答案中更新了代码。ContextMenu和ContextMenuStrip之间有很大的区别。啊,我看你已经明白了。好吧,最好是自己学习!我使用打开事件来记录将菜单打开到局部变量的SourceControl,然后在处理项单击时引用它。@QuickDanger是的,不幸的是,在触发ContextMenuStrip的ToolStripItem子项的单击事件时,SourceControl为空。似乎ContextMenuStrip的Closed事件在单击事件之前触发,这可能是导致问题的原因;我假设该属性在菜单“closes”后被清除。@CodyGray实际上,如果树更深,则必须循环OwnerItem属性链,直到找到在其Owner属性中具有ContextMenuStrip的ToolStripItem。但正如我刚才评论的,它不起作用;关联菜单上的SourceControl将为空。但是你说你不能复制它。。。也许问题只发生在菜单深度超过一个级别时?我的是两个子层深。谢谢你的解决方案,我一直在寻找。我也有同样的问题。但我建议不要嵌套所有这些if语句,并使用if-menuItem==null返回;如果您和我一样,不希望处理它的代码嵌套在额外的不必要的两个级别。在我看来,您提供的解决方案可以更简洁地编码:Control controlSelected=发件人作为ToolStripMenuItem?.Owner作为ContextMenuStrip?.SourceControl;这仅适用于上下文菜单中的直接项。问题是单击子菜单项时,ItemClicked不会触发;他们需要自己的点击事件,该事件将项目本身作为发件人,而不是菜单。我认为此代码更简单,谢谢
C1.Win.FlexGrid.C1FlexGrid fg = frmMain.ActiveForm.ActiveControl as C1.Win.FlexGrid.C1FlexGrid;