Comment un modèle de vue peut-il savoir quand les données d'un service sont mises à jour?

StackOverflow https://stackoverflow.com/questions/645557

  •  22-07-2019
  •  | 
  •  

Question

Dans mon application, j'ai plusieurs modèles View qui ont un seul service (référentiel, DAO, peu importe), appelons-le le WidgetService , qui leur est injecté.

Supposons que l'un de ces modèles de vue est une liste de tous les widgets d'un utilisateur. Un autre exemple pourrait être le ViewModel pour l'édition / la création d'un seul de ces widgets.

L'utilisateur peut afficher la liste des widgets dans le WidgetListView soutenu par un WidgetListViewModel et cliquer sur un bouton pour ajouter un nouveau widget. Pour créer ce nouveau widget, un CreateWidgetViewModel est nouveau et est injecté dans le DataContext de certains UserControl / Window, grâce à la magie de DataTemplates affichant le CreateWidgetViewModel dans un < strong> CreateWidgetView . En outre, la création de CreateWidgetViewModel ne se produit pas nécessairement dans le cadre de WidgetListViewModel .

Lorsque le WidgetListViewModel a été injecté avec une instance du WidgetService . CreateWidgetViewModel a été injecté avec la même instance WidgetService .

Maintenant, lorsque l'utilisateur clique sur Enregistrer dans la CreateWidgetView , la méthode Enregistrer sur le WidgetService sera invoquée. et le widget sera persisté. Désormais, le WidgetListViewModel doit être averti de la création d’un nouveau widget.

La longue accumulation conduit à cette question: comment informer le WidgetListViewModel du fait qu’il doit afficher le nouveau widget?

J'ai vu une vidéo dans laquelle Le gars de Microsoft fait ce genre de chose en utilisant un événement sur le service auquel le ViewModel est abonné. Cependant, l'inconvénient est que si le service survit au modèle de vue, celui-ci ne sera pas GC'd tant que le service ne l'est pas. Je pourrais ajouter IDisposable au ViewModel. Mais alors, quand et comment appeler Dispose quand le ViewModel est uniquement représenté dans l’UI via DataTemplates?

Quelqu'un at-il des suggestions à ce sujet?

Pour clarifier, je dirais que mon interprétation de MVVM ressemble le plus à celle de Josh Smith. Du moins dans la mesure où mon architecture MVVM correspond assez bien à celle trouvée dans la source Crack.Net.

Était-ce utile?

La solution

D'accord, vu qu'il n'y a pas encore eu de réponse à cette question, je pensais essayer mais je ne suis pas un expert en MVVM.

Les événements semblent être la solution. Toutefois, comme vous l'avez fait remarquer, une fuite de mémoire peut survenir si le service a une durée de vie supérieure à ViewModel. Le meilleur moyen de résoudre ce problème consiste à utiliser un écouteur d'événements faible.

Evénements faibles vous permet de vous connecter à un événement avec une référence faible de sorte que si l'objet source est GC'd, la source n'est pas conservée en vie par le gestionnaire d'événements.

Autres conseils

Utilisez les informations de Prism ( http://www.codeplex.com/CompositeWPF ) EventAggregator qui utilise le modèle éditeur-abonné, fournissant un couplage sans perte entre les éléments cible et source. Parfait pour exactement le scénario que vous décrivez.

J'ai utilisé le modèle Observer (le modèle de publication / abonnement) pour résoudre ce problème. problème. J'ai créé une classe que j'ai appelée EventAggregator qui partageait toutes les méthodes et tous les membres de données. Je pouvais m'inscrire à un événement sur le WidgetListViewModel et publier un " Widget Created " événement dans CreateWidgetViewModel. Vous pouvez demander à WidgetListViewModel de mettre en œuvre IDisposable (mieux) pour annuler l’enregistrement de votre événement ou simplement l’annuler dans la méthode Finalize. Cela a très bien fonctionné et la meilleure partie est que les deux modèles de vue n’avaient pas besoin de se connaître.

Pour quelque chose de plus compliqué ou si vous avez besoin de supporter les différences de version entre le service et votre application, vous pouvez implémenter un ModelView qui gèrerait ce genre de choses en créant le motif M-MV-VM-V de vos applications. Cela peut sembler un peu exagéré, mais cela peut rendre certaines catégories de problèmes beaucoup plus faciles à gérer. Je sais que j'ai eu quelques projets pour lesquels j'aurais souhaité insérer une MV, car la diaphonie entre les machines virtuelles et le code d'annulation vient de devenir ridicule.

Il y a plusieurs options:

  1. Utilisez ObservableCollection - il s’agit probablement de l’option la plus simple, mais vous devez disposer d’une sorte de "maître". collection dans le modèle et que l’interface utilisateur se lie directement à cette collection, elle peut ne pas être "propre". L’architecture MVVM, mais c’est probablement le moyen le plus simple de faire le travail.

  2. Utilisez l'événement et assurez-vous de nettoyer après vous-même, ce qui est difficile à faire dans MVVM.

  3. Utilisez un intermédiaire pour nettoyer automatiquement les événements (comme d'autres l'ont suggéré), mais n'écrivez pas le vôtre, il y a de nombreux pièges à cela, WPF a une classe intégrée qui le fait, mais j'ai oublié le nom (si quelqu'un se souvient du nom, laissez un commentaire).

  4. Effectuez des actualisations périodiques. Si la classe ViewModel actualise la liste toutes les X secondes, c’est le seul moyen d’obtenir les mises à jour sans aucune sorte de mécanisme de notification à gérer.

Je suis d’accord avec Cameron pour utiliser le modèle WeakEvent. J'ai créé une classe de base pour ViewModel (dans mon exemple, j'utilise le nom PresentationModel) qui prend en charge le modèle WeakEvent.

Vous pouvez trouver mon exemple de projet utile: http://www.codeplex.com/CompositeExtensions

jbe

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top