2016-08-28 3 views
1

Я пытаюсь предоставить элементы контекстного меню с различным внешним видом и функциональностью, но я не могу найти способ привязать команды к этим элементам. Модель просмотра каждого элемента меню выводится из одного класса AbstractEntryViewModel. Вот укороченный пример структуры моего текущего проекта. Использование ContextMenu.Resources - это единственный способ привязать шаблон к определенному типу.Привязать команду `DataTemplate` в` ContextMenu` при использовании нескольких шаблонов?

<ContextMenu ItemsSource="{Binding Entries}"> 
    <ContextMenu.Resources> 

     <DataTemplate DataType="{x:Type local:NopEntryViewModel}"> 
      <!-- Content --> 
     </DataTemplate> 

     <HierarchicalDataTemplate 
      DataType="{x:Type local:GroupEntryViewModel}" 
      ItemsSource="{Binding Entries}"> 
      <!-- Content --> 
     </HierarchicalDataTemplate> 

     <!-- More templates --> 

    </ContextMenu.Resources> 
</ContextMenu> 
internal abstract AbstractEntryViewModel : INotifyPropertyChanged { 
    public abstract void Invoke(); 
    // ... 
} 

internal NopEntryViewModel : AbstractEntryViewModel { 
    public override void Invoke() {} 
} 

internal GroupEntryViewModel : AbstractEntryViewModel { 
    public override void Invoke() { /* ... */ } 
    // ... 
} 

// More view models 

Обычно я могу связать команду к MenuItem как так

<MenuItem Command="{Binding StaticResourceOrViewModelProperty}" /> 

Как я могу сделать то же самое с шаблонами данных? Есть ли невидимый контейнер, оболочка для содержимого шаблона данных, который я могу использовать для привязки команды?

ответ

2

Для простоты, предположим, 2, полученные ViewModels, VM1 и VM2, с соответственно в CommandCommand1 и Command2.

Два шага:

1) Определить в базе ViewModel это свойство:

public Type Type 
{ 
    get { return GetType(); } 
} 

Мы не можем использовать GetType() напрямую, нам нужно свойство оберточной поскольку WPF Bindings работают только со свойствами.

2) Используйте это свойство, чтобы установить DataTrigger на Style для ContextMenuMenuItem:

<ContextMenu.Resources> 
    <Style TargetType="{x:Type MenuItem}"> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM1}"> 
     <Setter Property="Command" Value="{Binding Command1}"/> 
     </DataTrigger> 
     <DataTrigger Binding="{Binding Type}" Value="{x:Type local:VM2}"> 
     <Setter Property="Command" Value="{Binding Command2}"/> 
     </DataTrigger> 
     <!-- add other DataTriggers, one for every ViewModel --> 
    </Style.Triggers> 
    </Style> 
</ContextMenu.Resources> 

DataTemplates устанавливаются, как вы делаете с:

<DataTemplate DataType="{x:Type local:VM1}"> 
    <!-- Content --> 
</DataTemplate> 
<DataTemplate DataType="{x:Type local:VM2}"> 
    <!-- Content --> 
</DataTemplate> 
+2

WOW, работает как шарм и не прерывает MVVM :) При использовании дополнительного setter '', фактический экземпляр модели представления передается в команду. Большое спасибо :) – Cubinator73

Смежные вопросы