2009-03-13 7 views
5

Il y a beaucoup de bons exemples sur MVVM mais je suis toujours confus.Silverlight MVVM reliant le modèle et le modèle de vue

Disons que vous avez un CustomerModel et un CustomerViewModel. Il semble qu'il y aurait une propriété Name sur le CustomerModel et une sur le CustomerViewModel. Le setter sur CustomerViewModel définira la propriété CustomerModel Name, puis appellera OnPropertyChanged (PropName) afin que l'interface utilisateur soit mise à jour. Est-ce vraiment vrai? On dirait que le getter/setters sera défini deux fois. Si vous avez un modèle avec 50 propriétés, cela devient vraiment fastidieux.

Aussi, disons que je définis une propriété Qty. Le ViewModel met à jour le modèle. Le modèle met à jour sa propriété Value en fonction de la nouvelle Qté. Comment ViewModel est-il averti que la propriété Model a été modifiée?

Répondre

2

Dans l'exemple client que vous donnez, le CustomerModel contient toutes les informations stockées par votre base de données (ou autre backend). Le CustomerViewModel contient des informations similaires si elles sont affichées sur l'interface utilisateur (Nom etc., potentiellement 50 autres propriétés si vous avez une classe importante) mais utilise l'interface INotifyPropertyChanged pour les afficher en tant que propriétés que la vue (ie le XAML) peut lier à.

par exemple.

public int Name 
{ 
    get 
    { 
     return this.name; 
    } 

    set 
    { 
     if (this.name!= value) 
     { 
      this.name= value; 
      this.OnPropertyChanged("Name"); 
     } 
    } 
} 

Le ViewModel contient également d'autres bits d'état interface utilisateur - drapeaux de visibilité, index Tab actuelle, les bits plus complexes de texte construit à partir des données dans plusieurs domaines, ObservableCollection < > des éléments enfants, etc. Tous sont là pour être lié au XAML.

J'ai vu le ViewModel créé à partir du modèle comme un processus ponctuel, unidirectionnel, par exemple. avec un constructeur:

CustomerViewModel viewModel = new CustomerViewModel(customer); 

ou comme méthode d'extension

CustomerViewModel viewModel = customer.ToViewModel(); 

Je n'ai vu aucune disposition pour mettre à jour un ViewModel des modifications du modèle - le point de la ViewModel est qu'il est isolé de le modèle. Il conserve une copie séparée des données. Il ne propage pas les modifications vers le modèle, pas avant d'avoir appuyé sur un bouton "Enregistrer". Donc, si vous annulez à la place, rien dans le modèle n'a changé et il n'y a rien à annuler.

Vous essayez peut-être trop de garder le ViewModel à jour avec le modèle - la plupart des cas comme enregistrer ou charger vous pouvez simplement jeter le ViewModel actuel et en créer un nouveau à partir de l'état actuel du modèle. Avez-vous besoin de conserver l'état de l'interface utilisateur de ViewModel et de modifier les données? Ce n'est pas une exigence courante, mais cela peut être fait avec une méthode ou deux appelée quand la sauvegarde ou la charge se produit.

Donc, il y a aussi l'hypothèse que cette logique de branchement arrive quelque part. C'est pourquoi la plupart des modèles qui impliquent vues impliquent également contrôleurs qui sont chargés d'agir sur les commandes (par exemple, afficher un client, enregistrer un client) et mettre en place un nouvel état de l'interface utilisateur par la suite.

+0

Si vous conservez ViewModel distinct du modèle, comment les règles du modèle sont-elles appliquées? Dire que j'ai un modèle avec quantité et valeur. Si je change la Qté sur le ViewModel qui devrait passer au modèle qui met à jour la valeur basée sur la nouvelle Qté. Maintenant, ViewModel devrait montrer la nouvelle valeur. –

+0

"Si je change la quantité sur le ViewModel qui doit passer au modèle" non, pas avant d'avoir appuyé sur un bouton Enregistrer ou similaire. Lorsque vous le faites, le gestionnaire doit mettre à jour le modèle, le conserver et créer un nouveau ViewModel à partir du nouvel état du modèle. – Anthony

+0

Donc, si elle ne passe pas au modèle, alors comment ViewModel obtient-elle un champ de valeur mis à jour? Si je change la quantité, en tant qu'utilisateur je m'attendrais à voir la nouvelle valeur. Le MV n'a pas la logique métier pour calculer la valeur, seul le modèle le fait. –

5

Votre ViewModel ne doit pas encapsuler strictement le modèle. Dans votre scénario, le CustomerViewModel peut avoir une propriété Customer, ce qui signifie que votre View se lie aux propriétés Model ... cela se fait simplement via ViewModel. C'est parfaitement légitime. Cela dit, cependant, il y a souvent un avantage à encapsuler cela. Votre modèle d'entreprise peut ne pas inclure de notification de modification. Vous ne souhaitez peut-être pas que l'interaction de l'utilisateur modifie le modèle d'entreprise tant que l'utilisateur n'a pas cliqué sur un bouton OK.Votre modèle d'entreprise peut présenter des exceptions pour les mauvaises entrées, alors que vous souhaitez utiliser une autre forme de validation. Je suis sûr que vous pouvez penser à d'autres choses. En fait, je suppose que la plupart du temps, vous allez vouloir l'encapsulation, donc ce n'est pas vraiment "fastidieux" dans le sens d'écrire juste beaucoup de méthodes de relais inutiles.

0

La façon exacte dont cela est fait dépendra en partie de votre modèle commercial, comme l'a déjà indiqué wekempf. En fonction de la manière dont vous affichez les informations client dans votre interface utilisateur, vous pouvez avoir un ObservableCollection de types client (votre modèle) dans votre ViewModel. Si, par exemple, vous affichez un scénario maître/détail, où vous pourriez avoir une liste de clients et afficher les détails ci-dessous lorsqu'un client particulier est sélectionné.

Questions connexes