27 votes

Comment puis-je dire à mon DataTemplate de se lier à une propriété dans le PARENT ViewModel?

J'ai suivantes MainView.xaml fichier qui fonctionne bien comme MVVM menu switcher. J'ai ces paires:

  • Page1View / Page1ViewModel
  • Page2View / Page2ViewModel

dans mon MainViewModel - je remplir une ObservableCollection avec les deux Viewmodel, ensuite, lorsque l'utilisateur clique sur le Prochain bouton, il appelle NextPageCommand dans MainViewModel qui bascule hors CurrentPageViewModel avec un nouveau ViewModel qui est alors affiché avec une Vue appropriée, fonctionne très bien.

J'ai aussi un Menu rempli avec tous les titres de la Viewmodel dans la collection Observable, qui fonctionne aussi bien.

Cependant, chaque MenuItem a une Commande="{Binding SwitchPageCommand}" qui DEVRAIT appeler SwitchPageCommand sur le MainViewModel et pas sur, par exemple, Page1ViewModel ou Page2ViewModel.

Alors, comment puis-je indiquer dans le modèle à ne pas se lier à l'actuel ViewModel mais le ViewModel qui contient que ViewModel, par exemple, quelque chose comme ceci:

PSEUDO-CODE:

<DataTemplate x:Key="CodeGenerationMenuTemplate">
    <MenuItem 
    	Command="{Binding <parentViewModel>.SwitchPageCommand}" 
    	Header="{Binding Title}" 
    	CommandParameter="{Binding Title}"/>
</DataTemplate>

Voici MainViewModel:

<Window x:Class="TestMenu234.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:TestMenu234.Commands"
    xmlns:vm="clr-namespace:TestMenu234.ViewModels"
    xmlns:v="clr-namespace:TestMenu234.Views"
    Title="Main Window" Height="400" Width="800">

    <Window.Resources>
        <DataTemplate x:Key="CodeGenerationMenuTemplate">
            <MenuItem Header="{Binding Title}" Command="{Binding SwitchPageCommand}" CommandParameter="{Binding Title}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:Page1ViewModel}">
            <v:Page1View/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:Page2ViewModel}">
            <v:Page2View/>
        </DataTemplate>
    </Window.Resources>

    <DockPanel>

        <Menu DockPanel.Dock="Top">
            <MenuItem Header="Code _Generation" ItemsSource="{Binding AllPageViewModels}"
                      ItemTemplate="{StaticResource CodeGenerationMenuTemplate}"/>
        </Menu>

        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Margin="5" Content="Next Page" Command="{Binding NextPageCommand}"/>
        </StackPanel>

        <ContentControl
            Content="{Binding CurrentPageViewModel}"/>

    </DockPanel>
</Window>

43voto

Edward Tanguay Points 43219

La réponse est la suivante:

 <DataTemplate x:Key="CodeGenerationMenuTemplate">
    <MenuItem 
        Header="{Binding Title}" 
        Command="{Binding DataContext.SwitchPageCommand,
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}" 
        CommandParameter="{Binding Title}"/>
</DataTemplate>
 

Je viens de voir que Nir m'avait donné la syntaxe pour résoudre le problème ci-dessus sur cette question: Quelle est la meilleure façon dans MVVM de construire un menu qui affiche différentes pages? .

1voto

Thomas Levesque Points 141081

Il n'existe aucun moyen générique d'accéder au ViewModel parent, cela dépend de votre implémentation ... Vous devez probablement ajouter une propriété à votre PageViewModels qui fait référence au MainView. Vous pouvez initialiser cette propriété dans le constructeur. En supposant que Page1ViewModel et Page2ViewModel héritent d'une classe de base PageViewModel:

 ...

public PageViewModel(MainViewModel main)
{
    this._main = main;
}

public MainViewModel Main
{
    get { return _main; }
}

...
 

EDIT: j'ai oublié la dernière partie ...

Dans votre DataTemplate, reportez-vous à la commande comme celle-ci:

 <DataTemplate x:Key="CodeGenerationMenuTemplate">
    <MenuItem 
        Command="{Binding Main.SwitchPageCommand}" 
        Header="{Binding Title}" 
        CommandParameter="{Binding Title}"/>
</DataTemplate>
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X