INotifyPropertyChanged Property and Calculation

Suppose I have a simple Order class that has a computed TotalPrice property that can be bound to a WPF interface

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

Can RaisePropertyChanged ("TotalPrice") be called properties that affect TotalPrice calculations? What is the best way to update the TotalPrice property? Another option to do this, of course, is to change a property like this

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

and call TotalPrice = -1 instead. RaisePropertyChanged ("TotalPrice"); in other properties. offer better solutions

Thank you so much

+7
c # wpf inotifypropertychanged
source share
4 answers

It’s good to check whether this event should also be raised from any other member that can change the value, but only do it if you really change the value.

You can encapsulate this in a method:

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

Then you need to call this from your other mutating members:

 var oldPrice = this.TotalPrice; // mutate object here... this.CheckTotalPrice(oldPrice); 
+4
source share

Another solution is the one that Robert Rossney suggested in this matter:

WPF INotifyPropertyChanged for read-only related properties

You can create a map of property dependencies (using its code samples):

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

and then do it in your OnPropertyChanged:

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

You can even bind an attribute to bind the dependent property to the one on which it depends. Something like:

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

I have not implemented attribute details yet. Now I better work on it.

+7
source share

If you use NotifyPropertyWeaver , you can get this code

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

And it will be compiled.

 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; } } } 
+2
source share

Can RaisePropertyChanged ("TotalPrice") be called properties that affect TotalPrice calculations?

No, it is not, it does not scale and is a nightmare for maintenance.

https://github.com/StephenCleary/CalculatedProperties is the best formula mechanism at the moment for MVVM (in my opinion), which notifies about changes in derivatives / calculated properties and supports any level of nesting

  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
source share

All Articles