Saltar al contenido

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

Siéntete libre de divulgar nuestra página y códigos con tus amigos, danos de tu ayuda para hacer crecer esta comunidad.

Solución:

Cuando la vista se vincula directamente con el modelo (que también es el caso cuando ViewModel expone el modelo), está mezclando código de interfaz de usuario 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 puede enlazar. Un ejemplo:

class PersonViewModel

    private Person OriginalModel  get; set; 

    public ValueViewModel Name  get; set; 
    public ValueViewModel 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 un diseño ViewModel de este tipo realmente separa sus objetos de datos de su código de interfaz de usuario. Cuando se cambia la estructura de la clase Person, la interfaz de usuario no necesita ajustarse en consecuencia, porque ViewModel los separa entre sí.

Ahora a tu pregunta. Como puede ver en el ejemplo anterior, utilicé un genérico ValueViewModel. Esta clase implementa INotifyPropertyChanged (y algunas otras cosas). Cuando recibes un nuevo Person ejemplo, solo tienes que llamar ReadFromModel(newPerson) en su ViewModel para actualizar la interfaz de usuario, porque los ValueViewModels a los que se vincula la vista informarán a la interfaz de usuario cuando cambie su valor.

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

class ValueViewModel : INotifyPropertyChanged

    private T _value;
    public T Value 
    
        get  return _value;
        set
        
            _value = value;
            RaisePropertyChanged("Value");
        
    

Este es un enfoque que usamos en nuestra biblioteca MVVM. Tiene la ventaja de que obliga al desarrollador a separar claramente el código de las preocupaciones de los diseñadores. Y, como efecto secundario, 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.

Si la vista se vincula directamente con el modelo, siempre que el servicio utilice 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 configura esa propiedad, todos los enlaces deben recibir una alerta del cambio.

//in the ViewModel
public Person Model

   get  return _person; 
   set  _person = value; 
         RaisePropertyChanged("Model");  //<- this should tell the view to update
        

EDITAR:

Ya que dices que hay específicos ViewModel lógica, entonces 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

    
  

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

Puede volverse más elegante creando un asistente para vincular los cambios de propiedad del modelo al modelo de vista o usar un diccionario de mapeo

 _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);
       
 

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *