Al implementar ViewModel en una aplicación WPF de arquitectura Model-View-ViewModel, parece haber dos opciones principales sobre cómo hacer que se puedan combinar datos. He visto implementaciones que usan DependencyProperty
para propiedades con las que la Vista se va a unir y he visto la implementación de ViewModel en su INotifyPropertyChanged
lugar.
Mi pregunta es ¿cuándo debería preferir uno sobre el otro? ¿Hay alguna diferencia de rendimiento? ¿Es realmente una buena idea dar las dependencias de ViewModel a WPF? ¿Qué más debo tener en cuenta al tomar la decisión de diseño?
INotifyPropertyChanged
.Respuestas:
Kent escribió un blog interesante sobre este tema: Ver modelos: POCOs versus DependencyObjects .
Breve resumen:
Prefiero el enfoque POCO. Puede encontrar una clase base para PresentationModel (también conocido como ViewModel) que implementa la interfaz INotifyPropertyChanged aquí: http://compositeextensions.codeplex.com
fuente
Según la guía de rendimiento de WPF, los DependencyObjects definitivamente funcionan mejor que los POCO que implementan INotifyPropertyChanged:
http://msdn.microsoft.com/en-us/library/bb613546.aspx
fuente
La elección se basa totalmente en la lógica de su negocio y el nivel de abstracción de la interfaz de usuario. Si no desea una buena separación, DP trabajará para usted.
DependencyProperties se aplicará principalmente en el nivel de VisualElements, por lo que no será una buena idea si creamos muchos DP para cada uno de nuestros requisitos comerciales. También hay un mayor costo para DP que un INotifyPropertyChanged. Cuando diseñe un WPF / Silverlight, intente diseñar la interfaz de usuario y ViewModel totalmente separados para que en cualquier momento podamos cambiar los controles de diseño e interfaz de usuario (según el tema y los estilos)
Consulte esta publicación también: /programming/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . El enlace tiene mucha referencia al patrón Model-View-ViewModel, que es muy relevante para esta discusión.
fuente
Desde el punto de vista de la expresividad, disfruto mucho el uso de las propiedades de dependencia y me encojo al pensar en ello
INotifyPropertyChanged
. Además de losstring
nombres de propiedad y las posibles pérdidas de memoria debido a la suscripción de eventos,INotifyPropertyChanged
es un mecanismo mucho más explícito.Las propiedades de dependencia implican "cuando esto, haga eso" utilizando metadatos estáticos fáciles de entender. Es un enfoque declarativo que consigue mi voto por la elegancia.
fuente
[CallerMemberName]
.INotifyPropertyChanged
cuando se usa también le brinda la capacidad de agregar más lógica en el código de sus captadores y definidor de sus propiedades.DependencyProperty
ejemplo:En su getter y setter --- todo lo que puede hacer es simplemente llamar a SetValue y GetValue respectivamente, b / c en otras partes del marco no se llama al getter / setter, sino que llama directamente a SetValue, GetValue, por lo que su lógica de propiedad no ser ejecutado de manera confiable.
Con
INotifyPropertyChanged
, defina un evento:Y luego simplemente tenga cualquier lógica en cualquier parte de su código, luego llame:
Esto podría estar en un getter / setter, o en cualquier otro lugar.
fuente
Las propiedades de dependencia están destinadas a admitir enlaces (como destino) en elementos de la interfaz de usuario, no como fuente de enlace de datos, aquí es donde entra INotifyProperty. Desde un punto de vista puro, no debe usar DP en un ViewModels.
"Para ser la fuente de un enlace, una propiedad no necesita ser una propiedad de dependencia; puede usar cualquier propiedad CLR como fuente de enlace. Sin embargo, para ser el objetivo de un enlace, la propiedad debe ser un propiedad de dependencia. Para que un enlace unidireccional o bidireccional sea efectivo, la propiedad fuente debe admitir notificaciones de cambio que se propaguen al sistema de enlace y, por lo tanto, al destino. Para fuentes de enlace CLR personalizadas, esto significa que la propiedad debe admitir INotifyPropertyChanged. Las colecciones deben admitir INotifyCollectionChanged ".
Todos los objetos de dependencia no se pueden serializar (esto podría dificultar el uso de ViewModels y DTO (POCO).
Hay diferencias entre DP dentro de Silverlight en comparación con WPF.
http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx
fuente
Yo también tuve que considerar esta decisión recientemente.
Descubrí que el mecanismo INotifyPropertyChanged se adaptaba mejor a mis necesidades porque me permitía pegar mi GUI a un marco lógico comercial existente sin duplicar el estado. El marco que estaba usando tenía su propio patrón de observación y era fácil reenviar un nivel de notificación al siguiente. Simplemente tuve una clase que implementó la interfaz de observador desde mi marco de lógica de negocios y la interfaz INotifyPropertyChanged.
Con DP no puede definir el backend que almacena el estado usted mismo. Hubiera tenido que dejar que .net almacenara en caché una copia de cada elemento de estado al que estaba vinculado. Esto parecía una sobrecarga innecesaria: mi estado es grande y complicado.
Entonces, aquí encontré INotifyPropertyChanged mejor para exponer propiedades de la lógica empresarial a la GUI.
Dicho esto, donde necesitaba un widget GUI personalizado para exponer una propiedad y para que los cambios en esa propiedad afecten a otros widgets GUI DP demostró la solución simple.
Entonces allí encontré DP útil para la notificación de GUI a GUI.
fuente
.NET 4.0 tendrá System.Xaml.dll, por lo que no tendrá que depender de un marco arbitrario para utilizarlo. Vea la publicación de Rob Relyea sobre su sesión de PDC.
Mi toma
XAML es un lenguaje para describir objetos, y WPF es un marco cuyos objetos descritos son elementos de la interfaz de usuario.
Su relación es similar a C #, un lenguaje para describir la lógica, y .NET, un marco que implementa tipos particulares de lógica.
El propósito de XAML son los gráficos de objetos declarativos. Las tecnologías W * F son excelentes candidatos para este paradigma, pero XAML existe independientemente de ellas.
XAML y todo el sistema de dependencia se implementaron como pilas separadas para WF y WPF, probablemente para aprovechar la experiencia de diferentes equipos sin crear una dependencia (sin juego de palabras) entre ellos.
fuente
Las propiedades de dependencia son el pegamento de la creación de controles personalizados. Si está interesado en usar Intelli-sense para mostrar sus propiedades en la ventana de propiedades en tiempo de diseño XAML, debe usar las propiedades de dependencia. INPC nunca mostrará una propiedad en la ventana de propiedades en tiempo de diseño.
fuente
Parece que las Propiedades de dependencia deben usarse en controles que cree, como Botones. Para usar propiedades en XAML y usar todas las características de WPF, esas propiedades deben Propiedades de dependencia.
Sin embargo, su ViewModel está mejor usando INotifyPropertyChanged. El uso de INotifyPropertyChanged le dará la capacidad de tener lógica getter / setter si es necesario.
Recomiendo revisar la versión de Josh Smith de una clase base para un ViewModel que ya implementa INotifyPropertyChanged:
http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/
Creo que este es un excelente ejemplo de cómo hacer un ViewModel.
fuente
Creo que DependencyProperty e INotifyPropertyChanged se usan para dos cosas diferentes en Binding: la primera para permitir que una propiedad sea el objetivo de un enlace y recibir la entrada de otra propiedad (use {Binding ...} para establecer la propiedad), la última cuando desea que el valor de una propiedad se use como origen de un enlace (nombre en la Expresión de ruta de enlace). Entonces la elección es meramente técnica.
fuente
Prefiero un enfoque más directo, sobre el cual escribí en un blog en Presentation Model Sin INotifyPropertyChanged . Usando una alternativa al enlace de datos, puede enlazar directamente a las propiedades CLR sin ningún código de contabilidad. Simplemente escribe código .NET simple en su Modelo de vista, y se actualiza cuando cambia su Modelo de datos.
fuente
INotifyPropertyChanged
,PropertyDescriptor
se utilizan, lo que provoca pérdidas de memoriaSolo hay una cosa por la que preferir un
DependencyObject
: el enlace funcionará mejor. Simplemente pruebe un ejemplo con unaListBox
yTextBox
, complete la lista con los datos de laINotifyPropertyChanged
propiedadDependencyProperty
y edite el elemento actual desdeTextBox
...fuente
Si desea exponer las propiedades a otros controles, debe usar las propiedades de dependencia ... Pero buena suerte porque tardan un tiempo en darse cuenta ...
fuente