I have an Item class with two properties "quantity" and "price" and implements INotifyPropertyChanged
public class Item:INotifyPropertyChanged
{
private event PropertyChangedEventHandler _propertyChanged;
public event PropertyChangedEventHandler PropertyChanged
{
add { _propertyChanged += value; }
remove { _propertyChanged -= value; }
}
void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (_propertyChanged != null)
{
_propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public int QuantityOnHand
{
get
{
return this._quantityOnHand;
}
set
{
if (value > 0)
{
this._quantityOnHand = value;
NotifyPropertyChanged();
}
else
{
throw new System.ArgumentException("Quantity must be a positive value!");
}
}
}
.....
}
And I have a collection class of items named "Inventory" with a property of TotalRetailPrice:
public class Inventory {
private List<Item> _inventoryList = new LinkedList<Item>();
public decimal TotalRetailPrice
{
get
{
decimal totalRetailPrice = 0M;
foreach (var item in _inventoryList)
{
totalRetailPrice += item.QuantityOnHand * item.RetailPrice;
}
return totalRetailPrice;
}
}
I am trying to find out a way to automatically update this property TotalRetailPrice, whenever I change either the quantity or the price of any item(s) in the list. How can I do that? Right now with my code, every time I tried to get this totalRetailPrice property, I will have to go through the list and recalculate it.
thanks!
Since the interface INotifyPropertyChanged
exposes an event called PropertyChanged
you can just subscribe to that in the 'inventory' class.
You will also want to listen for changed events in the list since you will need to know when items are added/removed so you can add/remove event handlers as necessary. I'd suggest using ObservableCollection<T>
as this supports some 'collection changed' events. Is there any reason you are using LinkedList<T>
?
e.g.
public class Inventory
{
private ObservableCollection<Item> _inventoryList = new ObservableCollection<Item>();
public decimal _total;
// You probably want INPC for the property here too so it can update any UI elements bound to it
public decimal Total { get { return _total; } set { _total = value; } }
// Constructor
public Inventory()
{
WireUpCollection();
}
private void WireUpCollection()
{
// Listen for change events
_inventoryList.CollectionChanged += CollectionChanged;
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Check what was added - I'll leave this to you, the e.NewItems are the items that
// have been added, e.OldItems are those that have been removed
// Here's a contrived example for when an item is added.
// Don't forget to also remove event handlers using inpc.PropertyChanged -= Collection_PropertyChanged;
var inpc = e.NewItems[0] as INotifyPropertyChanged;
if(inpc != null)
inpc.PropertyChanged += Collection_PropertyChanged;
}
private void Collection_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
RecalculateTotal();
}
private void RecalculateTotal()
{
// Your original code here which should feed the backing field
}
}
Check out the MSDN docs here:
http://msdn.microsoft.com/en-us/library/ms668604(v=vs.110).aspx
For info on ObservableCollection<T>
. The events section is what you are after. Also note you can use anonymous functions to handle the events if you prefer the syntax or want to capture variables in a certain scope etc. It helps to understand them fully (not sure what's available for Java as I've not really touched it save a couple of Android mess-about projects) so it might be worth reading up as there are a small caveats to be aware of when capturing, but that's another story!
e.g.
_inventoryList.CollectionChanged += (o,e) =>
{
// Anonymous method body here
// o = the first param (object sender), e = args (NotifyCollectionChangedEventArgs e)
};