2011-05-24 2 views
24

Je suis relativement nouveau à WPF et MVVM et la chose la plus difficile que j'ai trouvée est comment commuter simplement un usercontrol ou une vue dans une application.Quel est le meilleur moyen de changer de vue/usercontrols dans MVVM-light et WPF?

Dans winforms, pour avoir un contrôle supprimer lui-même vous dirais simplement this.Parent.Controls.Remove (this);

Dans WPF, il n'existe aucun contrôle parent générique, vous devez le convertir en type spécifique (par exemple Grid), puis le supprimer.

Cela semble également rompre l'architecture MVVM. J'ai également essayé des modèles de données et des présentateurs de contenu, qui fonctionnent bien, sauf que je ne peux pas changer le datacontext du code, puisque le datacontext est toujours le viewmodellocator.

Les pages sont-elles un moyen acceptable de le faire dans WPF maintenant? Que se passerait-il si j'avais une grille avec un contrôle personnalisé et que je voulais l'activer en fonction d'une variable dans viewModel? Il semble que les tâches les plus simples ne peuvent pas être accomplies facilement dans WPF.

Répondre

33

Vous le feriez dans votre ViewModel parent.

Par exemple, si votre page (appelez-le PageViewModel) avait deux points de vue (ViewModelA et ViewModelB), vous auriez une propriété sur PageViewModel appelé CurrentView, et cela déterminerait qui View est visible. Lorsque PageViewModel.CurrentView est défini sur une instance de ViewModelA, le DataTemplate de ViewA est utilisé pour dessiner le contenu. Lorsqu'il est défini sur une instance de ViewModelB, le DataTemplate de ViewB est affiché.

<DataTemplate DataType="{x:Type local:PageViewModel}"> 
    <ContentControl Content="{Binding CurrentView}" /> 
</DataTemplate> 

<DataTemplate DataType="{x:Type local:ViewModelA}"> 
    <TextBlock Text="I'm ViewModelA" /> 
</DataTemplate> 

<DataTemplate DataType="{x:Type local:ViewModelB}"> 
    <TextBlock Text="I'm ViewModelB" /> 
</DataTemplate> 

Il serait idéal pour appeler la vue commutateur commande de la vue parent (dans ce cas, le DataTemplate pour le PageViewModel), si vous vouliez changer de vue de l'intérieur ViewModelA/B, vous pouvez brancher l'événement manuellement lorsque les objets sont créés (CurrentView.ChangeViewCommand = this.ChangeViewCommand) ou regardez dans un système de messagerie. MVVM lumière a une classe simple Messenger que j'ai trouvé était assez facile à utiliser, ou Prism a un plus avancé EventAggregator

Si vous voulez changer de vue pour le même ViewModel, je recommanderais une propriété de mode qui obtient utilisé pour déterminer quels vue à utiliser. Par exemple:

<DataTemplate x:Key="ViewA" DataType="{x:Type local:MyViewModel}"> 
    <TextBlock Text="I'm ViewModelA" /> 
</DataTemplate> 

<DataTemplate x:Key="ViewB" DataType="{x:Type local:MyViewModel}"> 
    <TextBlock Text="I'm ViewModelB" /> 
</DataTemplate> 

<DataTemplate DataType="{x:Type local:MyViewModel}"> 
    <ContentControl Content="{Binding }"> 
     <ContentControl.Style> 
      <Style TargetType="{x:Type ContentControl}"> 
       <Setter Property="ContentTemplate" Value="{StaticResource ViewA}" /> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding Mode}" Value="2"> 
         <Setter Property="ContentTemplate" Value="{StaticResource ViewB}" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </ContentControl.Style> 
    </ContentControl> 
</DataTemplate> 

EDIT

Je vois en fait ce genre de question venir beaucoup, quelque chose de si posté à ce sujet here si quelqu'un est intéressé

+0

C'est à peu près ce que je recherchais pour. Si je comprends bien, vous pouvez utiliser DataTriggers pour lier à une valeur et ensuite basculer le contenu à la volée. Est-ce que cela fonctionne pour d'autres contrôles tels que ContentPresenter? – JReed

+0

@JReed Bien sûr, je ne vois pas pourquoi pas. Dans le second exemple, je change la propriété 'ContentTemplate' d'un' ContentControl', mais vous pouvez changer presque n'importe quelle propriété sur n'importe quel contrôle basé sur un Trigger – Rachel

+0

Que se passe-t-il si viewModel a besoin de données avant l'initialisation? un constructeur sans paramètre? –

Questions connexes