模型中的计算特性

本文关键字:计算 模型 | 更新日期: 2023-09-27 18:28:24

祝你好运!

我的产品模型包含许多经典属性(代码、说明、含增值税价格、无增值税价格和增值税)。对于我的例子,我只列出了有趣的属性。

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

我的例子:

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

有了这个,当任何价格变化时,我都有无限循环和堆栈溢出。正常,因为当任何价格变化时,所有其他价格都会重新计算,然后依次重新计算价格:)

当我的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中重新读取它们的值。

更新

根据您的评论(尽管这是一个非常奇怪的要求),您可以通过更新支持字段值来实现您想要的。注意,为了避免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();
        }
    }
}

两个注意事项:

  • 术语"计算"在这里不是最好的选择
  • 若您添加更多的属性,这将影响其他属性,那么此类代码的复杂性将快速增长