2012-06-18 14 views
6

Uważam, że powtarzam sobie dużo i to oczywiście nie jest dobre. Zastanawiałem się, czy mógłbym coś z tym zrobić. Jest to wspólny kod w mojej aplikacji WPF:Owijanie obiektu ustawiającego

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

Więc zastanawiałem się, czy mogę owinąć setter jakoś zrobić to lepiej i bardziej czytelny. Jednym z pomysłów było coś takiego:

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

Wykorzystanie tak:

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

Ale nie jestem pewien, że to jest naprawdę inteligentny i będzie działać również z typów wartości?

Domyślam się, że nie jestem pierwszym, który wypróbował coś takiego, więc jeśli ktoś zna dobry, niezawodny sposób na coś takiego, proszę zadzwoń. Sądzę, że nie mógłbym wprowadzić właściwości "Zmieniony rodzaj" bez refleksji, ale wszelkie pomysły również pomogłoby.

+2

Sprawdź ReactiveUI dla tego zachowania, jeśli nie chcesz go używać, możesz go skopiować. http://www.reactiveui.net/ np. 'set {this.RaiseAndSetIfChanged (x => x.PasswordConfirmation, value); } ' –

+1

Dodaj' ref' do parametru właściwości i będzie działać również dla ValueTypes. – SimpleVar

Odpowiedz

2

Tak - to jest całkowicie dopuszczalne i normalne kod.

Oto przykład, który stwierdziłem, że jest dość znormalizowany (widzę wiele tego rodzaju użycia w przykładach kodu).

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 to kod wewnątrz klasy, która implementuje INotifyPropertyChanged i dziedziczą swoje obiekty danych z tej klasy.

W tym przykładzie wywołujesz zdarzenie bezpośrednio - Nigdy tego nie rób. Możesz utracić odniesienie do zdarzenia od momentu rozpoczęcia metody do czasu wywołania zdarzenia. Zawsze utwórz lokalną pamięć podręczną zdarzenia przed jego wywołaniem.

+0

Tak, moje metody OnPropertyChanged spowodują utworzenie lokalnego programu obsługi kopiowania. Dziękujemy, przegapiłeś słowo kluczowe ref. –

2

Może to pomóc

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 
} 

Zastosowanie:

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

Edit: Twoja klasa musi dziedziczyć z tego OservableObject klasy

+1

Nigdy nie dzwoń bezpośrednio do 'PropertyChanged' - istnieją warunki wyścigu, które spowodują awarię. Zamiast tego zawsze twórz lokalną kopię i wywołuj ją. – qJake

+0

Czy element odbijający memberExpression ma jakieś wady, na przykład wydajność lub sytuację, w której nie działają? –

+0

@ IngóVals Zaimplementowałem tę klasę w dwóch opracowanych przeze mnie projektach i jak dotąd nie było żadnego problemu – Dante

Powiązane problemy