2016-11-16 1 views
0

J'ai cherché pendant près de 3 heures et j'ai trouvé beaucoup de choses sur le partage de données PRISM et VM, mais je n'arrive pas à comprendre mon cerveau.Deux ViewModels utilisent un modèle qui contient des données

J'ai les deux ViewModels MainViewModel et ListViewModel. Le MainViewModel a un dockpanel où je veux avoir un menu commun à ajouter, supprimer des éléments et fermer l'application par exemple. Il y a aussi un usercontrol dans le XAML qui montre le ListView. Le ListView contient quelques ObservableCollection<ProjectModel>. Depuis MainVM, je veux ajouter plus de Projets - donc à une collection. Pour accéder au ListModel, qui contient les données, je passe au constructeur des deux ViewModels:

public MainModuleViewModel(ListModel listModel) 
     { 
      ListModel = listModel; 
      InitializeCommands(); 
     } 

public ListModuleViewModel(ListModel listModel) 
     { 
      ListModel = listModel; 
      InitializeCommands(); 
     } 

Mais il semble que pendant initializaiton à différents objets de ListModel sont créés.

Donc, ma question est: Que dois-je faire, pour travailler uniquement sur l'objet de ListModel, que je passe aux constructeurs?

+0

Comment créez-vous les instances de modèles de vue? – dymanoid

+0

utilisez-vous l'injection ou quelque chose? D'une certaine manière, vous devez passer la même instance aux deux constructeurs. Vous devriez montrer où vous instancier ces classes – Jonesopolis

+1

Peut-être pourriez-vous utiliser quelque chose comme un 'IListModelProvider' que vous injecteriez dans les deux classes. Ceci est tout simplement nouveau 'ListModel's si nécessaire, mais conserve un stock de modèles créés pour ne pas reconstruire des modèles existants? –

Répondre

1

Vous avez deux options, comme toujours:

  • enregistrer les ListModel comme singleton (ContainerControlledLifetimeManager dans l'unité)
  • ou enregistrer un service comme singleton qui donne les données au modèle de vue

Je voudrais aller avec le second car il est beaucoup plus flexible - vous pouvez utiliser une autre instance ListModel ailleurs avec un contenu différent, vous pouvez faire le service pour donner à chaque modèle de vue sa propre instance (bien que me contenu) ou vous pouvez le faire donner à chaque modèle de vue la même instance et ainsi de suite ...

public interface IDatasource 
{ 
    ListModel Data { get; } 
} 

internal class StephensService : IDatasource 
{ 
    ListModel Data { get; } = new ListModel(); // or however you plan to procure the data 
} 

// ... bootstrapper/module initialization ... 

Container.RegisterType<IDatasource, StephensService>(new ContainerControllerLifetimeManager()); 

// ... 

internal class ListModuleViewModel 
{ 
    public ListModuleViewModel(IDatasource datasource) 
    { 
     var heresMyData = datasource.Data; 
    } 
} 

En fonction de vos besoins, le service peut mettre en œuvre INotifyPropertyChanged ou ListModel peut être un ObservableCollection ...

+0

J'ai essayé de le coder, mais ça ne marche pas. À quoi sert le 'IDataSource'? J'ai un manque de compréhension ici. Avez-vous un exemple pour moi s'il vous plaît? –

+1

L'interface est là pour rendre le modèle de vue indépendant de l'implémentation concrète de la source de données qu'il utilise. Pensez à un test unitaire pour le modèle de vue: voulez-vous utiliser la source de données réelle ou préférez-vous passer un simulacre?L'utilisation du simulacre rendra le test unitaire plus court, plus stable, plus facile à comprendre et probablement plus rapide ... – Haukinger

+0

Très bien. Je l'ai eu le travail! :) J'ai oublié d'initialiser 'Container.RegisterType' dans le constructeur de cette classe. Une autre question: Est-ce que cela fait une énorme différence si je l'inscrive ou l'ajoute en tant que module dans le bootstrapper? –