INotifyPropertyChanged bez wpisywania nazwy właściwości.

Każdy, kto choć przez chwilę miał przyjemność pisać jakąś aplikacje w .NET używającą bindowania zapewne zna doskonale ten interfejs. Sam spędziłem mnóstwo czasu pisząc w setterach do właściwości OnPropertyChanged(„NazwaWłaściwości”);

Możecie otworzyć szampana, gdyż w .NET Framework 4.5 możemy się pozbyć bezmyślnego kopiowania nazwy właściwości.

Jak było wcześniej?

Wcześniej wywołując event PropertyChanged dla właściwości trzeba było podać jej nazwę.

class SimpleClass : INotifyPropertyChanged
{
    private int _myProperty;
    public int MyProperty {
       get { return _myProperty; }
       set
       {
          _myProperty = value;
          OnPropertyChanged("MyProperty");
       }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    private void OnPropertyChanged(string propertyName)
    {
       if (PropertyChanged != null)
       {
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
       }
    }
}

Jak wiadomo, nie służyło to refactoringowi. Wystarczyło zmienić nazwę właściwości a cały program się sypał i widok nie był odświeżany, gdy powinien.

Jak jest teraz?

Tak jak jednak wspominałem z pomocą przychodzi nam atrybut CallerMemberName, który jak możemy się domyślić zwraca nam nazwę właściwości/metody, która wywołała metodę.
Jak go użyć? Dodajemy ten atrybut przed deklaracją parametru do funkcji OnPropertyChanged oraz ustawiamy parametrowi wartość domyślną (null). Dzięki temu możemy wywołać funkcję OnPropertyChanged bez żadnych parametrów, a kompilator sam będzie wiedział co go wywołało.

class SimpleClass : INotifyPropertyChanged
{
   private int _myProperty;
   public int MyProperty {
      get { return _myProperty; }
      set
      {
         _myProperty = value;
         OnPropertyChanged();
      }
   }
 
   public event PropertyChangedEventHandler PropertyChanged;
 
   private void OnPropertyChanged([CallerMemberName]string propertyName = null)
   {
      if (PropertyChanged != null)
      {
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
   }
}

3 Comments

  1. Dzięki za przykład. Wcześniej znałem tylko jeszcze metode aby przekazywać Expression tree http://dotnet.dzone.com/news/silverlightwpf-implementing

    Odpowiedz

  2. Niezłe…
    Oprócz wspomnianego Expressions, znam jeszcze Weaving z Property Weaverem oraz wstrzykiwanie wywołania PropertyChanged Emitem. Obie metody tworzą czytelniejszy kod od powyższego, ale i tak warto znać. 🙂

    Odradzam stosowanie określenia atrybutu dla opisywania właściwości gdyż określenie atrybut jest już w c# używane(chociażby wspomniany CallerMemberName jest atrybutem ustawionym na parametrze do metody).
    Jak ktos nie lubi określenia „właściwość” to ma do wyboru jeszcze „propercja”(taki potworek który słyszałem na jednej z prezentacji). Skoro niektórzy używają encje zamiast bytów to czemu by miały nie być propercje?

    Odpowiedz

    1. Słuszna uwaga, nie wiem skąd mi się wzięły te atrybuty, jakoś tak bardziej mi pasuje ta nazwa. Poprawione.

      Odpowiedz

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *