tutorial curso beginner c# silverlight mvvm domain-driven-design prism

c# - curso - MVVM: modelo modificado, ¿cómo actualizar correctamente ViewModel y View?



mvvm en ios (2)

Cuando la vista se une directamente al modelo, está mezclando código de UI y código de datos. El objetivo de MVVM es separar estos dos dominios de código. Para eso está el ViewModel.

El modelo de vista debe tener sus propias propiedades a las que la vista se pueda vincular. Un ejemplo:

class PersonViewModel { private Person OriginalModel { get; set; } public ValueViewModel<string> Name { get; set; } public ValueViewModel<int> Postcode { get; set; } protected void ReadFromModel(Person person) { OriginalModel = person; Name.Value = OriginalModel.Name; Postcode.Value = OriginalModel.Postcode; } protected Person WriteToModel() { OriginalModel.Name = Name.Value; //... return OriginalModel; } }

El uso de dicho ViewModel-design realmente separa sus objetos de datos de su código de interfaz de usuario. Cuando la clase Persona cambia, la IU no necesita estar en forma, porque ViewModel los separa.

Ahora a tu pregunta. Como puede ver en el ejemplo anterior, utilicé un ValueViewModel<T> genérico ValueViewModel<T> . Esta clase implementa INotifyPropertyChanged (y algunas otras cosas). Pero cuando recibe una nueva Persona, solo tiene que llamar a ReadFromModel(newPerson) en su ViewModel para actualizar la UI, porque ValueViewModels a la que se vincula la Vista informará a la UI cuando cambie su valor.

Aquí un ejemplo extremadamente simplificado de la estructura interna de ValueViewModel :

class ValueViewModel<T> : INotifyPropertyChanged { private T _value; public T Value { get { return _value;} set { _value = value; RaisePropertyChanged("Value"); } } }

Este es un enfoque que utilizamos en nuestra biblioteca MVVM. Tiene la ventaja de que obliga al desarrollador a separar claramente su código de las preocupaciones de los diseñadores. Y como efecto colateral, genera un diseño de código estandarizado en todas sus Vistas y Modelos de Vista y, por lo tanto, mejora la calidad del código.

Caso

Supongamos que tengo una clase Person , un PersonViewModel y una PersonView .

La actualización de las propiedades desde PersonView al modelo Person es bastante simple. PersonViewModel contiene un objeto Person y tiene propiedades públicas a las que se une PersonView para actualizar el modelo de Person.

Sin embargo.

Imagine que el modelo de Person puede ser actualizado por el Service . Ahora el cambio de propiedad necesita ser comunicado a PersonViewModel y luego a PersonView .

Así es como lo arreglaría:

Para cada propiedad en el modelo Person , plantearía el evento PropertyChanged. PersonViewModel suscribe al evento PropertyChanged de Person . PersonViewModel luego levantaría otro PropertyChanged para actualizar el PersonView .

Esto para mí parece ser la manera más obvia, pero quiero lanzar esta pregunta con la esperanza de que alguien me muestre una manera más agradable. ¿Es realmente así de simple o hay mejores formas de marcar el modelo como modificado y actualizar las propiedades respectivas en el modelo de vista?

Adiciones

El DataContext de PersonViewModel es PersonViewModel . Person se completa desde JSON y se actualiza muchas veces durante su vida útil.

Siéntase libre de sugerir cambios arquitectónicos para mi caso particular.

Responder

Marqué aqwert como la respuesta a mi pregunta, ya que me proporcionó una alternativa a la solución que ya propuse.


Si la vista se vincula al Modelo directamente, siempre que el servicio esté utilizando la misma instancia, cualquier cambio en las propiedades del modelo se propagará a la vista.

Sin embargo, si está recreando un nuevo modelo en el servicio, le dará al modelo de vista el nuevo modelo. Espero ver el modelo como una propiedad en el modelo de vista, por lo que cuando establezca esa propiedad, se debe alertar a todos los enlaces del cambio.

//in the ViewModel public Person Model { get { return _person; } set { _person = value; RaisePropertyChanged("Model"); //<- this should tell the view to update } }

EDITAR:

Como ViewModel hay una lógica de ViewModel específica, puede adaptar esas propiedades en el ViewModel

private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e) { if(e.PropertyName == "Prop1") RaisePropertyChanged("SpecicalProperty"); ... } public string SpecicalProperty { get { reutrn Model.Prop1 + " some additional logic for the view"; } }

EN XAML

<TextBlock Text="{Binding Model.PropertyDirect}" /> <TextBlock Text="{Binding SpecicalProperty}" />

De esta forma, solo las propiedades Model y ViewModel están vinculadas a la vista sin duplicar los datos.

Puede obtener más fantasía creando un ayudante para vincular los cambios de propiedad del modelo al modelo de vista o usar un diccionario de asignación

_mapping.Add("Prop1", new string[] { "SpecicalProperty", "SpecicalProperty2" });

y luego encuentre las propiedades para actualizar obteniendo la lista de propiedades

private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e) { string[] props; if(_mapping.TryGetValue(e.PropertyName, out props)) { foreach(var prop in props) RaisePropertyChanged(prop); } }