Calculate result of two values on Property Changed MVVM

2.8k Views Asked by At

I am trying to Calculate the "NetAmount" by the following simple formula in MVVM

GrossAmount + Carriage - Discount = NetAmount

I am using MVVM Light Toolkit and declared properties as follows

public const string DiscountPropertyName = "Discount";
private double _discount;
public double Discount
{
    get
    {
        return _discount;
    }

    set
    {
        if (_discount == value)
        {
            return;
        }
        _discount = value;
        // Update bindings, no broadcast
        RaisePropertyChanged(DiscountPropertyName);
    }
}

public const string CarriagePropertyName = "Carriage";
private double _carriage;

public double Carriage
{
    get
    {
        return _carriage;
    }
    set
    {
        if (_carriage == value)
        {
            return;
        }
        _carriage = value;
        RaisePropertyChanged(CarriagePropertyName);
    }
}

public const string NetAmountPropertyName = "NetAmount";
private double _netAmount;

public double NetAmount
{
    get
    {
        _netAmount = Carriage + Discount;
        return _netAmount;
    }
    set
    {
        if (_netAmount == value)
        {
            return;
        }
        _netAmount = value;
        RaisePropertyChanged(NetAmountPropertyName);
    }
}

public const string GrossAmountPropertyName = "GrossAmount";
private double _grossAmount;

public double GrossAmount
{
    get
    {
        return _grossAmount;
    }

    set
    {
        if (_grossAmount == value)
        {
            return;
        }
        _grossAmount = value;
        RaisePropertyChanged(GrossAmountPropertyName);
    }
}

I Bind these properties in XAML with text boxes like follows:

<TextBox Text="{Binding GrossAmount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  DataContext="{Binding Mode=OneWay}"/>

<TextBox Text="{Binding Carriage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  DataContext="{Binding Mode=OneWay}"/>

<TextBox Text="{Binding Discount, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  DataContext="{Binding Mode=OneWay}"/>

And I bind a Text Block with the NetAmount Property like follows:

<TextBlock Text="{Binding NetAmount}" />

The ViewModel is SalesOrderViewModel.

I dont know where do I put the above mentioned formula so that it when any of the text boxes value is changed, it result in changing the NetAmount Property.

I am not new to C# but am new to MVVM and PropertyChanged Events, I know there is some really small silly thing I am doing wrong but cant get my head around it.

Any help will be highly appreciated.

1

There are 1 best solutions below

3
On BEST ANSWER

Since NetAmount is a calculation it makes sense to model it as a read only property in your view model. Accessing the property actually performs the calculation. The last trick is to call RaisePropertyChanged(NetAmountProperty) whenever any of the factors that affects NetAmount changes

public const string GrossAmountPropertyName = "GrossAmount";
private double _grossAmount;
public double GrossAmount
{
    get { return _grossAmount; }
    set 
    {
           if (_grossAmount == value)
                return;

           RaisePropertyChanged(GrossAmountPropertyName);
           RaisePropertyChanged(NetAmountPropertyName);
    }
}

public double Discount{} ... //Implement same as above
public double Carriage {} ... //Implement same as above

public const string NetAmountPropertyName = "NetAmount";
public double NetAmount
{
    get { return GrossAmount + Carriage - Discount; }
}

Edit: If you don't want to add a call to RaisePropertyChanged to every property that affects the NetAmount then you could modify RaisePropertyChanged so that it also raises a PropertyChanged event for the NetAmount property. It will cause some unnecessary PropertyChanged events to be raised but will be more maintainable

private void RaisePropertyChanged(string propertyName)
{
     var handler = PropertyChanged;
     if (handler != null)
     {
          handler(this, new PropertyChangedEventArgs(propertyName);
          handler(this, new PropertyChangedEventArgs(NetAmountProperty);
     }
}