2010-02-10 61 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