2012-06-18 13 views
6

Ich finde, dass ich mich viel wiederhole und das ist natürlich nicht gut. Also habe ich mich gefragt, ob ich etwas dagegen tun könnte. Dies ist eine gemeinsame Code in meinem WPF-Anwendung:Wrapping der Eigenschaft Setzer

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

Also habe ich mich gefragt, ob ich irgendwie die Setter wickeln könnte, um es besser und besser lesbar zu machen. Eine Idee war so etwas wie dieses:

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

Verwendung wie folgt aus:

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

Aber ich bin nicht sicher, ob das wirklich klug ist oder wäre auch mit Werttypen arbeiten?

Ich denke, ich bin nicht der erste, der so etwas versucht, also wenn jemand einen guten, narrensicheren Weg zu so etwas kennt, bitte hereinklingeln. Ich denke, ich konnte die Eigenschaft nicht ändern, ohne Reflektion, aber irgendwelche Ideen würde auch helfen.

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

Edit::

+2

Überprüfen Sie ReactiveUI für dieses Verhalten, wenn Sie es nicht verwenden möchten, dann können Sie es vielleicht kopieren. http://www.reactiveui.net/ z.B. 'set {this.RaiseAndSetIfChanged (x => x.PasswordConfirmation, Wert); } ' –

+1

Fügen Sie' ref' zu Ihrem Eigenschaftsparameter hinzu und es wird auch für ValueTypes funktionieren. – SimpleVar

Antwort

2

Ja von dieser OservableObject Klasse erben müssen - das ist völlig akzeptabel und normaler Code.

Hier ist ein Beispiel, das ich ziemlich standardisiert gefunden habe (ich sehe eine Menge dieser Art der Verwendung in Codebeispielen).

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 dieser Code innerhalb einer Klasse, die INotifyPropertyChanged implementiert, und Ihre Daten Objekte dieser Klasse erben. In Ihrem Beispiel rufen Sie das Ereignis direkt auf - machen Sie das nie. Sie können die Ereignisreferenz vom Start der Methode bis zum Zeitpunkt des Aufrufs des Ereignisses verlieren. Immer Erstellen Sie einen lokalen Cache des Ereignisses, bevor Sie es aufrufen.

+0

Ja meine OnPropertyChanged-Methoden umschließt das Erstellen eines lokalen Copy-Handlers. Danke, verpasste das Ref-Keyword. –

2

könnte man vielleicht

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 
} 

Usage Hilfe Ihre Klasse

+1

Rufen Sie niemals 'PropertyChanged' direkt auf - es gibt Race-Bedingungen, die dazu führen, dass dies fehlschlägt. Erstellen Sie stattdessen immer eine lokale Kopie und rufen Sie diese stattdessen auf. – qJake

+0

Hat die Reflection-Sache von memberExpression irgendwelche Nachteile, zum Beispiel in der Performance oder in der Situation, in der sie nicht funktionieren? –

+0

@ IngóVals Ich habe diese Klasse in zwei Projekten implementiert, die ich entwickelt habe, und bisher gab es kein Problem – Dante