Let\'s say in some abstract ViewModel base-class I have a plain-old property as follows:
public Size Size
{
get { return _size; }
set
{
_size
I recently blogged about this exact problem. I include a [DependsUpon("Size")]
attribute with the Rectangle. I REALLY like this approach, because it keeps the dependency knowledge with the code that creates the dependency, not the other way around.
Take a look: http://houseofbilz.com/archive/2009/11/14/adventures-in-mvvm----dependant-properties-with-inotifypropertychanged.aspx
I use Josh Smith's PropertyObserver, which you can get from his MVVM Foundation library at http://mvvmfoundation.codeplex.com/.
Usage:
_viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel)
.RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle);
Brian's attribute approach is nice too. One thing I like about PropertyObserver is that I can execute arbitrary code; allowing me to check conditions which may make me avoid the raise or perform other actions all together.
maybe because im a VB guy, but in your Rectangle code it looks like you are accessing the private _size declaration instead of the Public Size property which would not fire the OnPropertyChanged event to alert the view.
Also I may be off base, but shouldnt Rectangle be an actual Object while Size is a property of that object? Maybe that is what you are doing..some C# methodologies are still really foreign to me.
You can simply override OnPropertyChanged in the derived ViewModel like so:
protected override void OnPropertyChanged(string propertyName) {
base.OnPropertyChanged(propertyName);
if (propertyName == "Size") {
base.OnPropertyChanged("Rectangle");
}
}
Another possibility... A while back I put together a pretty nice ViewModel base class that supports attributes on properties like:
[DependsOn("Size")]
public Rect Rectangle {
get { new Rect(0,0,Size.Width, Size.Height); }
}
Then the ViewModel base class collects these DependsOnAttribute's at runtime and in its OnPropertyChanged method it basically just looks to see what other properties need to be invalidated when a property change occurs.
A clean MVVM way would be to use a Messenger
subscribe/notify mechanism (like in Josh Smith's MvvmFoundation)
Create a singleton Messenger object somewhere - the main App class is always a good place for this
public partial class App : Application
{
private static Messenger _messenger;
public static Messenger Messenger
{
get
{
if (_messenger == null)
{
_messenger = new Messenger();
}
return _messenger;
}
}
}
In the Size setter from the base class, notify changes:
public Size Size
{
get { return _size; }
set
{
_size = value;
OnPropertyChanged("Size");
App.Messenger.NotifyColleagues("SIZE_CHANGED");
}
}
Now you can let your inherited ViewModel's listen for these changes, and raise PropertyChanged events as appropriate...
public MyViewModel : MyViewModelBase
{
public MyViewModel()
{
App.Messenger.Register("SIZE_CHANGED", () => OnPropertyChanged("Rectangle"));
}
}
Of course - you can add as many subscriptions to this message as you need - one for each property that needs changes to be notified back to the View...
Hope this helps :)