¿Levanta un evento cada vez que cambia el valor de una propiedad?

Hay una propiedad, se llama ImageFullPath1

public string ImageFullPath1 {get; set; } 

Voy a disparar un evento cada vez que cambie su valor. Soy consciente de cambiar INotifyPropertyChanged , pero quiero hacerlo con eventos.

La interfaz INotifyPropertyChanged se implementa con eventos. La interfaz tiene solo un miembro, PropertyChanged , que es un evento al que los consumidores pueden suscribirse.

La versión que Richard publicó no es segura. Aquí es cómo implementar de forma segura esta interfaz:

 public class MyClass : INotifyPropertyChanged { private string imageFullPath; protected void OnPropertyChanged(PropertyChangedEventArgs e) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, e); } protected void OnPropertyChanged(string propertyName) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } public string ImageFullPath { get { return imageFullPath; } set { if (value != imageFullPath) { imageFullPath = value; OnPropertyChanged("ImageFullPath"); } } } public event PropertyChangedEventHandler PropertyChanged; } 

Tenga en cuenta que esto hace lo siguiente:

  • Resume los métodos de notificación de cambio de propiedad para que pueda aplicar esto fácilmente a otras propiedades;

  • Hace una copia del delegado PropertyChanged antes de intentar invocarlo (si no lo hace se creará una condición de carrera).

  • Implementa correctamente la interfaz INotifyPropertyChanged .

Si además desea crear una notificación para una propiedad específica que se está modificando, puede agregar el siguiente código:

 protected void OnImageFullPathChanged(EventArgs e) { EventHandler handler = ImageFullPathChanged; if (handler != null) handler(this, e); } public event EventHandler ImageFullPathChanged; 

A continuación, agregue la línea OnImageFullPathChanged(EventArgs.Empty) después de la línea OnPropertyChanged("ImageFullPath") .

Como tenemos .Net 4.5 existe el CallerMemberAttribute , que permite deshacerse de la cadena codificada para el nombre de la propiedad en el código fuente:

  protected void OnPropertyChanged( [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } public string ImageFullPath { get { return imageFullPath; } set { if (value != imageFullPath) { imageFullPath = value; OnPropertyChanged(); } } } 

Uso principalmente los mismos patrones que Aaronaught, pero si tienes muchas propiedades, sería bueno usar un poco de magia genérica para hacer que tu código sea un poco más DRY.

 public class TheClass : INotifyPropertyChanged { private int _property1; private string _property2; private double _property3; protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { PropertyChangedEventHandler handler = PropertyChanged; if(handler != null) { handler(this, e); } } protected void SetPropertyField(string propertyName, ref T field, T newValue) { if(!EqualityComparer.Default.Equals(field, newValue)) { field = newValue; OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } } public int Property1 { get { return _property1; } set { SetPropertyField("Property1", ref _property1, value); } } public string Property2 { get { return _property2; } set { SetPropertyField("Property2", ref _property2, value); } } public double Property3 { get { return _property3; } set { SetPropertyField("Property3", ref _property3, value); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion } 

Por lo general, también hago que el método OnPropertyChanged sea virtual para permitir que las subclases lo anulen para detectar cambios de propiedad.

Criar un evento cuando una propiedad cambia es precisamente lo que INotifyPropertyChanged hace. Hay un miembro requerido para implementar INotifyPropertyChanged y ese es el evento PropertyChanged. Cualquier cosa que implemente usted mismo probablemente sea idéntica a esa implementación, por lo que no hay ventaja de no usarla.

 public event EventHandler ImageFullPath1Changed; public string ImageFullPath1 { get { // insert getter logic } set { // insert setter logic // EDIT -- this example is not thread safe -- do not use in production code if (ImageFullPath1Changed != null && value != _backingField) ImageFullPath1Changed(this, new EventArgs(/*whatever*/); } } 

Dicho eso, estoy completamente de acuerdo con Ryan. Este escenario es precisamente por qué existe INotifyPropertyChanged.

Si cambia su propiedad para usar un campo de respaldo (en lugar de una propiedad automática), puede hacer lo siguiente:

 public event EventHandler ImageFullPath1Changed; private string _imageFullPath1 = string.Empty; public string ImageFullPath1 { get { return imageFullPath1 ; } set { if (_imageFullPath1 != value) { _imageFullPath1 = value; EventHandler handler = ImageFullPathChanged; if (handler != null) handler(this, e); } } }