Могу ли я применить ContextMenu к ContextMenuViewModel, используя DataTemplate? - PullRequest
2 голосов
/ 22 февраля 2010

У меня есть ViewModel (AbstractContextMenu), который представляет мое контекстное меню (IContextMenu), и я привязываю к нему реальное ContextMenu с помощью DataTemplate:

<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
    <ContextMenu x:Name="contextMenu" 
          ItemsSource="{Binding Path=(local:IContextMenu.Items)}"
          IsEnabled="{Binding Path=(local:IContextMenu.IsEnabled)}"/>
</DataTemplate>

Тогда у меня есть фиктивный объект ConcreteContextMenu для тестирования, который просто наследуется от AbstractContextMenu. AbstractContextMenu просто реализует этот интерфейс:

public interface IContextMenu : IExtension
{
    IEnumerable<IMenuItem> Items { get; set; }
    bool IsEnabled { get; set; }
}

Я использую его как свойство другого объекта ViewModel:

    public IContextMenu ContextMenu
    {
        get
        {
            return m_ContextMenu;
        }
        protected set
        {
            if (m_ContextMenu != value)
            {
                m_ContextMenu = value;
                NotifyPropertyChanged(m_ContextMenuArgs);
            }
        }
    }
    private IContextMenu m_ContextMenu = new ConcreteContextMenu();
    static readonly PropertyChangedEventArgs m_ContextMenuArgs =
        NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu);

Затем я привязываю StackPanel к этой ViewModel и привязываю свойство ContextMenu на StackPanel к свойству ContextMenu ViewModel:

    <StackPanel Orientation="Horizontal" 
                ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
                ContextMenuOpening="stackPanel_ContextMenuOpening">
    <!-- stuff goes in here -->
    </StackPanel>

Когда я запускаю это, событие ContextMenuOpening на StackPanel вызывается, но ContextMenu никогда не отображается. Я не уверен, смогу ли я это сделать (примените ContextMenu к ContextMenu ViewModel, используя DataTemplate). Кто-нибудь знает?

Ответы [ 3 ]

1 голос
/ 25 февраля 2010

Какой тип AbstractSolutionItem.ContextMenu? Если оно соответствует свойству ContextMenu в вашем вопросе, возможно, проблема в том, что тип неправильный. Свойство ContextMenu для FrameworkElement ожидает фактическое значение ContextMenu, а не IContextMenu. Попробуйте проверить окно вывода при отладке приложения - вы можете получить сообщение об ошибке, в котором говорится, что это проблема.

Вместо использования DataTemplate для определения ContextMenu, просто поместите содержимое шаблона StackPanel.ContextMenu:

<StackPanel Orientation="Horizontal" 
    ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
    ContextMenuOpening="stackPanel_ContextMenuOpening">
    <StackPanel.ContextMenu DataContext="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}">
        <ContextMenu x:Name="contextMenu" 
            ItemsSource="{Binding Path=Items}"
            IsEnabled="{Binding Path=IsEnabled}"/>
    </StackPanel.ContextMenu>
    <!-- stuff goes in here -->
</StackPanel>

Это должно помочь вам пройти большую часть пути туда. Однако проблема все еще существует, поскольку ContextMenu не знает, как создать MenuItem из IMenuItem. Чтобы решить эту проблему, создайте ItemTemplate для ContextMenu, который связывает элементы IMenuItem с `MenuItem.

0 голосов
/ 01 сентября 2010

Свяжите свойство ContextMenu вашего представления (StackPanel в этом сценарии) со свойством ContextMenu вашей ViewModel и предоставьте IValueConverter для привязки, которая создаст объект ContextMenu и задаст IContextMenu его DataContext.

0 голосов
/ 27 февраля 2010

Не могли бы вы пролить свет на синтаксис, используемый в свойстве ItemsSource в DataTemplate? Использование скобок обычно означает прикрепленное свойство. И Items не является прикрепленным свойством, определяемым IContextMenu (поскольку интерфейс не может определить такое свойство).

DataTemplate связан с объектом типа AbstractContextMenu, который имеет свойство с именем Items. Итак, DataTemplate может просто ссылаться на него так:

<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
    <ContextMenu x:Name="contextMenu" 
          ItemsSource="{Binding Path=Items)}"
          IsEnabled="{Binding Path=IsEnabled}"/>
</DataTemplate>

Если класс AbstractSolutionItem является виртуальной машиной StackPanel, вы можете связать его следующим образом:

<StackPanel Orientation="Horizontal" 
            ContextMenu="{Binding Path=ContextMenu}"
            ContextMenuOpening="stackPanel_ContextMenuOpening">
<!-- stuff goes in here -->
</StackPanel>

Конечно, DataTemplate должен быть «доступен» из StackPanel.

...