INotifyPropertyChanged vs. DependencyProperty en ViewModel

Al implementar ViewModel en una aplicación WPF de la architecture Model-View-ViewModel, parece haber dos opciones principales para hacer que sea un archivo de datos. He visto implementaciones que usan DependencyProperty para las propiedades a las que la Vista se va a vincular y he visto el ViewModel implementando INotifyPropertyChanged en 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?

Kent escribió un blog interesante sobre este tema: Modelos de vista: POCOs versus DependencyObjects .

Breve resumen:

  1. DependencyObjects no están marcados como serializables
  2. La clase DependencyObject anula y sella los métodos Equals () y GetHashCode ()
  3. Un DependencyObject tiene afinidad por el hilo: solo se puede acceder a él en el hilo en el que se creó

Prefiero el enfoque POCO. Una clase base para PresentationModel (también conocido como ViewModel) que implementa la interfaz INotifyPropertyChanged se puede encontrar aquí: http://compositeextensions.codeplex.com

De acuerdo con 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

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 quieres una buena separación, DP funcionará para ti.

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 los requisitos de nuestro negocio. También hay un costo mayor para DP que un INotifyPropertyChanged. Cuando diseña WPF / Silverlight intente diseñar UI y ViewModel totalmente separados para que en cualquier momento podamos cambiar los controles de diseño y UI (según el tema y los estilos)

Consulte también esta publicación: https://stackoverflow.com/questions/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.

Desde el punto de vista de la expresividad, disfruto mucho el uso de propiedades de dependencia y me estremezco ante la idea de INotifyPropertyChanged . Además de los nombres de propiedad de string 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, hazlo” usando metadatos estáticos fácilmente entendibles. Es un enfoque declarativo que obtiene mi voto por elegancia.

INotifyPropertyChanged cuando se usa también le brinda la capacidad de agregar más lógica en el código de sus captadores y sus propiedades.

Ejemplo de DependencyProperty :

 public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) ); public String Name { set { SetValue( NameProperty, value ); } get { return ( String ) GetValue( NameProperty ); } } 

En su getter y setter — todo lo que puede hacer es simplemente llamar a SetValue y GetValue respectivamente, b / c en otras partes del framework no se llama al getter / setter, sino que directamente llama a SetValue, GetValue, por lo que su lógica de propiedad no confiablemente ejecutado.

Con INotifyPropertyChanged , define un evento:

 public event PropertyChangedEventHandler PropertyChanged; 

Y luego simplemente tenga cualquier lógica en cualquier parte de su código, luego llame:

 // ... // Something cool... // ... if( this.PropertyChanged != null ) { PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) ); } // More cool stuff that will reliably happen... 

Esto podría estar en un getter / setter, o en cualquier otro lugar.

Las propiedades de dependencia están pensadas para admitir el enlace (como un objective) en elementos de IU, no como una fuente para el enlace de datos, aquí es donde entra en juego 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 destino de un enlace, la propiedad debe ser un Para que un enlace de ida o de dos vías sea efectivo, la propiedad de origen debe admitir notificaciones de cambio que se propagan al sistema de enlace y, por lo tanto, al destino. Para las fonts de enlace de CLR personalizadas, esto significa que la propiedad debe admitir INotifyPropertyChanged. Las colecciones deben ser compatibles con INotifyCollectionChanged “.

Todos los objetos de dependencia no pueden ser serializados (Esto podría dificultar el uso de ViewModels y DTO (POCO) ‘s.

Existen 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

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 unir mi GUI a un marco de lógica empresarial existente sin duplicar el estado. El marco que estaba usando tenía su propio patrón de observador y era fácil pasar un nivel de notificación al siguiente. Simplemente tuve una clase que implementó la interfaz del observador desde mi marco lógico comercial y la interfaz INotifyPropertyChanged.

Con DP no puede definir el backend que almacena el estado usted mismo. Hubiera tenido que dejar .net cache una copia de cada elemento del estado al que me estaba ligando. Esto parecía una sobrecarga innecesaria: mi estado es grande y complicado.

Así que aquí encontré INotifyPropertyChanged mejor para exponer las propiedades de la lógica empresarial a la GUI.

Dicho esto, cuando necesitaba un widget GUI personalizado para exponer una propiedad y para que los cambios en esa propiedad afectaran a otros widgets de GUI, DP demostró ser la solución más simple.

Entonces, descubrí que DP es útil para la GUI a la notificación de GUI.

¿Es realmente una buena idea dar las dependencias de ViewModel a WPF?

.NET 4.0 tendrá System.Xaml.dll, por lo que no tendrá que tomar una dependencia 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 UI.

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 ellos.

XAML y todo el sistema de dependencia se implementaron como stacks separadas para WF y WPF, probablemente para aprovechar la experiencia de diferentes equipos sin crear una dependencia (sin juego de palabras) entre ellos.

Parece que las Propiedades de dependencia se deben usar en los controles que crees, 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 es mejor utilizando INotifyPropertyChanged. Usar INotifyPropertyChanged le dará la posibilidad de tener lógica get / setter si es necesario.

Recomiendo ver 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.

Creo que DependencyProperty e INotifyPropertyChanged se utilizan para dos cosas diferentes en Binding: la primera para permitir que una propiedad sea un destino de un enlace y recibir la entrada de otra propiedad (use {Binding …} para establecer la propiedad), el último cuando desee utilizar el valor de una propiedad como fuente de un enlace (nombre en la Expresión de ruta de enlace). Entonces la elección es meramente técnica.

Las propiedades de dependencia son el pegamento de la creación de control personalizado. 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 el momento del diseño.

Prefiero un enfoque más directo, del que publiqué en Blogger en Presentation Model Without INotifyPropertyChanged . Al usar una alternativa al enlace de datos, puede enlazar directamente a las propiedades de 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.

Solo hay una cosa por la que preferir un DependencyObject : el enlace funcionará mejor. Simplemente pruebe un ejemplo con un ListBox y TextBox , INotifyPropertyChanged lista con datos de la propiedad INotifyPropertyChanged vs. DependencyProperty y edite el elemento actual desde TextBox

Si quieres exponer propiedades a otros controles, debes usar las propiedades de Dependencia … Pero buena suerte, ya que tardan un poco en descubrir …