Lors de l'implémentation du ViewModel dans une application WPF d'architecture Model-View-ViewModel, il semble y avoir deux choix principaux pour le rendre lié aux données. J'ai vu des implémentations qui utilisent DependencyProperty
des propriétés contre lesquelles View va se lier et j'ai vu l'implémentation de ViewModel à la INotifyPropertyChanged
place.
Ma question est quand dois-je préférer l'un à l'autre? Y a-t-il des différences de performances? Est-ce vraiment une bonne idée de donner les dépendances de ViewModel à WPF? De quoi d'autre dois-je tenir compte lors de la prise de décision de conception?
INotifyPropertyChanged
.Réponses:
Kent a écrit un blog intéressant sur ce sujet: Afficher les modèles: POCO versus DependencyObjects .
Court résumé:
Je préfère l'approche POCO. Une classe de base pour PresentationModel (alias ViewModel) qui implémente l'interface INotifyPropertyChanged peut être trouvée ici: http://compositeextensions.codeplex.com
la source
Selon le guide de performance WPF, les DependencyObjects fonctionnent définitivement mieux que les POCO qui implémentent INotifyPropertyChanged:
http://msdn.microsoft.com/en-us/library/bb613546.aspx
la source
Le choix est totalement basé sur votre logique métier et le niveau d'abstraction de l'interface utilisateur. Si vous ne voulez pas une bonne séparation, DP travaillera pour vous.
DependencyProperties sera applicable principalement au niveau VisualElements, donc ce ne sera pas une bonne idée si nous créons beaucoup de DP pour chacune de nos exigences commerciales. En outre, il existe un coût plus élevé pour DP qu'un INotifyPropertyChanged. Lorsque vous concevez un WPF / Silverlight, essayez de concevoir l'interface utilisateur et ViewModel de manière totalement distincte afin qu'à tout moment nous puissions modifier les contrôles de disposition et d'interface utilisateur (en fonction du thème et des styles)
Reportez-vous également à cet article - /programming/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . Le lien fait beaucoup référence au modèle Model-View-ViewModel, qui est très pertinent pour cette discussion.
la source
Du point de vue de l'expressivité, j'aime beaucoup utiliser les propriétés de dépendance et grincer des dents à l'idée
INotifyPropertyChanged
. Outre lesstring
noms de propriété et les éventuelles fuites de mémoire dues à l'abonnement aux événements, ilINotifyPropertyChanged
existe un mécanisme beaucoup plus explicite.Les propriétés de dépendance impliquent "quand ceci, faites cela" en utilisant des métadonnées statiques faciles à comprendre. C'est une approche déclarative qui obtient mon vote pour l'élégance.
la source
[CallerMemberName]
.INotifyPropertyChanged
lorsqu'il est utilisé vous donne également la possibilité d'ajouter plus de logique dans le code de vos getters et setter de vos propriétés.DependencyProperty
exemple:Dans votre getter et setter --- tout ce que vous pouvez faire est simplement d'appeler SetValue et GetValue respectivement, b / c dans d'autres parties du framework, le getter / setter n'est pas appelé, au lieu de cela il appelle directement SetValue, GetValue, donc votre logique de propriété ne serait pas être exécuté de manière fiable.
Avec
INotifyPropertyChanged
, définissez un événement:Et puis simplement avoir n'importe quelle logique n'importe où dans votre code, puis appelez:
Cela pourrait être dans un getter / setter, ou n'importe où ailleurs.
la source
Les propriétés de dépendance sont destinées à prendre en charge la liaison (en tant que cible) sur les éléments d'interface utilisateur et non en tant que source à la liaison de données, c'est là qu'INotifyProperty entre en jeu. D'un point de vue pur, vous ne devriez pas utiliser DP sur un ViewModels.
"Pour être la source d'une liaison, une propriété n'a pas besoin d'être une propriété de dépendance. Vous pouvez utiliser n'importe quelle propriété CLR comme source de liaison. Cependant, pour être la cible d'une liaison, la propriété doit être un propriété de dépendance. Pour qu'une liaison unidirectionnelle ou bidirectionnelle soit efficace, la propriété source doit prendre en charge les notifications de modification qui se propagent au système de liaison et donc à la cible. Pour les sources de liaison CLR personnalisées, cela signifie que la propriété doit prendre en charge INotifyPropertyChanged. Les collections doivent prendre en charge INotifyCollectionChanged. "
Tous les objets de dépendance ne peuvent pas être sérialisés (cela pourrait entraver l'utilisation des ViewModels et des DTO (POCO)).
Il existe des différences entre DP dans Silverlight et WPF.
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
la source
J'ai moi aussi dû reconsidérer cette décision récemment.
J'ai trouvé que le mécanisme INotifyPropertyChanged convenait mieux à mes besoins car il me permettait de coller mon interface graphique à un cadre logique métier existant sans dupliquer l'état. Le cadre que j'utilisais avait son propre modèle d'observateur et il était facile de transmettre un niveau de notification au suivant. J'ai simplement eu une classe qui a implémenté l'interface d'observateur à partir de mon cadre logique métier et de l'interface INotifyPropertyChanged.
Avec DP, vous ne pouvez pas définir vous-même le backend qui stocke l'état. J'aurais dû laisser .net mettre en cache une copie de chaque état auquel je me liais. Cela semblait être une surcharge inutile - mon état est vaste et compliqué.
J'ai donc trouvé INotifyPropertyChanged mieux pour exposer les propriétés de la logique métier à l'interface graphique.
Cela étant dit, là où j'avais besoin d'un widget GUI personnalisé pour exposer une propriété et pour que les modifications apportées à cette propriété affectent d'autres widgets GUI, DP a prouvé la solution simple.
J'ai donc trouvé DP utile pour la notification GUI vers GUI.
la source
.NET 4.0 aura System.Xaml.dll, vous n'aurez donc pas à dépendre d'une infrastructure arbitraire pour l'utiliser. Voir le post de Rob Relyea sur sa session PDC.
Ma prise
XAML est un langage pour décrire des objets et WPF est un framework dont les objets décrits sont des éléments d'interface utilisateur.
Leur relation est similaire à C #, un langage pour décrire la logique, et .NET, un cadre qui implémente des types particuliers de logique.
Le but de XAML est les graphes d'objets déclaratifs. Les technologies W * F sont d'excellents candidats pour ce paradigme, mais XAML existe indépendamment d'eux.
XAML et l'ensemble du système de dépendance ont été mis en œuvre en tant que piles distinctes pour WF et WPF, probablement pour tirer parti de l'expérience de différentes équipes sans créer de dépendance (sans jeu de mots) entre elles.
la source
Les propriétés de dépendance sont le ciment de la création de contrôles personnalisés. Si vous souhaitez utiliser Intelli-sense pour afficher vos propriétés dans la fenêtre des propriétés au moment du design XAML, vous devez utiliser les propriétés de dépendance. INPC n'affichera jamais une propriété dans la fenêtre de propriétés au moment du design.
la source
Il semble que les propriétés de dépendance doivent être utilisées dans les contrôles que vous créez, tels que les boutons. Pour utiliser des propriétés dans XAML et utiliser toutes les fonctionnalités WPF, ces propriétés doivent avoir des propriétés de dépendance.
Cependant, votre ViewModel est préférable d'utiliser INotifyPropertyChanged. L'utilisation d'INotifyPropertyChanged vous donnera la possibilité d'avoir une logique getter / setter si vous en avez besoin.
Je recommande de vérifier la version de Josh Smith d'une classe de base pour un ViewModel qui implémente déjà INotifyPropertyChanged:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
Je pense que c'est un excellent exemple de la façon de faire un ViewModel.
la source
Je pense que DependencyProperty et INotifyPropertyChanged sont utilisés pour deux choses différentes dans Binding: la première pour permettre à une propriété d'être la cible d'une liaison et de recevoir l'entrée d'une autre propriété (utilisez {Binding ...} pour définir la propriété), la dernière lorsque vous souhaitez que la valeur d'une propriété soit utilisée comme source d'une liaison (nom dans l'expression du chemin de liaison). Le choix est donc purement technique.
la source
Je préfère une approche plus directe, sur laquelle j'ai blogué dans Presentation Model Without INotifyPropertyChanged . En utilisant une alternative à la liaison de données, vous pouvez vous lier directement aux propriétés CLR sans aucun code de tenue de livres. Vous écrivez simplement du code .NET ancien dans votre modèle d'affichage, et il est mis à jour lorsque votre modèle de données change.
la source
INotifyPropertyChanged
,PropertyDescriptor
sont utilisés, ce qui provoque des fuites de mémoireIl n'y a qu'une seule raison pour laquelle préférer un
DependencyObject
- La reliure fonctionnera mieux. Essayez simplement un exemple avec unListBox
etTextBox
, remplissez la liste avec les données de laINotifyPropertyChanged
propriétéDependencyProperty
et modifiez l'élément actuel à partir deTextBox
...la source
Si vous souhaitez exposer des propriétés à d'autres contrôles, vous devez utiliser les propriétés de dépendance ... Mais bonne chance car elles prennent un certain temps à comprendre ...
la source