Определите, какой контроль ContextMenuStrip использовался

У меня есть ContextMenuStrip, который присваивается нескольким различным спискам. Я пытаюсь выяснить, когда нажимается ContextMenuStrip то, что ListBox оно было использовано. Я попробовал код ниже, но он не работает. Значение sender имеет правильное значение, но когда я пытаюсь назначить его menuSubmitted, оно равно null.

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

Ответ 1

Для a ContextMenu:

Проблема заключается в том, что параметр sender указывает на элемент в контекстном меню, который был нажат, а не на контекстное меню.

Это простое исправление, потому что каждый MenuItem предоставляет метод GetContextMenu, который расскажет вам, что 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;
    }
}

При a ContextMenuStrip:

Это немного изменит ситуацию, если вы используете ContextMenuStrip вместо ContextMenu. Два элемента управления не связаны друг с другом, и экземпляр одного не может быть передан экземпляру другого.

Как и раньше, элемент, который был нажат, по-прежнему возвращается в параметре sender, поэтому вам нужно будет определить ContextMenuStrip, которому принадлежит этот отдельный пункт меню. Вы делаете это с помощью свойства Owner. Наконец, вы будете использовать свойство SourceControl, чтобы определить, какой элемент управления отображает контекстное меню.

Измените свой код следующим образом:

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

Ответ 2

Старая почта, но в случае, если кто-то вроде меня наткнулся на нее:

Для ContextMenuStrip приведенное выше не работает для меня, но это привело к обнаружению того, что произошло.

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

Это дало мне ожидаемое контрольное имя. Вы можете ввести подтверждение и т.д. С операторами if, я просто отправляю сообщения, чтобы добраться до точки.

Ответ 3

Мне было очень трудно заставить работать этот код. Это самое простое решение, которое я смог найти:

Для 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);
    }