Reputation: 165
My questions is similar to this INotifyPropertyChanged and calculated property
I'm reusing some code from the above example because it's easier to understand what's going on.
Assume I started with something similar to this. Note that INotifyPropertyChangedBase is the base class that I use to implement INotifyPropertyChanged.
public class Order : INotifyPropertyChangedBase
{
private string itemName;
public string ItemName
{
get { return itemName; }
set
{
itemName = value;
}
}
private decimal itemPrice;
public decimal ItemPrice
{
get { return itemPrice; }
set
{
itemPrice = value;
}
}
private int quantity;
public int Quantity
{
get { return quantity; }
set
{
quantity= value;
OnPropertyChanged("Quantity");
OnPropertyChanged("TotalPrice");
}
}
public decimal TotalPrice
{
get { return ItemPrice * Quantity; }
}
}
After generating similar code to this I realized that each order could be comprised of multiple Items
so I generated a class : Item
similar to this:
public class Item : INotifyPropertyChangedBase
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private decimal price;
public decimal Price
{
get { return price; }
set { price = value; }
}
private int quantity;
public int Quantity
{
get { return quantity; }
set
{
quantity = value;
OnPropertyChanged("Quantity");
}
}
}
Then I converted my Order
class to look like this.
public class Order : INotifyPropertyChangedBase
{
private ObservableCollection<Item> itemInfo;
public ObservableCollection<Item> ItemInfo
{
get { return itemInfo; }
set
{
itemInfo = value;
OnPropertyChanged("ItemInfo");
OnPropertyChanged("TotalPrice");
}
}
public decimal TotalPrice
{
get
{
Decimal totalPrice;
foreach (Item item in ItemInfo)
{
totalPrice += item.Quantity * item.Price;
}
return totalPrice;
}
}
}
Implementing this is done via a DataGrid
. Each Order
is a row. I am binding column headers to Item.Name
(limited number of options) and Item.Quantity
to the appropriate column cell. The final column is the TotalPrice
.
Previously, the TotalPrice
would update when I changed the Quantity
. Now, with the new implementation using Item
the TotalPrice
will not update in the DataGrid
. It seems that the setter for ItemInfo
will not fire when I update a instance of Item.Quantity
. The setter on Item.Quantity
does fire when I update the appropriate DataGrid
cell.
How do I get the value of a read-only property (TotalPrice
) to update using nested properties (Item
)?
Upvotes: 3
Views: 1984
Reputation: 12315
You will have to listen CollectionChanged of ItemInfo like
public class Order : INotifyPropertyChangedBase
{
public Order()
{
ItemInfo =new ObservableCollection<Item>();
ItemInfo.CollectionChanged += ItemInfo_CollectionChanged;
}
void ItemInfo_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("TotalPrice");
}
private ObservableCollection<Item> itemInfo;
public ObservableCollection<Item> ItemInfo
{
get { return itemInfo; }
set
{
itemInfo = value;
OnPropertyChanged("ItemInfo");
OnPropertyChanged("TotalPrice");
}
}
OR
public class Order : INotifyPropertyChangedBase
{
void ItemInfo_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("TotalPrice");
}
private ObservableCollection<Item> itemInfo;
public ObservableCollection<Item> ItemInfo
{
get { return itemInfo; }
set
{
if(itemInfo!=null)
itemInfo.CollectionChanged -= ItemInfo_CollectionChanged;
itemInfo = value;
if(itemInfo!=null)
itemInfo.CollectionChanged += ItemInfo_CollectionChanged;
OnPropertyChanged("ItemInfo");
OnPropertyChanged("TotalPrice");
}
}
Upvotes: 2