There are various ways of achieving this (and various MVVM frameworks that does it for you, to a degree) and it all depends on the context.
If you have a fairly static set of children (static as is static for the life of the owning view model) then having the owing view model connect to the
INotifyPropertyChanged.PropertyChanged
event on each child might work for you.
If on the other hand the list of children changes so that the owning view model would have to subscribe and unsubscribe to child events then that might be a little messy.
Consider the following simple example;
Notifier
using System.ComponentModel;
namespace WpfApplication {
public class Notifier : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
protected void Notify(string propertyName) {
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ChildModel
namespace WpfApplication {
public class ChildModel {
private readonly string name;
public string MutableValue { get; set; }
public ChildModel(string name, string mutableValue) {
this.name = name;
MutableValue = mutableValue;
}
public string Name {
get { return name; }
}
}
}
MainModel
using System.Collections.Generic;
namespace WpfApplication {
public class MainModel {
private readonly string name;
private readonly IEnumerable<ChildModel> children;
public MainModel(string name, IEnumerable<ChildModel> children) {
this.name = name;
this.children = children;
}
public string Name {
get { return name; }
}
public IEnumerable<ChildModel> Children {
get { return children; }
}
}
}
ChildViewModel
namespace WpfApplication {
public class ChildViewModel : Notifier {
private readonly ChildModel model;
public ChildViewModel(ChildModel model) {
this.model = model;
}
public string MutableValue {
get { return model.MutableValue; }
set {
if (value == model.MutableValue)
return;
model.MutableValue = value;
Notify("MutableValue");
}
}
}
}
MainViewModel
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
namespace WpfApplication {
public class MainViewModel {
private readonly MainModel model;
private readonly IEnumerable<childviewmodel> children;
public MainViewModel(MainModel model) {
this.model = model;
children = model.Children.Select(child => new ChildViewModel(child)).ToList();
foreach (var child in children) {
child.PropertyChanged += OnChildPropertyChanged;
}
}
private void OnChildPropertyChanged(object sender, PropertyChangedEventArgs e) {
var child = sender as ChildViewModel;
}
public string Name {
get { return model.Name; }
}
public IEnumerable<childviewmodel> Children {
get { return children; }
}
}
}
</childviewmodel></childviewmodel>
In this case the events from the
ChildViewModel
are monitored by the owning view model,
MainViewModel
, and the hooking up to the event is the responibility of the
MainViewModel
and is done in its constructor as it creates view models from models of the children.
Again; a setup like this might turn messy if you need to;
- Dynamically add/remove children
- There are many properties on the
ChildViewModel
and the MainViewModel
needs to do different things depending on which property was changed. - The type of children vary
Hope this helps,
Fredrik