确定使用 ContextMenuStrip 的控件

我有一个 ContextMenuStrip,它被分配给几个不同的列表框。我试图找出什么时候的 ContextMenuStrip被点击了什么 ListBox它被用在。我尝试下面的代码作为一个开始,但它不工作。sender具有正确的值,但是当我尝试将它赋给 menuSubmitted时,它为空。

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;
}
}
}
54942 次浏览

For a ContextMenu:

The problem is that the sender parameter points to the item on the context menu that was clicked, not the context menu itself.

It's a simple fix, though, because each MenuItem exposes a GetContextMenu method that will tell you which ContextMenu contains that menu item.

Change your code to the following:

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

For a ContextMenuStrip:

It does change things slightly if you use a ContextMenuStrip instead of a ContextMenu. The two controls are not related to one another, and an instance of one cannot be casted to an instance of the other.

As before, the item that was clicked is still returned in the sender parameter, so you will have to determine the ContextMenuStrip that owns this individual menu item. You do that with the Owner property. Finally, you'll use the SourceControl property to determine which control is displaying the context menu.

Modify your code like so:

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

Older post, but in case someone like myself comes across it:

For a ContextMenuStrip, the above didn't work for me, but it led to finding what did.

void DeleteMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
Control sourceControl = menu.SourceControl;
MessageBox.Show(sourceControl.Name);
}

This gave me the expected control's name. You can put in validation etc with if statements, I'm just posting to get to the point.

I had great difficulty getting any of this code to work. This is the simplest solution I could find:

For A ContextMenuStrip:

    Control _sourceControl = null;
private void contextMenuStrip_Opened(object sender, EventArgs e)
{
_sourceControl = contextMenuStrip.SourceControl;
}


private void contextMenuItem_Click(object sender, EventArgs e)
{
var menuItem = (ToolStripMenuItem)sender;


_sourceControl.Text = menuItem.Text;
MessageBox.Show(menuItem.Name);
MessageBox.Show(sourceControl.Name);
}

The easiest solution would be:

Control parentControl = ((sender as MenuItem).GetContextMenu()).SourceControl;
 

Cast sender to ToolStripItem to reach Owner which will be a ToolStrip that doesn't have a SourceControl property.

Cast Owner to ContextMenuStrip to reach SourceControl.

Control sc = ((ContextMenuStrip)((ToolStripItem)sender).Owner).SourceControl;

How about just using ActiveForm.ActiveControl, in this example from a C1 grid:

C1.Win.FlexGrid.C1FlexGrid fg = frmMain.ActiveForm.ActiveControl as C1.Win.FlexGrid.C1FlexGrid;