2010-02-10 13 views
7

Załóżmy, że mam proste klasy Order, które mają TotalPrice obliczoną nieruchomość, która może być związany WPF UIINotifyPropertyChanged i obliczone nieruchomość

public class Order : INotifyPropertyChanged 
{ 
    public decimal ItemPrice 
    { 
    get { return this.itemPrice; } 
    set 
    { 
     this.itemPrice = value; 
     this.RaisePropertyChanged("ItemPrice"); 
     this.RaisePropertyChanged("TotalPrice"); 
    } 
    } 

    public int Quantity 
    { 
    get { return this.quantity; } 
    set 
    { 
     this.quantity= value; 
     this.RaisePropertyChanged("Quantity"); 
     this.RaisePropertyChanged("TotalPrice"); 
    } 
    } 

    public decimal TotalPrice 
    { 
    get { return this.ItemPrice * this.Quantity; }  
    } 
} 

Czy jest to dobra praktyka, aby zadzwonić RaisePropertyChanged („TotalPrice”) w właściwości, które wpływają na obliczenia TotalPrice? Jaki jest najlepszy sposób na odświeżenie usługi TotalPrice? Inna wersja to zrobić, jest oczywiście zmieniać własności jak ta

public decimal TotalPrice 
{ 
    get { return this.ItemPrice * this.Quantity; } 
    protected set 
    { 
     if(value >= 0) 
      throw ArgumentException("set method can be used for refresh purpose only"); 

    } 
} 

i wywołać TotalPrice = -1 zamiast this.RaisePropertyChanged ("TotalPrice"); w innych właściwościach. proszę sugerować rozwiązania lepiej

dzięki dużo

+0

nie sądzę 'i' Ilość ItemPrice' 'powinno być odpowiedzialne za podniesienie' PropertyChanged' dla 'TotalPrice'. To zadziała, ale co by było, gdyby "ItemPrice" i "Quantity" były w innej klasie - wtedy nie byłbyś w stanie tego zrobić i musiałbyś to zrobić w inny sposób. Odpowiedziałem na to pytanie w innym pytaniu, w którym odpowiedź jest taka sama, nawet jeśli właściwości były w tej samej klasie lub były w innych klasach: http://stackoverflow.com/questions/43653750/raising-propertychanged-for- zależna właściwość-kiedy-warunkiem-własności-w-innej-klasie – Jogge

Odpowiedz

4

Dobrze jest sprawdzić, czy należy podnieść tego zdarzenia, jak również z każdego innego członka, który może zmienić wartość, ale tylko zrobić, jeśli rzeczywiście zmiana się wartość.

Można ująć to w sposób:

private void CheckTotalPrice(decimal oldPrice) 
{ 
    if(this.TotalPrice != oldPrice) 
    { 
     this.RaisePropertyChanged("TotalPrice"); 
    } 
} 

Następnie trzeba zadzwonić, że z innych członków mutującymi:

var oldPrice = this.TotalPrice; 
// mutate object here... 
this.CheckTotalPrice(oldPrice); 
7

Innym rozwiązaniem jest jeden Robert Rossney zaproponowano w tej kwestii:

WPF INotifyPropertyChanged for linked read-only properties

można Crea Te mapy zależność nieruchomość (używając jego próbki kodu):

private static Dictionary<string, string[]> _DependencyMap = 
new Dictionary<string, string[]> 
{ 
    {"Foo", new[] { "Bar", "Baz" } }, 
}; 

a następnie zrobić to na swój OnPropertyChanged:

PropertyChanged(this, new PropertyChangedEventArgs(propertyName)) 
if (_DependencyMap.ContainsKey(propertyName)) 
{ 
    foreach (string p in _DependencyMap[propertyName]) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(p)) 
    } 
} 

Można nawet dołączyć atrybut związać właściwość zależną z jednym to zależy na. Coś jak:

[PropertyChangeDependsOn("Foo")] 
public int Bar { get { return Foo * Foo; } } 
[PropertyChangeDependsOn("Foo")] 
public int Baz { get { return Foo * 2; } } 

Nie wprowadziłem jeszcze szczegółów tego atrybutu. Lepiej będę teraz nad tym pracował.

+0

Szukałem biblioteki open source, która to robi - sam mógłbym ją napisać, ale ktoś już to zrobił. – BrainSlugs83

2

Jeśli używasz NotifyPropertyWeaver można mieć ten kod

public class Order : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public decimal ItemPrice { get; set; } 

    public int Quantity { get; set; } 

    public decimal TotalPrice 
    { 
     get { return ItemPrice*Quantity; } 
    } 
} 

i będzie skompilowany do tego.

public class Order : INotifyPropertyChanged 
{ 
    decimal itemPrice; 
    int quantity; 
    public event PropertyChangedEventHandler PropertyChanged; 

    public virtual void OnPropertyChanged(string propertyName) 
    { 
     var propertyChanged = PropertyChanged; 
     if (propertyChanged != null) 
     { 
      propertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public decimal ItemPrice 
    { 
     get { return itemPrice; } 
     set 
     { 
      if (itemPrice != value) 
      { 
       itemPrice = value; 
       OnPropertyChanged("TotalPrice"); 
       OnPropertyChanged("ItemPrice"); 
      } 
     } 
    } 

    public int Quantity 
    { 
     get { return quantity; } 
     set 
     { 
      if (quantity != value) 
      { 
       quantity = value; 
       OnPropertyChanged("TotalPrice"); 
       OnPropertyChanged("Quantity"); 
      } 
     } 
    } 

    public decimal TotalPrice 
    { 
     get { return ItemPrice*Quantity; } 
    } 
} 
0

Czy jest to dobra praktyka, aby zadzwonić RaisePropertyChanged ("TotalPrice") we właściwościach, które wpływają do obliczania TotalPrice?

Nie, nie jest, nie skaluje się i jest koszmarem związanym z konserwacją.

https://github.com/StephenCleary/CalculatedProperties jest najlepszy silnik formuła jak na razie dla MVVM (moim zdaniem), który powiadamia o zmianach właściwości pochodnych/obliczeniowe i obsługuje dowolny poziom zagnieżdżenia

public decimal ItemPrice 
    { 
    get { return Property.Get(0m); } 
    set { Property.Set(value); } 
    } 

    public int Quantity 
    { 
    get { return Property.Get(0); } 
    set { Property.Set(value); } 
    } 

    public decimal TotalPrice 
    { 
    get { return Property.Calculated(() => ItemPrice * Quantity); }  
    } 
+0

Myślę, że najlepiej na .net 4.5+, aby zadzwonić nameof (Total) –

+0

Nie odwołuję się do ciągu hardcode vs nameof() - antipattern jest to, że właściwości wyzwalacza (Quantity and ItemPrice) w oryginalnym przykładzie wiedzieć o ich użyteczności w pochodnych właściwości wyjściowe. p.s. CalculatedProperties używa atrybutu [CallerMemberName], aby uniknąć nazw właściwości hardcode – KolA

+0

, jeśli użyjemy RaisePropertyChanged (nameof (TotalPrice)) niż jeśli nazwa właściwości zostanie zmieniona, kod się nie skompiluje ... więc powinno wystarczyć użycie go tak, jak jest –

Powiązane problemy