2009-02-24 19 views
17

Sto utilizzando il modello M-V-VM in un'app WPF. Collego ViewModel a ContentControl e utilizzo di un modello dati definito nelle risorse della finestra per eseguire il rendering della vista (un controllo utente) per quel ViewModel.Collegamento a un comando in un datagrid

Nel ViewModel, ho una collezione di articoli. Collego questa raccolta alla griglia di dati fornita nel toolkit WPF. Anche nel modello di vista, ho un comando RemoveItem definito che accetta un argomento per l'ID dell'articolo da rimuovere.

Come collegarmi a tale comando nella griglia di dati? Il contesto dei dati della griglia è tale raccolta, quindi qualcosa come:

<Button Command="{Binding Path=RemoveCommand}" CommandParameter="{Binding Path=id}">X</Button> 

non funziona - non riesce a trovare il comando. Penso di aver bisogno di legare RelativeSource, ma come sarebbe? Il tipo di antenato sarebbe UserControl o ContentControl? Dov'è il mio ViewModel residente come DataContext?

O sono via da qui?

risposta

36

Sì, devi solo salire di livello. Proverò prima un binding con ElementName e ricorrerò a RelativeSource solo se necessario. Per esempio, io preferisco questo:

<DataGrid x:Name="_grid"> 
    ... 
     <Button Command="{Binding DataContext.RemoveItem, ElementName=_grid}"/> 
    ... 
</DataGrid> 

Detto questo, il compilatore XAML può ottenere le sue mutandine in un nodo quando si tratta di nomi di elementi e di scoping nei controlli, quindi potrebbe essere necessario ricorrere a un RelativeSource:

<DataGrid x:Name="_grid"> 
    ... 
    <Button Command="{Binding DataContext.RemoveItem, 
        RelativeSource={RelativeSource FindAncestor, 
            AncestorType={x:Type DataGrid}} 
        }"/> 
    ... 
</DataGrid> 

È necessario cercare solo fino a quando il contesto dati sarà il modello di visualizzazione. Potresti cercare un UserControl se lo desideri, non sono sicuro che sia davvero importante. Entrambi sono binding piuttosto fragili, motivo per cui preferisco l'approccio ElementName.

+0

Impressionante. Grazie, Kent! –

+1

Benvenuto. Un altro modo per farlo è quello di esporre una raccolta di modelli di visualizzazione figlio piuttosto che una raccolta di elementi di dati. Quindi, quei modelli di visualizzazione figlio possono avere una proprietà che espone il comando, salvandoti dall'introduzione di collegamenti fragili come questi. –

+0

Grazie, questo ha risolto il mio problema. –

1

Mi piace definire il viewmodel nel datacontext del controllo con il nome ViewModel. Il legame è più facile scrivere utilizzando ElementName

... 
<UserControl.DataContext> 
    <local:UserControlViewModel x:Name="ViewModel"/> 
</UserControl.DataContext> 
... 

... 
<DataGridTemplateColumn Width="30"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <Button Command="{Binding RemoveCommand, ElementName=ViewModel}" 
        CommandParameter="{Binding}">Remove</Button> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 
... 

nota che in questo caso è Comando Parametro intero oggetto dati della riga. A volte meglio di

CommandParameter="{Binding Id}" 

perché non è necessario trovare nuovamente i dati.

Problemi correlati