2010-10-31 8 views
5

Je suis un peu nouveau pour MVVM. Je ne suis pas sûr de la meilleure façon de faire ce que j'essaie de faire.Bonne façon d'accéder à un modèle de vue à partir d'un modèle de vue existant

Voici le scénario:

J'ai une machine virtuelle qui va afficher une autre fenêtre. Je peux appeler myNewWindowView.Show(), mais d'abord j'ai besoin de définir des données dans la VM de ma nouvelle fenêtre.

Devrais-je exposer à la fois le myNewWindowView et le NewWindowViewModel au ViewModel appelant?

Voici un exemple:

class MainVM 
{ 
    public void FindCustomer(string nameParial) 
    { 
     List<Customer> customers = ServiceCall.GetCustomers(nameParital); 
     // This is the part I am not sure how to do. I am not sure if this 
     // View Model should have a reference to a different view model and 
     // the view too. 
     myNewWindowViewModel.CustomerList = customers; 
     myNewWindowView.Show(); 
    } 
} 

Répondre

3

je garderais la viewmodel séparée de toute vue. J'ai tendance à les considérer comme des couches, mais elles ne sont interchangeables que dans un seul sens. Par conséquent, un modèle de type foo peut avoir n'importe quel modèle de vue en superposition, et il ne s'attend ni ne se soucie du type de modèle de vue. Un modèle de vue ne peut être que pour un type de modèle, mais il ne se soucie pas du type de vue qui l'utilisera.

Une vue sera pour un type particulier de viewmodel. Ce que vous semblez avoir est un viewmodel les soucis de ce que les vues font, ce qui me semble faux.

Si c'était moi, j'obtiendrais la vue pour MainVM pour afficher la nouvelle fenêtre, obtenant le MainVM pour passer le modèle approprié pour la nouvelle fenêtre.

C'est le code que je mettrais derrière le point de vue de la principale viewmodel

class MainWindow : Window 
{ 
    public MainWindow() 
    { 
      Initialize(); 
      DataContext = new MainVM(); 
    } 

    public void FindCustomerClick(object sender, RoutedEventArgs args) 
    { 
      CustomerListView clv = new CustomerListView(); 
      clv.DataContext = (DataContext as MainVM).FindCustomer(search.Text); 
      clv.Show(); 
    } 
} 

Comme vous pouvez le voir, le viewmodel a une méthode qui prend une chaîne et retourne un CustomerListViewModel, qui est ensuite appliquée à la DataContext d'un CustomerListView.

+0

Sonne bien, mais sonne aussi flou. Pouvez-vous me montrer un exemple de la façon dont vous feriez mon exemple? (C'est à dire avoir une fenêtre ouverte une autre avec des données passées entre eux.) – Vaccano

+0

Je vais essayer. Je vais probablement devoir le réparer plus tard, comme je le fais depuis mon téléphone :) –

+0

Cela semble bien, sauf que mon 'CustomerListView.DataContext' est défini sur mon' CustomerListViewModel'. Si je définis sur le résultat de 'FindCustomer' alors je perds l'installation MVVM pour cette vue. – Vaccano

2

Ne pas référencer les vues dans votre modèle de vue. Avoir des vues créer des vues et voir des modèles créer des modèles de vue.

Un moyen simple d'accomplir cette séparation des préoccupations est avec les événements. La façon rapide et sale de le faire est de créer une propriété ChildViewModel sur votre modèle de vue parent, puis gérer PropertyChanged dans la vue, par exemple:

ParentViewModel vm = (ParentViewModel)DataContext; 
vm.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "ChildViewModel") 
    { 
     MyChildWindow w = new MyChildWindow(); 
     w.Show(vm.ChildViewModel); 
    } 
}; 

Maintenant, chaque fois que le modèle de vue parent modifie la propriété ChildViewModel, la La vue parent ouvrira une nouvelle vue enfant.

A moins rapide et moins sale, l'approche est de créer un délégué CreateViewEventHandler et CreateViewEventArgs classe, et rendre le gestionnaire d'événements, et une méthode OnCreateView protégée, une partie de votre classe vue base de modèle (en supposant que vous en avez un). Cela permet au modèle de vue d'être beaucoup plus explicite quant à la création d'une fenêtre enfant. Notez que s'il est important pour le modèle de vue parent de savoir quand le modèle de vue enfant a fermé, le modèle de vue enfant peut exposer un événement auquel le parent peut s'abonner (ou, encore une fois, utiliser une propriété et l'événement PropertyChanged).Notez que dans les deux cas, vous pouvez écrire des tests unitaires qui vérifient que le modèle de vue ouvre la fenêtre (c'est-à-dire déclenche l'événement) lorsqu'il est supposé ne pas impliquer les vues.

Je n'ai utilisé aucun framework MVVM moi-même, mais ceux que j'ai examinés ont des outils de messagerie conçus pour faciliter ce genre de choses.

Questions connexes