Propriété INotifyPropertyChanged et calculée

Supposons que j’ai la classe simple Order, qui possède une propriété calculée TotalPrice, qui peut être liée à l’interface utilisateur WPF.

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

Est-ce une bonne pratique d’appeler RaisePropertyChanged (“TotalPrice”) dans les propriétés qui affectent le calcul de TotalPrice? Quel est le meilleur moyen d’actualiser la propriété TotalPrice? L’autre version pour ce faire est bien sûr de changer une propriété comme celle-ci.

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

et appelez TotalPrice = -1 au lieu de this.RaisePropertyChanged (“TotalPrice”); dans d’autres propriétés. veuillez suggérer des solutions mieux

Merci beaucoup

Il convient de vérifier si vous devez également signaler cet événement à un autre membre susceptible de modifier la valeur, mais uniquement si vous modifiez réellement la valeur.

Vous pouvez encapsuler ceci dans une méthode:

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

Ensuite, vous devez appeler cela de vos autres membres mutants:

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

Une autre solution est celle proposée par Robert Rossney dans cette question:

WPF INotifyPropertyChanged pour les propriétés liées en lecture seule

Vous pouvez créer une carte de dépendance de propriété (en utilisant ses exemples de code):

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

puis faites ceci dans votre OnPropertyChanged:

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

Vous pouvez même attacher un atsortingbut pour lier la propriété dépendante à celle dont il dépend. Quelque chose comme:

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

Je n’ai pas encore implémenté les détails de l’atsortingbut. Je ferais mieux de travailler là-dessus maintenant.

Si vous utilisez NotifyPropertyWeaver, vous pouvez avoir ce 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; } } } 

Et ce sera compilé à cela.

 public class Order : INotifyPropertyChanged { decimal itemPrice; int quantity; public event PropertyChangedEventHandler PropertyChanged; public virtual void OnPropertyChanged(ssortingng 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; } } } 

Est-ce une bonne pratique d’appeler RaisePropertyChanged (“TotalPrice”) dans les propriétés qui affectent le calcul de TotalPrice?

Non, ce n’est pas, cela ne s’adapte pas et est un cauchemar d’entretien.

https://github.com/StephenCleary/CalculatedProperties est actuellement le meilleur moteur de formule pour MVVM (à mon avis) qui informe des modifications de propriétés dérivées / calculées et prend en charge tous les niveaux d’imbrication.

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