2010-02-10 59 views
7

假設我有簡單的Order類,有計算的財產TotalPrice,它可以綁定到WPF UIINotifyPropertyChanged的和計算的財產

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

它是一個很好的做法,在調用RaisePropertyChanged(「TotalPrice」)影響TotalPrice計算的屬性?什麼是刷新TotalPrice財產的最佳方式? 另一個版本做當然這是改變屬性這樣

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"); 

    } 
} 

和呼叫TotalPrice = -1,而不是this.RaisePropertyChanged(「TotalPrice」);在其他物業。請更好的建議解決方案

非常感謝

+0

任何級別的,我不認爲'ItemPrice'和'數量MVVM(在我看來) '應該負責爲'TotalPrice'提高'PropertyChanged'。這會起作用,但如果ItemPrice和Quantity是在另一個類中,那麼你將無法做到這一點,並且必須以另一種方式做到這一點。我在另一個問題中回答了這個問題,答案是相同的,即使這些屬性是在同一個類中,或者它們是在其他類中:http://stackoverflow.com/questions/43653750/raising-propertychanged-for- a-dependent-property-when-a-prerequisite-property-in-another-class – Jogge 2017-04-28 05:42:55

回答

4

它的優良檢查,看看是否應該從可能改變數值的任何其他成員引發此事件爲好,但只能這樣做,如果你真的變化的值。

你可以在方法中封裝此:

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

然後,你需要調用從您的其他變異成員:

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

另一種解決方案是一個羅伯特Rossney在這個問題上提出:

WPF INotifyPropertyChanged for linked read-only properties

你可以crea TE屬性依賴地圖(用他的代碼示例):

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

,然後做你的OnPropertyChanged:

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

你甚至可以附加一個屬性的相關屬性綁定到一個它取決於上。例如:

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

我還沒有實現該屬性的細節。我現在最好去研究一下。

+0

我一直在尋找一個開源的庫,可以做到這一點 - 我可以自己寫,但有人必須已經做到了。 – BrainSlugs83 2014-09-05 21:41:00

2

如果使用NotifyPropertyWeaver,你可以有這樣的代碼

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

它會被編譯到這一點。

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

它是一個很好的做法影響到TotalPrice計算性能調用RaisePropertyChanged( 「TotalPrice」)?

不,它不是,它不縮放,是一個維修的噩夢。

https://github.com/StephenCleary/CalculatedProperties是最好的公式引擎截至目前該通知有關派生/計算性能的變化,支持嵌套

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

我認爲最好的方式.net 4.5+調用nameof(總) – 2017-11-08 08:27:38

+0

我沒有引用硬編碼字符串vs nameof() - 反模式是觸發屬性(數量和ItemPrice)在原始示例中知道它們在派生上游屬性。 p.s.如果我們使用RaisePropertyChanged(nameof(TotalPrice)),CalculatedProperties使用[CallerMemberName]屬性來避免硬編碼屬性名稱 – KolA 2017-11-09 19:59:08

+0

比如果屬性名稱將被更改,代碼將不會編譯...因此,這應該足以使其可用 – 2017-11-09 22:17:34