Reputation: 452
Bonjour !
I have Product model who contain many classics properties (Code, Description, Price With VAT, Price WITHOUT Vat, VAT). For my example I put only interesting properties.
In this model, I want to add prices calculations. When any amount change, to calculate other properties (When Vat change, recalculate Price With Vat and Price Without Vat, vice versa)
My example :
public class Product : EditableObject
{
//VAT percentage propertie (ex: 20%)
private decimal _vat;
public decimal Vat
{
get { return _vat; }
set
{
_vat = value;
PriceWithVat = _priceWithoutVat * (1 + Vat / 100); //Vat changed, we recalculate Price WITH VAT propertie
PriceWithoutVat = _priceWithVat / (1 + Vat / 100); //Vat changed, we recalculate Price WITHOUT VAT propertie
NotifyOfPropertyChange(() => Vat);
}
}
//Product Price Without VAT
private decimal _priceWithoutVat;
public decimal PriceWithoutVat
{
get { return _priceWithoutVat; }
set
{
_priceWithoutVat = value;
PriceWithVat = _priceWithoutVat * (1 + Vat / 100); //PriceWithoutVat changed, we recalculate Price WITH VAT propertie
NotifyOfPropertyChange(() => PriceWithoutVat);
}
}
//Product Price WITH Vat
private decimal _priceWithVat;
public decimal PriceWithVat
{
get { return _priceWithVat; }
set
{
_priceWithVat = value;
PriceWithoutVat = _priceWithVat / (1 + Vat / 100); //PriceWithVat changed, we recalculate Price WITHOUT VAT propertie
NotifyOfPropertyChange(() => PriceWithVat);
}
}
}
With this, when any price change, I have infinity loop and Stack Overflow. Normal, because when any price change, all others are recalculated, and they recalculate prices in turn :)
Do you have solution to automatically recalculate my 3 amounts when any of them change ?
Upvotes: 0
Views: 4095
Reputation: 37790
Do not make calculated properties read-write. Instead, raise appropriate PropertyChanged
for read-only calculated properties, e.g.:
public decimal Price
{
get { return _price; }
set
{
if (_price != value)
{
_price = value;
NotifyOfPropertyChange(() => Price);
NotifyOfPropertyChange(() => PriceWithVat);
}
}
}
public decimal Vat
{
get { return _vat; }
set
{
if (_vat != value)
{
_vat = value;
NotifyOfPropertyChange(() => Vat);
NotifyOfPropertyChange(() => PriceWithVat);
}
}
}
public decimal PriceWithVat
{
get { return _price / (1 + _vat / 100); }
}
Since they are calculated properties, you can't set their values directly. On the other hand, raising PropertyChanged
for them is enough to re-read their values from UI.
UPDATE
According to your comment (even though this is a very strange requirement), you can achieve what you want by updating backing field values. Note, that you must not call property setters here to avoid StackoverflowException
:
private void UpdatePriceWithVat()
{
_priceWithVat = _price * (1 + _vat / 100);
NotifyOfPropertyChange(() => PriceWithVat);
}
private void UpdatePrice()
{
_price = _priceWithVat / (1 + _vat / 100);
NotifyOfPropertyChange(() => Price);
}
public decimal Price
{
get { return _price; }
set
{
if (_price != value)
{
_price = value;
NotifyOfPropertyChange(() => Price);
UpdatePriceWithVat();
}
}
}
public decimal Vat
{
get { return _vat; }
set
{
if (_vat != value)
{
_vat = value;
NotifyOfPropertyChange(() => Vat);
UpdatePriceWithVat();
}
}
}
public decimal PriceWithVat
{
get { return _priceWithVat; }
set
{
if (_priceWithVat != value)
{
_priceWithVat = value;
NotifyOfPropertyChange(() => PriceWithVat);
UpdatePrice();
}
}
}
Two notes:
Upvotes: 1