2012-05-04 7 views
8

Tal vez aquí ya es una pregunta, pero no lo encontré.¿Suscribirse a PropertyChanged o a una llamada de método de adición en setter?

Tengo la aplicación MVVM, y en mi ViewModel tengo que hacer algunas acciones adicionales sobre los cambios de algunas propiedades (por ejemplo, si View las cambia). ¿Qué enfoque es mejor en tu mente y por qué?

primero - Añadir AdditionalAction llamada a Setter

public class ViewModel: INotifyPropertyChanged 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 

     // --- ADDITIONAL CODE --- 
     AdditionalAction(); 
    } 
    } 
} 

segundo - Auto-suscribirse a INotifyPropertyChanged

public class ViewModel: INotifyPropertyChanged 
{ 
    public ViewModel() 
    { 
    // --- ADDITIONAL CODE --- 
    PropertyChanged += OnPropertyChanged; 
    } 

    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    void PropertyChanged(object sender, PropertyChangedEventArgs e) 
    { 
    // --- ADDITIONAL CODE --- 
    if (e.PropertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

Imagínese, que yo no tengo problema de rendimiento o 10'000 objetos Es solo View y ViewModel. ¿Qué es mejor? El primer código es "más pequeño" y tiene menos sobrecarga, pero el segundo (en mi opinión) es más claro y puedo usar fragmentos de código para el código de propiedades de autogeneración. Aún más - en el segundo caso Puedo escribir en el controlador de eventos algo como:

On.PropertyChanged(e, p => p.MyProperty, AdditionalAction); 

donde On es la clase-ayudante.

Entonces, ¿qué es lo que tiene en mente y por qué?

Actualizado:

OK, parece que he encontrado todavía un enfoque:

tercero - añadir "punto de extensión" en RaisePropertyChanged:

public class NotificationObject : INotifyPropertyChanged 
{ 
    void RaisePropertyChanged(Expression<...> property) 
    { 
    // ... Raise PropertyChanged event 
    if (PropertyChanged != null) 
     // blah-blah 

    // Call extension point 
    OnPropertyChanged(property.Name); 
    } 

    public virtual OnPropertyChanged(string propertyName) 
    { 
    } 
} 

public class ViewModel: NotificationObject 
{ 
    private int _MyProperty; 

    public int MyProperty 
    { 
    get { return _MyProperty; } 
    set 
    { 
     if (_MyProperty == value) return; 
     _MyProperty = value; 
     RaisePropertyChanged(() => MyProperty); 
    } 
    } 

    override OnPropertyChanged(string propertyName) 
    { 
    if (propertyName == "MyProperty") 
     AdditionalAction(); 
    } 
} 

esta manera no usamos evento, pero todas las "acciones adicionales" se invocan desde el mismo "punto de extensión". ¿Es mejor un "lugar para todas las acciones adicionales" que un "flujo de trabajo no transparente"?

+2

http://tergiver.wordpress.com/2011/01/20/self-subscription-is-asinine/ – Tergiver

+0

sidenote: considere el uso de un método de ayuda para poner las tres líneas en colocador de sus propiedades a uno, devolviendo un booleano si la propiedad cambió. Más corto y sin duplicación. ej. 'if (RaisePropertyChanged (ref _MyProperty, value, o => o.MyProperty)) AdditionalAction();' – stijn

+0

@Tergiver ¿Cuál es la diferencia entre tu camino y mi 2da manera? Son lo mismo: escribe código adicional no en el "setter" pero en el "controlador de eventos". El método 'OnXXX' desde este punto de vista es lo mismo que la auto-suscripción al evento. Entonces, desde su punto de vista, mi pregunta es: "¿Es mejor llamar a 'AdditionalAction' desde setter o desde el método OnPropertyChanged?" (incluso si no hay un método OnPropertyChanged en realidad) – chopikadze

Respuesta

3

Me definitivamente ir a por el primer método:

  • Está claro
  • es explícita en su flujo y la intención
  • Evita raro (OMI) de suscripción auto

Los "beneficios" de la segunda opción, que le permite usar propiedades autogeneradas, no justifican la claridad del flujo de ejecución del primer caso, imo.

Espero que esto ayude.

+0

¿qué opinas sobre 3rd way? – chopikadze

+0

@chopikadze: parece bueno, porque * podría * admitir la refactorización del código, si se deshace de la cadena: propertyName de alguna manera. – Tigran

3

Aquí está el patrón "habitual". Esto le permite poner código específico de propiedad dentro del método OnX y permite que las clases derivadas hagan lo mismo. No hay necesidad de una declaración de cambio grande, a menos que, por supuesto, seas el oyente externo, pero eso es parte del curso de INotifyPropertyChanged.

public class NotificationObject : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void FirePropertyChanged(PropertyChangedEventArgs e) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
      handler(this, e); 
    } 
} 

public class ViewModel : NotificationObject 
{ 
    private int _MyProperty1; 
    public int MyProperty1 
    { 
     get { return _MyProperty1; } 
     set 
     { 
      if (value != _MyProperty1) 
      { 
       _MyProperty1 = value; 
       OnMyProperty1Changed(new PropertyChangedEventArgs("MyProperty1")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty1Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 

    private int _MyProperty2; 
    public int MyProperty2 
    { 
     get { return _MyProperty2; } 
     set 
     { 
      if (value != _MyProperty2) 
      { 
       _MyProperty2 = value; 
       OnMyProperty2Changed(new PropertyChangedEventArgs("MyProperty2")); 
      } 
     } 
    } 

    protected virtual void OnMyProperty2Changed(PropertyChangedEventArgs e) 
    { 
     FirePropertyChanged(e); 
    } 
} 
+0

Muchas gracias por su ayuda, marqué la respuesta de @Tigran solo porque tiene más votos, ¡pero realmente aprecio nuestra discusión! – chopikadze

Cuestiones relacionadas