2013-03-22 4 views
9

Desidero associare un menu di scelta rapida a un elenco di comandi.ContextMenu in MVVM

<Grid.ContextMenu> 
    <ContextMenu ItemsSource="{Binding ItemContextCommands, Converter={StaticResource commandToStringConverter}}"> 
      <ContextMenu.ItemTemplate > 
        <DataTemplate DataType="MenuItem"> 
          <MenuItem Command="{Binding}"></MenuItem> 
         </DataTemplate> 
       </ContextMenu.ItemTemplate> 
     </ContextMenu> 
</Grid.ContextMenu> 

Il commandToStringConverter converte semplicemente un elenco di comandi per una lista di stringhe chiamando il ToString() su ogni comando nella lista.

Come posso ottenere che venga chiamato il Command in ogni MenuItem?

+0

È * * probabbly dovrebbe pensare di utilizzare un altro ancora convertitore che converte ogni singolo {} Binding alla chiamata comando vero e proprio. – Tigran

+0

il convertitore restituisce un elenco di Func? –

risposta

16

Vorrei utilizzare un piccolo "modello di visualizzazione" per contenere le informazioni per tale comando.

class ContextAction : INotifyPropertyChanged 
{ 
    public string Name; 
    public ICommand Action; 
    public Brush Icon; 
} 

fare una raccolta all'interno del vostro modello di vista, che dovrebbe ottenere le azioni di contesto come

ObservableCollection<ContextAction> Actions {get;set;} 

e semplicemente legare questa collezione al vostro ContextMenu.

<Grid.ContextMenu> 
    <ContextMenu ItemsSource="{Binding Actions}/> 

L'ItemTemplate per le voci ContextMenu possono ora accedere al nome, il comando e qualsiasi altra cosa che potrebbe essere necessario. Potrebbe essere utile cambiare anche il CommandParameter in modo che chiamerà il comando con l'elemento proprietario delle azioni, non con l'azione stessa.

+1

+1 eri più veloce :) – blindmeis

+0

Qualcuno ha un'idea su come gestire un ContextMenu con separatori e sottomenu? Questa soluzione sembra essere utile solo per un insieme omogeneo di oggetti. –

+0

I sottomenu sono altrettanto semplici. Basta dare al ContextMenu un ItemContainerStyle con un setter per ItemsSource e associare a una nuova proprietà di tipo ObservableCollection all'interno di una ContextAction. Per i Separatori, consultare la soluzione [this] (http://stackoverflow.com/questions/4823760/how-to-add-horizontal-separator-in-a-dinamically-creattext-contest). – dowhilefor

11

io uso qualcosa di simile:

public class ContextMenuVM 
{ 
    public string Displayname {get;set;} 
    public ICommand MyContextMenuCommand {get;set;} 
} 

nel vostro DataContext contextmenu:

public ObservableCollection<ContextMenuVM> MyCommandList {get;set;} 

in XAML

<ContextMenu ItemsSource="{Binding MyCommandList}"> 
     <ContextMenu.ItemTemplate > 
       <DataTemplate DataType="MenuItem"> 
         <MenuItem Header="{Binding Displayname}" Command="{Binding MyContextMenuCommand}"></MenuItem> 
        </DataTemplate> 
      </ContextMenu.ItemTemplate> 
    </ContextMenu> 

suoi scritti, senza ide, così forse alcuni errori di sintassi in ci

+3

Questa soluzione ha il controllo annidato di MenuItem –

2

una versione migliorata di XAML soluzione @blindmils di seguito:

<ContextMenu ItemsSource="{Binding MyCommandList}"> 
    <ContextMenu.ItemContainerStyle> 
     <Style TargetType="MenuItem"> 
      <Setter Property="Header" Value="{Binding Displayname}" /> 
      <Setter Property="Command" Value="{Binding MyContextMenuCommand }" /> 
     </Style> 
    </ContextMenu.ItemContainerStyle> 
</ContextMenu>