ViewModels in ViewModelLocator MVVM Light

Est-il correct de stocker l'ensemble de mes Viewmodel dans SimpleIoc? Par exemple, j'ai trois pages page principale, Photos, répertoires (donc trois modèles de vue -> MainVM, PhotosVM, DirectoriesVM). Dois-je définir DataContext dans chaque page pour afficher la propriété Model dans ViewModelLocator ou Nest ViewModels comme propriétés dans MainVM et lier chaque page DataContext À Main.PhotosVMProperty, Main.DirectoriesVMProperty et ainsi de suite? Quelqu'un pourrait-il m'expliquer l'idée et le but du CIO ?

33
demandé sur McGarnagle 2013-01-03 02:34:16

2 réponses

tout d'abord, regardons ce que ViewModelLocator fait et pourquoi nous l'utilisons:

ViewModelLocator est déclaré comme un objet sur notre Application.XAML page et est une application singleton. Nous allons en avoir un, et un seul d'entre eux disponibles pour l'application quand il fonctionne.

ViewModelLocator est la source de tous nos Viewmodel dans MVVM Light. Pour chaque ViewModel, nous aurons une propriété sur le ViewModelLocator qui nous permet d'obtenir un ViewModel pour une vue. Ce code ressemble ceci:

public class ViewModelLocator
{
    public MainPageViewModel MainPage
    {
        get { return new MainPageViewModel(); }
    }
}

Ceci est une partie de mon application.xaml:

<Application.Resources>
    <vm:ViewModelLocator
        x:Key="ViewModelLocator" />
</Application.Resources>

C'est un morceau de Vue.xaml

DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}"

So far So good. Pour répondre à votre première question, devez-vous utiliser Ioc in MVVM Light? Aucun. Il n'y a aucun besoin car votre viewmodel sera donné à votre vue entièrement construite et instanciée par le ViewModelLocator.

maintenant, sur votre deuxième question: Quel est le but du CIO?

le COI est conçu pour vous permettre de faire suivantes:

Avec Mvvm Light vous faites le au-dessus comme ceci:

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, DataService>();         
        }

        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
    }
}

public class MainViewModel
{
    public ObservableCollection<Foo> Foos { get; set; }

    public MainViewModel(IDataService dataService)
    {
        _dataService=dataService;
        Foos=_dataService.GetFoos();
    }
}

Quand je résoudre mon MainViewModel quand je l'appelle

SimpleIoc.Default.GetInstance<MainViewModel>()

ce qui se passe en interne, c'est que le SimpleIoc vérifie si le Modèleview main a des dépendances (paramètres dans son constructeur). Il essaie ensuite de résoudre ces paramètres en regardant les interfaces qui ont été enregistrées avec lui. Il le fait de façon récursive, donc si DataService avait une dépendance, il serait instancié et passé au constructeur DataService lors de son instanciation.

pourquoi ferais-je tout ce travail?

  1. rendez vos classes facilement testables à l'unité
  2. activez l'interface de votre code. Cela signifie que vous faites référence à des interfaces plutôt qu'à des classes concrètes
  3. faites un couplage lâche de votre code. Cela signifie que quelqu'un peut changer la mise en œuvre d'une interface et les classes qui consomment cette interface ne se soucient pas et n'avez pas à être re-codé.
  4. résolvez vos dépendances de classes de manière automatisée.
  5. à la lumière MVVM, vous verrez qu'elle peut dire quand elle tourne en mode design (ViewModelBase.IsInDesignModeStatic), cela signifie que vous pouvez créer des services de design-time pour fournir vos données de modèles de vue afin que votre vue dans Visual Studio contienne des données réelles.
120
répondu Faster Solutions 2013-04-27 13:34:05

MVVM Light a beaucoup de belles fonctionnalités, mais il me semble que le Localisateur de Service crée une dépendance indésirable des vues sur les modèles de vue. Idéalement, je voudrais avoir le ViewModelLocator dans la bibliothèque A, les modèles de vue dans la bibliothèque B et les vues dans la bibliothèque C. Alors je peux mélanger et faire correspondre ces derniers si nécessaire pour les projets futurs. Cependant, dans la conception de MVVM Light, pour autant que je puisse voir, les vues (bibliothèque C) auront toujours une dépendance sur le ViewModelLocator (c'est correct) mais parce que le ViewModelLocator (bibliothèque A) aura toujours une dépendance sur les modèles de vue (bibliothèque B), alors les vues dépendront toujours des modèles de vue (ce n'est pas correct car une vue doit maintenant inclure toutes les bibliothèques de modèles de vue qu'elle a été utilisée avec tous les produits).

je crois que Prism contourne ce problème en utilisant les touches string d'une façon ou d'une autre. Ai-je raté quelque chose?

Oups! Je pense que je viens de répondre à ma propre question. La solution est de faire de la bibliothèque un, le ServiceLocator, spécifique à une solution particulière (produit). Il contient ensuite une référence aux modèles de vue uniquement pour cette solution. Puis les vues dépendent de ce ServiceLocator qui à son tour dépend de tous les modèles de vue pour ce produit. Le résultat final est que les vues dépendent uniquement des modèles de vues qui seront utilisés pour ce produit. Il n'y a aucun problème avec le fait que nous dupliquons le ServiceLocator pour chaque solution car ce module ne contient que du code qui est spécifique à la solution. Les composants du ServiceLocator tels que la classe SimpleIoc sont, bien sûr, communs à toutes les solutions, mais ils ont été pris en compte dans des classes réutilisables que nous invoquons dans ServiceLocator.

pour résumer les choses, le problème que j'essaie de résoudre est de supposer qu'une solution a 6 modèles de vue, dont quatre sont étroitement liés et deux sont étroitement liés. Nous créons donc deux assemblées, chacune contenant la vue étroitement liée modèle. Supposons que nous concevons un produit qui utilise un ensemble de modèles de vue et la solution est conçue pour exécuter Windows 8. Maintenant les vues sont toutes différentes et nous voulons réutiliser un seul ensemble (assemblage) de modèles de vue. Nous nous contentons donc de créer une nouvelle assemblée ServiceLocator qui pointe vers cette assemblée de modèles de vue et aussi vers tous les autres dont nous avons besoin. Nos nouvelles vues Windows 8 dépendent désormais de ce nouvel assemblage ServiceLocator et seulement des modèles de vue qui sont utilisés dans notre nouveau produit (solution).

1
répondu Richard 2015-06-20 02:31:22