it-swarm.com.de

Ein Ereignis auslösen, wenn sich der Wert einer Immobilie ändert?

Es gibt eine Eigenschaft mit dem Namen ImageFullPath1

public string ImageFullPath1 {get; set; }

Ich werde ein Ereignis auslösen, wenn sich sein Wert geändert hat. Ich bin mir bewusst, dass ich INotifyPropertyChanged ändere, aber ich möchte es mit Ereignissen tun.

61
Mohammad Dayyan

Die Schnittstelle INotifyPropertyChanged ist mit Ereignissen implementiert . Die Schnittstelle hat nur ein Mitglied, PropertyChanged. Dies ist ein Ereignis, das Verbraucher abonnieren können.

Die Version, die Richard gepostet hat, ist nicht sicher. So implementieren Sie diese Schnittstelle sicher:

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;
}

Beachten Sie, dass dies die folgenden Dinge bewirkt:

  • Fasst die Benachrichtigungsmethoden für Eigenschaftsänderungen zusammen, sodass Sie diese problemlos auf andere Eigenschaften anwenden können.

  • Erstellt eine Kopie des PropertyChanged-Delegaten , bevor versucht wird, ihn aufzurufen (andernfalls wird eine Race-Bedingung erstellt).

  • Implementiert die Schnittstelle INotifyPropertyChanged korrekt.

Wenn Sie zusätzlich eine Benachrichtigung für eine zu ändernde spezifische Eigenschaft erstellen möchten, können Sie den folgenden Code hinzufügen:

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

public event EventHandler ImageFullPathChanged;

Fügen Sie dann die Zeile OnImageFullPathChanged(EventArgs.Empty) nach der Zeile OnPropertyChanged("ImageFullPath") ein.

Seit .Net 4.5 gibt es das CallerMemberAttribute , mit dem die fest codierte Zeichenfolge für den Eigenschaftsnamen im Quellcode entfernt werden kann:

    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();
            }
        }
    }
149
Aaronaught

Ich verwende im Wesentlichen die gleichen Muster wie Aaronaught, aber wenn Sie viele Eigenschaften haben, kann es hilfreich sein, ein wenig generische Methodenmagie zu verwenden, um Ihren Code ein wenig trockener zu machen [~ # ~] [~ # ~]

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<T>(string propertyName, ref T field, T newValue) {
        if(!EqualityComparer<T>.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
}

Normalerweise mache ich die OnPropertyChanged-Methode auch virtuell, damit Unterklassen sie überschreiben können, um Eigenschaftsänderungen zu erfassen.

34
Mikael Sundberg

Ein Ereignis auslösen, wenn sich eine Eigenschaft ändert, ist genau das, was INotifyPropertyChanged tut. Es gibt ein erforderliches Mitglied, um INotifyPropertyChanged zu implementieren, und das ist das PropertyChanged-Ereignis. Alles, was Sie selbst implementiert haben, ist wahrscheinlich identisch mit dieser Implementierung. Es ist also kein Vorteil, es nicht zu verwenden.

7
Ryan Brunner
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*/);
    }
}                        

Trotzdem stimme ich Ryan voll und ganz zu. In diesem Szenario ist genau deshalb INotifyPropertyChanged vorhanden.

5
Richard Berg

Wenn Sie Ihre Eigenschaft ändern, um ein Hintergrundfeld (anstelle einer automatischen Eigenschaft) zu verwenden, können Sie Folgendes tun:

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);
    }
  }
}
4
Oded