Alex Rivera | Logout

Change Notification in MVVM Hierarchies

Asked 2010-01-05T23:51:32.797
14

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 = value;
        OnPropertyChanged("Size");
    }
}

I then create a more specific ViewModel, inheriting from the previous one, which contains the following property:

public Rect Rectangle
{
    get { return new Rect(0, 0, _size.Width, _size.Height); }
}

Now, in some View class I bind to the aforementioned ViewModel's Rectangle property. Everything works fine, until I change the size. When Size changes, Rectangle doesn't know about it and the change doesn't propagate to the View. And since Rectangle is in the child class, I can't simply add an OnPropertyChanged("Rectangle") to the Size setter.

Now imagine that I have many different properties like Rectangle, that all depend on base-class properties, and that none of these changes are being propagated. I need some lightweight and elegant way of chaining change notifications, preferably one that doesn't require a lot of code and doesn't force me into using dependency properties.

Obviously there are a lot of ugly solutions here- what I am looking for is something clean and clever. It seems to me this would be a very common scenario, and it seems to me there might be an MVVM-friendly way of doing this.

Edit
Report

2 Answers

1

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 :)

answered 2010-01-06T00:28:32.200
0

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.

answered 2010-01-06T12:42:34.997

Your Answer