Based on the comments in your question, BnB
is a member of the reservation model. Given that, you can change TotalPrice
to a readonly property, a property without a set
method, and just caluclate the total in the get
method. Then, in the setters for CheckIn
and CheckOut
, call Notify("TotalPrice")
to update the UI. You also need to call Notify("TotalPrice")
in the setter for BnB
, since that member participates in the calculation of TotalPrice
.
This assumes that the Reservation Model implements INotifyPropertyChanged
and that Notify
invokes the PropertyChanged
event.
public class Reservation : INotifyPropertyChanged
{
private BnB? _bnb;
private DateTime _checkIn;
private DateTime _checkOut;
public double TotalPrice
{
// Instead of using a field, just calculate TotalPrice on the fly.
get
{
// Check for nulls - since _bnb is the only thing that is
// is nullable in the calculation, it is the only thing we
// need to check.
if (BnB== null)
{
return 0;
}
return (CheckOut - CheckIn).TotalDays * BnB.Price;
}
}
public BnB BnB
{
get => _bnb;
set
{
if (_bnb != value)
{
_bnb = value;
Notify(nameof(BnB));
Notify(nameof(TotalPrice));
}
}
}
public DateTime CheckIn
{
get => _checkIn;
set
{
if (value != _checkIn && value < _checkOut)
{
// I've changed the check to ensure that the new value isn't the
// same as the current value. No sense running this code if nothing
// has actually changed.
_checkIn = value;
}
// Without knowing what Notify does exactly, I can't say for sure. But
// if it is only invoking the PropertyChanged event then these two lines
// should probably be placed inside the if statement. There isn't any
// point to notifying the UI that a change happened if a change didn't
// actually happen.
Notify(nameof(CheckIn));
// You can notify the UI to update TotalPrice within a setter for a
// different property.
Notify(nameof(TotalPrice));
}
}
public DateTime CheckOut
{
get => _checkOut;
set
{
if (value != _checkOut&& value > _checkIn)
{
_checkOut = value;
}
// These might make more sense inside the if statement as well.
Notify(nameof(CheckOut));
Notify(nameof(TotalPrice));
}
}
// Other members of the Reservation model.
}
If you really need to have TotalPrice
be a property with a getter / setter and a backing field, then just set the TotalPrice
property when you set CheckIn
, CheckOut
, or BnB
.
public class Reservation
{
private BnB? _bnb;
private DateTime _checkIn;
private DateTime _checkOut;
private double _totalPrice;
public double TotalPrice
{
get => _totalPrice;
set
{
if (_totalPrice != value)
{
_totalPrice = value;
Notify("TotalPrice");
}
}
}
public BnB BnB
{
get => _bnb;
set
{
if (_bnb != value)
{
_bnb = value;
Notify(nameof(BnB));
TotalPrice = CalculateTotalPrice();
}
}
}
public DateTime CheckIn
{
get => _checkIn;
set
{
if (value != _checkIn && value < _checkOut)
{
// I've changed the check to ensure that the new value isn't the
// same as the current value. No sense running this code if nothing
// has actually changed.
_checkIn = value;
}
// Without knowing what Notify does exactly, I can't say for sure. But
// if it is only invoking the PropertyChanged event then these two lines
// should probably be placed inside the if statement. There isn't any
// point to notifying the UI that a change happened if a change didn't
// actually happen.
Notify(nameof(CheckIn));
// You can notify the UI to update TotalPrice within a setter for a
// different property.
TotalPrice = CalculateTotalPrice();
}
}
public DateTime CheckOut
{
get => _checkOut;
set
{
if (value != _checkOut&& value > _checkIn)
{
_checkOut = value;
}
// These might make more sense inside the if statement as well.
Notify(nameof(CheckOut));
TotalPrice = CalculateTotalPrice();
}
}
private double CalculateTotalPrice()
{
if (BnB== null)
{
return 0;
}
return (CheckOut - CheckIn).TotalDays * BnB.Price;
}
// Other members of the Reservation model.
}
Also, on a side note you might want to consider switching from double
to decimal
to represent currency.