INotifyPropertyChanged vs DependencyProperty en ViewModel


Al implementar el ViewModel en una aplicación WPF de arquitectura Model-View-ViewModel, parece haber dos opciones principales para hacerlo databindable. He visto implementaciones que usan DependencyProperty para propiedades contra las que se va a enlazar la vista y he visto el ViewModel implementando INotifyPropertyChanged en su lugar.

Mi pregunta es ¿cuándo debo preferir uno sobre el otro? ¿Hay alguna diferencia de rendimiento? ¿Es realmente una buena idea dar las dependencias ViewModel a WPF? ¿Qué más hacer Necesito considerar cuándo tomar la decisión de diseño?

Author: lokusking, 2008-11-15

14 answers

Kent escribió un blog interesante sobre este tema: Ver modelos: POCOs versus DependencyObjects .

Breve resumen:

  1. Los objetos de dependencia no están marcados como serializable
  2. La clase DependencyObject anula y sella los valores Equals () y GetHashCode () methods
  3. Un DependencyObject tiene afinidad de hilo – solo se puede acceder a él en el hilo en el que fue creado

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

 205
Author: jbe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-08 10:05:11

De acuerdo con la guía de rendimiento de WPF, DependencyObjects definitivamente funciona mejor que POCOs que implementan INotifyPropertyChanged:

Http://msdn.microsoft.com/en-us/library/bb613546.aspx

 36
Author: James Ashley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-03 16:45:21

La elección se basa totalmente en su lógica de negocio y el nivel de abstracción de la interfaz de usuario. Si usted no quiere una buena separación entonces DP trabajará para usted.

DependencyProperties será aplicable principalmente a nivel de VisualElements por lo que no será buena idea si creamos muchos DPs para cada uno de nuestros requisitos de negocio. También hay un costo mayor para DP que un INotifyPropertyChanged. Cuando diseñes un WPF/Silverlight intenta diseñar UI y ViewModel totalmente separados para que en cualquier momento podemos cambiar el Diseño y los controles de interfaz de usuario (Basado en tema y Estilos)

Consulte este post también - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel . El enlace tiene mucha referencia al patrón Modelo-Vista-Modelo de vista, que es muy relevante para esta discusión.

 26
Author: Jobi Joy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:51

Desde el punto de vista de la expresividad, disfruto mucho usando propiedades de dependencia y me encoge ante la idea de INotifyPropertyChanged. Aparte de los nombres de propiedad string y las posibles fugas 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, hacer eso" usando metadatos estáticos fáciles de entender. Es un enfoque declarativo que consigue mi voto a favor de la elegancia.

 19
Author: Bryan Watts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-15 23:41:22

INotifyPropertyChanged cuando se utiliza también le da la posibilidad de añadir más lógica en el código de sus getters y setter de sus propiedades.

DependencyProperty ejemplo:

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 llama directamente a setValue, getValue, por lo que su lógica de propiedades no se ejecutará de manera confiable.

Con INotifyPropertyChanged, define un evento:

public event PropertyChangedEventHandler PropertyChanged;

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

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

 16
Author: Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-25 13:38:53

Las propiedades de dependencia están destinadas a soportar el enlace (como destino) en los elementos de la interfaz de usuario, no como fuente para el enlace de datos, aquí es donde entra en juego INotifyProperty. Desde un punto de vista puro, no deberías usar DP en 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 una propiedad de dependencia. Para un solo sentido o para que el enlace bidireccional sea efectivo, la propiedad de origen 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 pueden ser serializados (esto podría obstaculizar el uso de ViewModels y DTO (POCO)'s.

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

 16
Author: Nick Hermans,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-09 10:07:49

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 de lógica empresarial existente sin duplicar el estado. El marco que estaba utilizando tenía su propio patrón de observador y era fácil reenviar un nivel de notificación al siguiente. Simplemente tenía una clase que implementaba la interfaz observer desde mi marco de lógica de negocio y el INotifyPropertyChanged interfaz.

Con DP no puede definir el backend que almacena el estado usted mismo. Habría tenido que dejar que. net almacenara en caché una copia de cada elemento de estado al que estaba enlazando. Esto parecía una sobrecarga innecesaria - mi estado es grande y complicado.

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

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

Así que allí encontré DP útil para la notificación GUI a GUI.

 7
Author: morechilli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-24 17:16:32

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

. NET 4.0 tendrá Sistema.XAML.dll, por lo que no tendrá que tomar una dependencia de un marco arbitrario para utilizarlo. Ver El post de Rob Relyea sobre su sesión de PDC.

Mi toma

XAML es un lenguaje para describir objetos, y WPF es un framework cuyos objetos descritos son elementos UI.

Su relación es similar a C#, un lenguaje para describir logic, y. NET, un framework 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 grandes candidatas para este paradigma, pero XAML existe independientemente de ellas.

XAML y todo el sistema de dependencias 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.

 6
Author: Bryan Watts,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-15 09:25:07

Parece que las propiedades de dependencia deben usarse en los controles que cree, como los Botones. Para usar propiedades en XAML y usar todas las características de WPF, esas propiedades deben tener Propiedades de dependencia.

Sin embargo, su ViewModel es mejor usar INotifyPropertyChanged. Usar INotifyPropertyChanged te dará la posibilidad de tener lógica getter/setter si lo necesitas.

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.

 4
Author: timothymcgrath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-25 01:59:11

Creo que DependencyProperty e INotifyPropertyChanged se usan para dos cosas diferentes en Binding : el primero para permitir que una propiedad sea un objetivo de un binding y reciba la entrada de otra propiedad (use {Binding ...} para establecer la propiedad), la última cuando desea que el valor de una propiedad se utilice como el origen de un enlace (nombre en la expresión de ruta de enlace). Así que la elección es meramente técnica.

 4
Author: Domnik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-02 18:37:07

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 propiedades en tiempo de diseño XAML, debe usar Propiedades de dependencia. INPC nunca mostrará una propiedad en la ventana de propiedades en el momento del diseño.

 4
Author: John Peters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-28 21:04:28

Prefiero un enfoque más directo, que escribí en el blog en Modelo de Presentación Sin INotifyPropertyChanged. Usando una alternativa al enlace de datos, puede enlazar directamente a las propiedades CLR sin ningún código de contabilidad. Simplemente escriba código. NET antiguo en su Modelo de vista y se actualizará cuando cambie su Modelo de datos.

 3
Author: Michael L Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-30 13:15:14

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

 3
Author: ramos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-26 06:24:28

Si desea exponer propiedades a otros controles, debe usar Propiedades de dependencia... Pero buena suerte porque tardan un tiempo en averiguarlo...

 1
Author: JWP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-03 21:05:21