web-dev-qa-db-fra.com

Vues de navigation WPF MVVM

J'ai une application WPF avec plusieurs vues. Je souhaite passer de la vue 1 à la vue 2 et à partir de là, je peux passer à plusieurs vues. Donc, je veux un bouton sur la vue 1 qui charge View2 dans la même fenêtre.

J'ai essayé ces choses, mais je n'arrive pas à les faire fonctionner.

Depuis le premier lien, le problème est que je ne comprends pas le code ViewModelLocator. Ils appellent la fonction CreateMain(); mais où est-ce défini et comment puis-je basculer vers une autre vue depuis une vue.

41
user2499088

Tout d'abord, vous n'avez besoin d'aucun de ces toolkits/framework pour implémenter MVVM. Cela peut être aussi simple que cela ... supposons que nous ayons un MainViewModel, un PersonViewModel et un CompanyViewModel, chacun avec sa propre vue associée et chacun prolongeant un abstract classe de base BaseViewModel.

Dans BaseViewModel, nous pouvons ajouter des propriétés communes et/ou des instances ICommand et implémenter l'interface INotifyPropertyChanged. Comme ils étendent tous la classe BaseViewModel, nous pouvons avoir cette propriété dans la classe MainViewModel qui peut être définie sur n’importe lequel de nos modèles de vue:

public BaseViewModel ViewModel { get; set; }

Bien sûr, vous implémenteriez correctement l'interface INotifyPropertyChanged sur les propriétés de votre contrairement à cet exemple rapide. Maintenant en App.xaml, nous déclarons quelques DataTemplate s simples pour connecter les vues aux modèles de vue:

<DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
    <Views:MainView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:PersonViewModel}">
    <Views:PersonView />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModels:CompanyViewModel}">
    <Views:CompanyView />
</DataTemplate>

Maintenant, chaque fois que nous utilisons l’une de nos instances BaseViewModel dans notre application, ces DataTemplate indiqueront au framework d’afficher la vue associée. Nous pouvons les afficher comme ceci:

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

Donc, tout ce que nous avons à faire pour passer à une nouvelle vue est de définir la propriété ViewModel à partir de la classe MainViewModel:

ViewModel = new PersonViewModel();

Enfin, comment pouvons-nous changer les points de vue d'autres points de vue? Il existe plusieurs façons de le faire, mais le plus simple est d’ajouter un Binding directement de la vue enfant à un ICommand dans le MainViewModel. J'utilise une version personnalisée du RelayComand, mais vous pouvez utiliser n'importe quel type et je suppose que vous obtiendrez l'image suivante:

public ICommand DisplayPersonView
{
    get { return new ActionCommand(action => ViewModel = new PersonViewModel(), 
        canExecute => !IsViewModelOfType<Person>()); }
}

Dans la vue enfant XAML:

<Button Command="{Binding DataContext.DisplayPersonView, RelativeSource=
    {RelativeSource AncestorType={x:Type MainView}}, Mode=OneWay}" />

C'est ça! Prendre plaisir.

109
Sheridan

Quand j'ai commencé avec MVVM, j'ai également eu du mal à utiliser les différents frameworks MVVM et en particulier la partie navigation. Par conséquent, j'utilise ce petit tutoriel que j'ai trouvé, créé par Rachel Lim. C'est très gentil et bien expliqué.

Jetez un coup d'oeil sur le lien suivant:

J'espère que ça vous a aidé :)

7
mskydt86

Peut-être que this le lien vous aidera. Il suffit de définir la propriété NavigateTo sur la vue à afficher dans la fenêtre.

Par exemple, vous pouvez faire quelque chose comme

<Window x:Class="MainWindowView" xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
                                 xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
                                 xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
                                 xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"
                                 meffed:ViewModelLocator.NonSharedViewModel="YourViewModel"
                                 WindowStartupLocation="CenterScreen">

    <Button meffed:NavigationExtensions.NavigateTo="firstview"
                    meffed:NavigationExtensions.NavigationHost="{Binding ElementName=_viewContainer}"
                    meffed:NavigationExtensions.NavigateOnceLoaded="False"
                    Visibility="Visible" />

    <ContentControl x:Name="_viewContainer" Margin="0,0,0,10" />
<Window>

Ensuite, le fichier de classe serait

public partial class MainWindowView : Window
{
    public MainWindowView()
    {           
              InitializeComponent();
    }

        public ContentControl ViewContainer { get { return _viewContainer; } }

    }

Ensuite, vous pouvez définir chaque vue comme UserControl, puis utiliser le lien que j'ai donné ci-dessus pour lier le meffed:NavigationExtensions.NavigateTo="secondView" Du bouton. Pour cibler le ContentControl du Window, utilisez simplement une liaison RelativeSource. Par exemple

meffed:NavigationExtensions.NavigationHost="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}},Path=ViewContainer}"

Dans chacune des vues, veillez simplement à annoter le code derrière la définition de la classe avec la fonction [NavigationView("firstview")], etc.

C'est compliqué pour la première fois, mais ce sera très facile une fois que vous aurez compris l'idée.

1
Sandesh
<ContentControl x:Name="K.I.S.S" Content="{Binding ViewModel, Converter={StaticResource ViewLocator}}"/>
1
atomaras