2012-06-18 8 views
6

Me parece que me repito mucho y eso, por supuesto, no sirve. Entonces me pregunté si podría hacer algo al respecto. Se trata de un código común en mi aplicación WPF:Envolviendo el conjunto de propiedades

private string _name; 
public string Name 
{ 
    get { return _name; } 
    set 
    { 
     if (_name != value) 
     { 
      _name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 
} 

así que me preguntaba si podría envolver el colocador de alguna manera para que sea mejor y más fácil de leer. Una idea fue algo como esto:

protected void PropertySetter<T>(T property, T value, string name) 
{ 
    if (EqualityComparer<T>.Default.Equals(property, value)) 
    { 
     property = value; 
     OnPropertyChanged(name); 
    } 
} 

Uso de la siguiente manera:

private string _name2; 
public string Name2 
{ 
    get { return _name2; } 
    set 
    { 
     PropertySetter<string>(Name2, value, "Name2"); 
    } 
} 

, pero no estoy seguro de que esto es realmente inteligente o funcionaría, así como con tipos de valor?

Supongo que no soy el primero en probar algo como esto, así que si alguien conoce una buena manera infalible de algo como esto, por favor entre en escena. Creo que no pude hacer el propertyChanged typesafe sin reflexión pero con ideas también ayudaría

+2

Compruebe ReactiveUI para este comportamiento, si no desea utilizarlo, entonces usted podría ser capaz de copiarlo. http://www.reactiveui.net/ p. 'set {this.RaiseAndSetIfChanged (x => x.PasswordConfirmation, value); } ' –

+1

Agregue' ref' a su parámetro de propiedad y también funcionará para ValueTypes. – SimpleVar

Respuesta

2

Sí - esto es completamente de código aceptable y normal.

Aquí hay un ejemplo que encontré bastante normalizado (veo mucho de este tipo de uso en muestras de código).

public event PropertyChangedEventHandler PropertyChanged; 

private void SetProperty<T>(ref T field, T value, string name) 
{ 
    if (!EqualityComparer<T>.Default.Equals(field, value)) 
    { 
     field = value; 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 

Wrap este código dentro de una clase que implementa INotifyPropertyChanged, y heredar sus objetos de datos de esta clase.

En su ejemplo, usted está llamando al evento directamente - nunca lo haga. Puede perder la referencia de evento desde el momento en que se inicia el método hasta el momento en que llama al evento. Siempre crear un caché local del evento antes de invocarlo.

+0

Sí, mis métodos OnPropertyChanged envuelven la creación de un controlador de copia local. Gracias, te perdiste la palabra clave ref. –

2

Tal vez esto podría ayudarle a

public class ObservableObject : INotifyPropertyChanged 
{ 
    #region Events 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 

    #region Protected Methods 
    protected virtual void SetAndNotify<T>(ref T field, T value, Expression<Func<T>> property) 
    { 
     if (!object.ReferenceEquals(field, value)) 
     { 
      field = value; 
      this.OnPropertyChanged(property); 
     } 
    } 

    protected virtual void OnPropertyChanged<T>(Expression<Func<T>> changedProperty) 
    { 
     if (PropertyChanged != null) 
     { 
      string name = ((MemberExpression)changedProperty.Body).Member.Name; 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
} 

Uso:

private String _myField; 
    public String MyProperty 
    { 
     get 
     { return _myField; } 
     set 
     { SetAndNotify(ref _myField, value,() => MyProperty); } 
    } 

Editar: Su clase debe heredar de esta clase OservableObject

+1

Nunca llame directamente a 'PropertyChanged'; existen condiciones de carrera que harán que esto falle. En cambio, siempre crea una copia local e invoca eso en su lugar. – qJake

+0

¿Tiene algún inconveniente la reflexión memberExpression? ¿Desempeño por ejemplo, por ejemplo o situación en la que no funcionan? –

+0

@ IngóVals He implementado esta clase en dos proyectos que he desarrollado y hasta ahora no ha habido ningún problema – Dante

Cuestiones relacionadas