2010-09-16 8 views
4

Vous recherchez des indications sur l'emplacement du code dépendant des modifications apportées à une propriété.Lors de l'utilisation d'un modèle MVVM, le code relatif aux modifications de propriétés doit-il figurer dans le setter ou un événement?

Par exemple, j'ai un modèle de vue qui est utilisé pour maintenir l'état pour un des paramètres d'applications

public SettingsViewModel(ISettingsRepository settings) 
{ 
    _settings = settings; 
    // ... 
} 

Pour chaque modification d'une propriété de paramètres que nous devons persister ce changement dans le référentiel, et sur certaines propriétés , d'autres propriétés sont affectées, un code supplémentaire est donc requis.

J'ai commencé simplement ajouter cette logique au poseur

public ProjectCollection Projects 
{ 
    get { return _projects; } 
    set 
    { 
     if (_projects == value) return; 
     _projects = value; 
     RaisePropertyChanged("Projects"); 

     // Extra work needed when collection of projects change 
     _settings.SaveProjects(_projects); 
     Startable = _projects != null && _projects.Count > 0; 
    } 
} 

Mais intervertis pour le câblage en cas PropertyChanged pour INotifyPropertyChanged et a retiré le code supplémentaire sur le poseur de propriété

public SettingsViewModel(ISettingsRepository settings) 
{ 
    _settings = settings; 
    // ... 
    PropertyChanged += onPropertyChanged; 
} 

void onPropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    switch (e.PropertyName) 
    { 
     case "Projects": 
      _settings.SaveProjects(Projects); 
      Startable = Projects != null && Projects.Count > 0; 
      break; 
     // ... 
    } 
} 

public ProjectCollection Projects 
{ 
    get { return _projects; } 
    set 
    { 
     if (_projects == value) return; 
     _projects = value; 
     RaisePropertyChanged("Projects"); 
    } 
} 

Avoir la logique à l'intérieur du setter signifie moins de code à écrire, moins de chance de faire une erreur en câblant le mauvais nom de propriété (le test unitaire devrait le ramasser) et serait légèrement plus rapide, bien que probablement insignifiant. Avoir la logique câblée à un événement semble être une approche plus maintenable, tant que les méthodes sont nommées de manière appropriée, il devrait être plus facile de suivre le code, et signifie que le setter ne fait pas d'autre travail en dehors de la mise en propriété. Je suppose qu'il pourrait également fournir plus de flexibilité, en utilisant l'exemple ci-dessus, si les exigences changeaient de sorte que la persistance des changements se produise à partir d'un autre événement, par exemple. Bouton "Enregistrer" cliquez sur le changement de propriété, puis le code devrait être plus facile à modifier. J'apprécie que ce soit une question subjective, mais je suis nouveau dans le modèle MVVM (même si je suppose que cela peut être vrai pour n'importe quelle logique de setter?) Donc je cherche d'autres raisons avant de m'arrêter sur une approche. Merci!

+0

Je vote pour des événements. Je n'ai pas grand-chose à ajouter au-delà de ce que vous avez déjà identifié, mais la promotion d'un modèle de vue plus facile à maintenir et le maintien d'un but unique semblent être un choix évident pour moi. Je soupçonne également que vous pouvez vous retrouver avec beaucoup de code en double dans les différents setters; que se passe-t-il si vous en avez plusieurs qui dépendent des mêmes propriétés?Un événement peut ne pas épargner beaucoup de code, mais le fait d'avoir tout en un seul endroit plutôt que de se propager à tous les différents setters semble plus gérable. –

+0

Merci Dan, je me penchais aussi, mais je pense que la réponse des slugsters est encore plus belle. – si618

Répondre

4

Lorsque vous décidez quel code mettre où, rappelez-vous ceci: un ViewModel est pour présenter les données à la vue. Il peut masser ou manipuler les données un peu pour le faire (dans le cas bien sûr - le changement d'une valeur à une couleur pourrait être considéré comme très bien à faire). Le ViewModel ne connaît rien de l'interface utilisateur et ne sait rien sur l'enregistrement des données. Les paramètres de propriété doivent être aussi simples que possible, et ils doivent avertir si quelque chose dépend d'eux (ce qui sera généralement le cas - la VM est utilisée pour la liaison). Cela signifie que votre deuxième exemple utilisant le gestionnaire d'événements OnPropertyChanged() est une meilleure option que le premier exemple.

Cependant, il en sait encore trop à mon goût. J'élèverais des événements auxquels le Modèle peut souscrire, et laisserais le Modèle faire le travail. Le ViewModel devrait juste dire "hé, mes données ont changé, je me fiche de ce que vous faites à ce sujet mais je vous ai dit de faire ce que vous voulez". Le modèle peut ensuite soit enregistrer instantanément, ou ce que jusqu'à plus de changements ont eu lieu avant de persister les données.

+0

Ah, c'est tout à fait logique! Ainsi, au lieu de passer le ISettingsRepository à ViewModel, il y aurait un SettingsModel (qui connaît ISettingsRepository), et ce modèle est passé à SettingsViewModel. Ainsi, le modèle de vue définit simplement la propriété models dans son setter, et le modèle est responsable de la persistance (ou autre chose). C'est beaucoup mieux, merci slugster! – si618

+0

Oui, vous l'avez. Le modèle peut lire les valeurs hors de la machine virtuelle (car le modèle est informé de la machine virtuelle) ou la machine virtuelle peut communiquer les valeurs modifiées en tant qu'arguments dans l'événement déclenché. – slugster