模型中的计算属性
Calculated properties in Model
您好!
我的产品模型包含许多经典属性(代码、描述、含增值税价格、不含增值税价格、增值税)。对于我的示例,我只放置了有趣的属性。
在此模型中,我想添加价格计算。当任何金额变化时,计算其他属性(当增值税变化时,重新计算含增值税价格和不含增值税价格,反之亦然)
我的例子:
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);
}
}
}
有了这个,当任何价格变化时,我都有无限循环和 Stack Overflow。正常,因为任何价格变化,其他的都重新计算,他们依次重新计算价格:)
你们有解决方案可以在我的 3 个金额发生变化时自动重新计算吗?
不要将计算的属性设为读写。相反,为只读计算属性提高适当的 PropertyChanged
,例如:
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); }
}
由于它们是计算 属性,您不能直接设置它们的值。另一方面,为它们提高 PropertyChanged
足以从 UI.
重新读取它们的值
更新
根据您的评论(尽管这是一个 非常 奇怪的要求),您可以通过更新支持字段值来实现您想要的。请注意,您不能在此处调用 属性 setter 以避免 WhosebugException
:
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();
}
}
}
两个注意事项:
- 术语 "calculated" 在这里不是最佳选择;
- 如果您添加更多属性,此类代码的复杂性会增长得非常快,这会影响其他人。
您好!
我的产品模型包含许多经典属性(代码、描述、含增值税价格、不含增值税价格、增值税)。对于我的示例,我只放置了有趣的属性。
在此模型中,我想添加价格计算。当任何金额变化时,计算其他属性(当增值税变化时,重新计算含增值税价格和不含增值税价格,反之亦然)
我的例子:
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);
}
}
}
有了这个,当任何价格变化时,我都有无限循环和 Stack Overflow。正常,因为任何价格变化,其他的都重新计算,他们依次重新计算价格:)
你们有解决方案可以在我的 3 个金额发生变化时自动重新计算吗?
不要将计算的属性设为读写。相反,为只读计算属性提高适当的 PropertyChanged
,例如:
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); }
}
由于它们是计算 属性,您不能直接设置它们的值。另一方面,为它们提高 PropertyChanged
足以从 UI.
更新
根据您的评论(尽管这是一个 非常 奇怪的要求),您可以通过更新支持字段值来实现您想要的。请注意,您不能在此处调用 属性 setter 以避免 WhosebugException
:
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();
}
}
}
两个注意事项:
- 术语 "calculated" 在这里不是最佳选择;
- 如果您添加更多属性,此类代码的复杂性会增长得非常快,这会影响其他人。