Sunday, 23 September 2012

INPC Parent Child Notification

Here is a simple example of a parent listening to change notification from a child and exposing an aggregate value (or “denormalized” value in database terminology).

The Order (parent) exposes the TotalCost, which is a sum of the Cost properties in OrderLines (child).

image

public class Order : InpcBase
{
private readonly ObservableCollection<OrderLine> orderLines;

public Order()
{
orderLines = new ObservableCollection<OrderLine>();
}

public decimal TotalCost
{
get { return orderLines.Sum(ol => ol.Cost); }
}

public void AddOrderLine(OrderLine orderLine)
{
orderLine.PropertyChanged += orderLine_PropertyChanged;
}

private void orderLine_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Cost") OnPropertyChanged("TotalCost");
}
}

public class OrderLine : InpcBase
{
private decimal cost;
public decimal Cost
{
get { return cost; }
set
{
if (cost == value) return;
cost = value;
OnPropertyChanged("Cost");
}
}
}

public abstract class InpcBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler == null) return;
handler(this, new PropertyChangedEventArgs(name));
}
}

2 comments:

  1. Some people prefer to do it using ExpressionTrees.
    http://blogs.msdn.com/b/atverma/archive/2010/07/28/inotifypropertychanging-and-inotifypropertychanged-in-real-life-using-expression-trees.aspx

    C#5 now has CallerMemberName
    http://www.robfe.com/2011/09/raising-the-right-propertychanged-with-c-5s-caller-info-attributes/

    ReplyDelete
  2. Hi CoderMonkey, thanks for the comment - good shout! I like the ExpressionTree solution and use it at work. For this blog post I tried to keep it simple and focused on purely Parent/Child notification. In fact for my solution at work I ended up using a modelSpecificEventAggregator for the notification (as opposed to an application wide Event Aggregator) but the above code is useful. The new C#5 update is v cool, something everyone has wanted since Xaml was released :)

    ReplyDelete