INotifyPropertyChanged和计算属性

Ars*_*yan 7 c# wpf inotifypropertychanged

假设我有一个简单的类Order,它有一个TotalPrice计算属性,可以绑定到WPF UI

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; }    
  }
}
Run Code Online (Sandbox Code Playgroud)

在影响TotalPrice计算的属性中调用RaisePropertyChanged("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");

    }
}
Run Code Online (Sandbox Code Playgroud)

并调用TotalPrice = -1而不是this.RaisePropertyChanged("TotalPrice"); 在其他属性.请更好地提出建议

非常感谢

小智 7

另一个解决方案是Robert Rossney在这个问题中提出的解决方案:

WPF INotifyPropertyChanged用于链接的只读属性

您可以创建属性依赖关系图(使用他的代码示例):

private static Dictionary<string, string[]> _DependencyMap = 
new Dictionary<string, string[]>
{
   {"Foo", new[] { "Bar", "Baz" } },
};
Run Code Online (Sandbox Code Playgroud)

然后在OnPropertyChanged中执行此操作:

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

您甚至可以附加属性以将依赖属性绑定到它依赖的属性.就像是:

[PropertyChangeDependsOn("Foo")]
public int Bar { get { return Foo * Foo; } }
[PropertyChangeDependsOn("Foo")]
public int Baz { get { return Foo * 2; } }
Run Code Online (Sandbox Code Playgroud)

我还没有实现属性的细节.我现在最好开始研究它.


Mar*_*ann 4

可以检查是否应该从可能更改该值的任何其他成员处引发此事件,但只有在您实际更改该值时才这样做。

您可以将其封装在一个方法中:

private void CheckTotalPrice(decimal oldPrice)
{
    if(this.TotalPrice != oldPrice)
    {
         this.RaisePropertyChanged("TotalPrice");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你需要从其他变异成员中调用它:

var oldPrice = this.TotalPrice;
// mutate object here...
this.CheckTotalPrice(oldPrice);
Run Code Online (Sandbox Code Playgroud)