模型中的计算属性

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" 在这里不是最佳选择;
  • 如果您添加更多属性,此类代码的复杂性会增长得非常快,这会影响其他人。