Событие ContextMenuOpening не запускается в WPF?

У меня есть словарь ресурсов, внутри которого у меня есть контекстное меню:

<ResourceDictionary x:Class="MyApp.Components.MyContextMenu"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:MyApp"
                    xmlns:components="clr-namespace:MyApp.Components">
    <ContextMenu ContextMenuOpening="OnContextMenuOpening">

а ресурсный словарь XAML имеет следующий код:

using System;
using System.Windows;
using System.Windows.Controls;

namespace MyApp.Components
{
    public partial class MyContextMenu : ResourceDictionary
    {
        public MyContextMenu()
        {
            InitializeComponent();
        }  

        void OnContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            Console.WriteLine("here i am!");
        }
    }
}

Журнал не появляется. Интересно, почему событие не стреляет или не попадает в нужное место - проблема, потому что я обернул контекстное меню внутри этого ресурсного словаря?

Обновление: Интересно, что если я удалю функцию кода, я получаю сообщение об ошибке во время компиляции:

не содержит определения для 'ContextMenu_OnContextMenuOpening' и никакой метод расширения 'ContextMenu_OnContextMenuOpening', принимающий можно найти первый аргумент типа "MyApp.Components.MyContextMenu" (вам не хватает директивы using или ссылки на сборку?)

Обновление 2: Похоже, что как Console.WriteLine, так и Debug.WriteLine производят вывод, но только "случайно" и особенно когда я нажимаю на нижнюю часть элемента. Может быть, какое-то обнаружение столкновения не работает?

Ответ 1

Это ошибка в рамках: http://connect.microsoft.com/VisualStudio/feedback/details/353112/contextmenu-opening-event-doesnt-fire-properly

Событие открытия контекстного меню не запускается при первом щелчке правой кнопкой мыши. Он срабатывает только тогда, когда вы выполняете два последовательных щелчка правой кнопкой мыши, не перемещаясь мышь.

Ответ 2

Событие ContextMenuOpening должно обрабатываться на предком ContextMenu, а не на самом ContextMenu. Если вы попытаетесь обработать его в ContextMenu, событие запускается только при щелчке правой кнопкой мыши, когда ContextMenu уже открыт.

Ответ 3

Я считаю, что курразиман имеет правильный ответ, но мне потребовалось некоторое время, чтобы понять это. В моем случае у меня был элемент управления TreeView с контекстным меню. Использование myTreeView.ContextMenu.ContextMenuOpening не помогло, но с помощью myTreeView.ContextMenuOpening сделал.

Ответ 4

Я использую IsVisibleChanged:

private void ContextMenu_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    var isVisible = (bool)e.NewValue;
    if (isVisible)
    {
        //...
    }
}

Ответ 5

Это не ошибка, это работает... вот самая распространенная ошибка, которую большинство людей совершают с событием ContextMenuOpening... рассмотрим два разных сценария, чтобы выяснить действительную причину этой проблемы,

СЦЕНАРИЙ 1 (это не будет работать):

<ListBox Name="lb_sizes" Height="120">
<ListBox.ContextMenu>
<ContextMenu ContextMenuOpening="My_ContextMenuOpening">
<MenuItem Header="Delete"/>
<MenuItem Header="Delete All"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>

СЦЕНАРИЙ 2 (это будет работать):

<ListBox Name="lb_sizes" Height="120" ContextMenuOpening="My_ContextMenuOpening">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"/>
<MenuItem Header="Delete All"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>

Единственное отличие заключается в назначении события ContextMenuOpening для соответствующего элемента... в сценарии 1 он назначается (присоединяется) к элементу <ContextMenu>, а в сценарии 2 он присваивается элементу <ListBox>, который является надлежащим способом сделать это и должен работать.