c# - instancelocator - xamarin stacklayout content binding
En MVVM ¿debería ViewModel o Model implementar INotifyPropertyChanged? (15)
Creo que MVVM tiene un nombre muy pobre y al llamar a ViewModel un ViewModel hace que muchos pierdan una característica importante de una arquitectura bien diseñada, que es un DataController que controla los datos sin importar quién esté tratando de tocarlos.
Si considera el Modelo de Vista como más un Controlador de Datos e implementa una arquitectura donde su DataController es el único elemento que toca los datos, entonces nunca tocará los datos directamente, pero siempre usará el Controlador de Datos. DataController es útil para la interfaz de usuario, pero no necesariamente solo para la interfaz de usuario. Es para capa empresarial, capa UI, etc.
DataModel -------- DataController ------ View
/
Business --------/
Terminas con un modelo como este. Incluso la empresa solo debe tocar los datos usando ViewModel. Entonces tu acertijo simplemente desaparece.
La mayoría de los ejemplos de MVVM que he trabajado han hecho que el Modelo implemente INotifyPropertyChanged, pero en el ejemplo CommandSink de Josh Smith, ViewModel implementa INotifyPropertyChanged .
Todavía estoy recopilando cognitivamente los conceptos de MVVM, por lo que no sé si:
- tienes que poner INotifyPropertyChanged en ViewModel para que CommandSink funcione
- esto es solo una aberración de la norma y en realidad no importa
- siempre debe hacer que el Modelo implemente INotifyPropertyChanged y esto es solo un error que se corregirá si se desarrolla desde un ejemplo de código a una aplicación
¿Cuáles han sido las experiencias de otros en los proyectos de MVVM en los que ha trabajado?
Creo que la respuesta es bastante clara si deseas adherirte al MV-VM.
ver: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx
En el patrón MVVM, la vista encapsula la IU y cualquier lógica de IU, el modelo de vista encapsula la lógica y el estado de la presentación, y el modelo encapsula la lógica y los datos de la empresa.
"La vista interactúa con el modelo de vista mediante el enlace de datos, los comandos y los eventos de notificación de cambio. El modelo de vista consulta, observa y coordina las actualizaciones del modelo, convirtiendo, validando y agregando datos según sea necesario para visualizarlos en la vista".
Creo que todo depende del caso de uso.
Cuando tiene un modelo simple con muchas propiedades, puede hacer que implemente INPC. Por simple quiero decir que este modelo se parece más a un POCO .
Si su modelo es más complejo y vive en un dominio de modelo interactivo (modelos que hacen referencia a modelos, suscribirse a eventos de otros modelos), tener eventos modelo implementados como INPC es una pesadilla.
Póngase en una posición de entidad modelo que tenga que colaborar con otros modelos. Tienes varios eventos para suscribirte. Todos ellos se implementan como INPC. Imagina esos manejadores de eventos que tienes. Una enorme cascada de cláusulas if y / o clausses de cambio.
Otro problema con INPC. Debe diseñar sus aplicaciones para que dependan de la abstracción, no de la implementación. Esto se hace típicamente usando interfaces.
Echemos un vistazo a 2 implementaciones diferentes de la misma abstracción:
public class ConnectionStateChangedEventArgs : EventArgs
{
public bool IsConnected {get;set;}
}
interface IConnectionManagerINPC : INotifyPropertyChanged
{
string Name {get;}
int ConnectionsLimit {get;}
/*
A few more properties
*/
bool IsConnected {get;}
}
interface IConnectionManager
{
string Name {get;}
int ConnectionsLimit {get;}
/*
A few more properties
*/
event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;
bool IsConnected {get;}
}
Ahora mira a los dos. ¿Qué le dice IConnectionManagerINPC? Que algunas de sus propiedades pueden cambiar. Tú no sabes cuál de ellos. De hecho, el diseño es que solo los cambios IsConnected, ya que el resto son de solo lectura.
Por el contrario, las intenciones de IConnectionManager son claras: "Puedo decirte que el valor de mi propiedad IsConnected puede cambiar".
Depende de cómo hayas implementado tu modelo. Mi empresa utiliza objetos comerciales similares a los objetos CSLA de Lhotka y hace un uso extenso de INotifyPropertyChanged en todo el modelo comercial.
Nuestro motor de validación depende en gran medida de que se notifique que las propiedades cambian a través de este mecanismo y funciona muy bien. Obviamente, si está utilizando una implementación diferente a los objetos comerciales donde la notificación de cambios no es tan crítica para la operación, es posible que tenga otros métodos para detectar cambios en su modelo comercial.
También tenemos Modelos de Vista que propagan los cambios desde el Modelo donde sea necesario, pero los Modelos de Vista mismos están escuchando los cambios del Modelo subyacente.
En MV-VM, ViewModel siempre (Model not always) implementa INotifyPropertyChanged
Consulte la plantilla / kit de herramientas de proyecto MV-VM en http://blogs.msdn.com/llobo/archive/2009/05/01/download-m-v-vm-project-template-toolkit.aspx . Utiliza DelegateCommand
para comandar y debería ser una excelente plantilla de inicio para tus proyectos MV-VM.
En mi opinión, el modelo de vista implementa INotifyPropertyChange
y el modelo podría usar la notificación en un "nivel" diferente.
Por ejemplo, con algún servicio de documentos y un objeto de documento tiene un evento documentChanged que un modelo de vista escucha para borrar y reconstruir la vista. En el modelo de vista de edición, tiene un cambio de propiedad para las propiedades del documento para admitir las vistas. Si el servicio hace mucho con el documento al guardar (actualizar la fecha de cambio, el último usuario, etc.) es fácil obtener una sobrecarga de eventos modificados por Iproperty y basta con un documento modificado.
Pero si utiliza INotifyPropertyChange
en su modelo, creo que es una buena práctica retransmitirlo en su modelo de vista en lugar de suscribirse directamente en su vista. En ese caso, cuando los eventos cambian en su modelo, solo tiene que cambiar el modelo de vista y la vista permanece intacta.
Estoy de acuerdo con la respuesta de Paulo, implementar INotifyPropertyChanged
in Models es totalmente aceptable e incluso es sugerido por Microsoft -
Normalmente, el modelo implementa las instalaciones que facilitan el enlace a la vista. Esto generalmente significa que es compatible con la propiedad y la notificación de cambio de colección a través de las interfaces
INotifyPropertyChanged
eINotifyCollectionChanged
. Las clases de modelos que representan colecciones de objetos normalmente se derivan de la claseObservableCollection<T>
, que proporciona una implementación de la interfazINotifyCollectionChanged
.
Aunque depende de usted decidir si desea ese tipo de implementación o no, pero recuerde:
¿Qué sucede si las clases de su modelo no implementan las interfaces requeridas?
A veces necesitará trabajar con objetos modelo que no implementen las
INotifyPropertyChanged
,INotifyCollectionChanged
,IDataErrorInfo
oINotifyDataErrorInfo
. En esos casos, el modelo de vista puede necesitar envolver los objetos modelo y exponer las propiedades requeridas a la vista. Los valores de estas propiedades serán proporcionados directamente por los objetos modelo. El modelo de vista implementará las interfaces necesarias para las propiedades que expone, de modo que la vista pueda vincular datos fácilmente.
Tomado de - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx
He trabajado en algunos proyectos donde no hemos implementado INotifyPropertyChanged
en nuestros modelos y debido a esto enfrentamos muchos problemas; la duplicación innecesaria de propiedades era necesaria en VM y al mismo tiempo tuvimos que actualizar el objeto subyacente (con valores actualizados) antes de pasarlos a BL / DL.
Te enfrentarás a problemas especialmente si necesitas trabajar con la colección de tus objetos modelo (por ejemplo, en una grilla o lista editable) o modelos complejos; los objetos modelo no se actualizarán automáticamente y tendrás que administrar todo eso en tu máquina virtual.
Originalmente respondida en otra pregunta similar, agregando aquí ya que contiene el imp. detalles que faltan en este hilo -
https://.com/a/6923833/45382
Estoy totalmente en desacuerdo con el concepto de que el Modelo no debe implementar INotifyPropertyChanged
. ¡Esta interfaz no es específica de UI! Simplemente informa de un cambio. De hecho, WPF usa esto en gran medida para identificar cambios, pero eso no significa que sea una interfaz de interfaz de usuario. Lo compararía con el siguiente comentario: " Un neumático es un accesorio de automóvil ". Claro que sí, pero las bicicletas, los autobuses, etc. también lo usan. En resumen, no tome esa interfaz como una cosa UI.
Dicho esto, no necesariamente significa que creo que el Modelo debería proporcionar notificaciones. De hecho, como regla general, el modelo no debería implementar esta interfaz, a menos que sea necesario. En la mayoría de los casos en que no se envían datos del servidor a la aplicación del cliente, el modelo puede estar obsoleto. Pero si escucho los datos del mercado financiero, entonces no veo por qué el modelo no puede implementar la interfaz. A modo de ejemplo, ¿qué ocurre si tengo una lógica que no es UI, como un servicio que cuando recibe un precio Bid o Ask para un valor determinado, emite una alerta (por ejemplo, a través de un correo electrónico) o realiza un pedido? Esta podría ser una posible solución limpia.
Sin embargo, hay diferentes formas de lograr las cosas, pero siempre argumentaré a favor de la simplicidad y evitaría la redundancia.
¿Qué es mejor? ¿Definir eventos en una colección o cambios de propiedad en el modelo de vista y propagarlo al modelo o hacer que la vista actualice intrínsecamente el modelo (a través del modelo de vista)?
En resumidas cuentas, cada vez que ve a alguien que afirma que " no puede hacer esto o aquello " es una señal de que no sabe de lo que está hablando.
Realmente depende de su caso y, de hecho, MVVM es un marco con muchos problemas y todavía no veo una implementación común de MVVM en todos los ámbitos.
Ojalá tuviera más tiempo para explicar los muchos sabores de MVVM y algunas soluciones a problemas comunes, principalmente proporcionados por otros desarrolladores, pero creo que tendré que hacerlo en otro momento.
Estoy usando la interfaz INotifyPropertyChange
en un modelo. En realidad, un cambio de propiedad modelo debe ser activado solo por la UI o el cliente externo.
He notado varias ventajas y desventajas:
Ventajas
Notificador está en el modelo de negocio
- Según el dominio impulsado, es correcto. Debe decidir cuándo aumentar y cuándo no.
Desventajas
El modelo tiene propiedades (cantidad, tasa, comisión, total). Totalfrieght se calcula utilizando cantidad, tasa, cambio de comisión.
Al cargar valores de db, el cálculo total de frieght se llama 3 veces (cantidad, tasa, comisión). Debería ser una vez
Si rate, qty se asigna en la capa de negocios, se llama de nuevo al notificador.
Debería haber una opción para desactivar esto, posiblemente en la clase base. Sin embargo, los desarrolladores podrían olvidarse de hacer esto.
Normalmente, ViewModel implementará INotifyPropertyChanged
. El modelo puede ser cualquier cosa (archivo xml, base de datos o incluso objeto). El modelo se usa para dar los datos al modelo de vista, que se propaga a la vista.
Pero a veces (como en este texto de enlace de presentación), el modelo es el servicio, que proporciona a la aplicación algunos datos en línea y luego necesita contratar notificación de que llegaron nuevos datos o que los datos han cambiado utilizando eventos ...
Solo use INotifyPropertyChange
en su viewmodel y no en el Modelo,
el modelo generalmente usa IDataErrorInfo
para manejar los errores de validación, así que simplemente manténgalo en su ViewModel y usted está en su camino de MVVM.
Supongamos que la referencia del objeto en su vista cambia. ¿Cómo notificará todas las propiedades que se actualizarán para mostrar los valores correctos? Llamar a OnPropertyChanged
en su vista para todas las propiedades del objeto es basura para mi punto de vista.
Entonces, lo que hago es dejar que el objeto notifique a alguien cuando cambia un valor en una propiedad, y en mi opinión utilizo enlaces como Object.Property1
, Object.Property2
y on. De esa manera, si solo quiero cambiar el objeto que se mantiene actualmente en mi vista, solo hago OnPropertyChanged("Object")
.
Para evitar cientos de notificaciones durante la carga de objetos, tengo un indicador booleano privado que establezco en verdadero durante la carga que se OnPropertyChanged
desde OnPropertyChanged
del objeto y no hace nada.
Yo diría en tu ViewModel. No es parte del Modelo ya que el Modelo es IU agnóstico. El Modelo debe ser ''todo EXCEPTO agnóstico del negocio''
Diría todo lo contrario, siempre pongo mi INotifyPropertyChanged
en mi ViewModel; realmente no quiere contaminar su modelo con una característica específica de WPF como INotifyPropertyChanged
, esas cosas deberían estar en el ViewModel.
Estoy seguro de que otros estarían en desacuerdo, pero así es como trabajo.