模型中的计算属性

时间:2015-12-28 10:52:51

标签: c# model stack-overflow inotifypropertychanged

Bonjour!

我的产品型号包含许多经典属性(代码,描述,价格含增值税,价格不含增值税,增值税)。对于我的例子,我只放了一些有趣的属性。

在这个模型中,我想添加价格计算。当任何金额变化时,计算其他属性(当增值税改变时,重新计算价格与增值税和价格无增值税,反之亦然)

我的例子:

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个金额?

1 个答案:

答案 0 :(得分:1)

不要将计算属性设为读写。相反,为只读计算属性引用适当的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重新读取他们的值。

<强>更新

根据您的评论(即使这是非常奇怪的要求),您可以通过更新支持字段值来实现您想要的效果。请注意,您不得在此处调用属性设置器以避免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();
        }
    }
}

两个注释:

  • term&#34;计算&#34;这不是最好的选择;
  • 如果您添加更多属性会影响其他人,此类代码的复杂性将会快速增长。