How to send notifications between viewmodels?

Oct 27, 2009 at 1:18 AM
Edited Oct 27, 2009 at 1:20 AM

I am using mvvm, and am having some trouble.  Each component of my app uses MEF to share common information, where I can inject the dependencies I need just fine.

But lets say that one vm controls something that all vms need to update, like a theme for example.  The theme viewmodel handles the users theme choice, and then sets its theme accordingly- but all of the other vms need to be updated as well, and this is where Im running into problems.

Every viewmodel needs to have its own 'SelectedTheme' dependency property that fires the OnPropertyChanged notification, telling its model to update if I understand this stuff right.  But how do I do this?

Ive tried all kinds of stuff- having the ThemeVM have this:

[Export("SelectedTheme")]
public string SelectedTheme
{
    get
    {
        return _selectedTheme;
    }
    set
    {
        _selectedTheme = value;
        OnPropertyChanged("SelectedTheme");
    }
}

And then inject this dependiency into the other vms that need to know:

[Import("SelectedTheme")]
public string SelectedTheme { get; set; }

But this didnt work.  As far as I can tell, SelectedTheme is set to the proper value in the other viewmodels, which they get when they ask.  But they dont know to ask, so nothing changes.  Maybe this should work and Im missing something else.  But more likely Im misusing MEF somehow.

How do I accomplish my goal here?

THanks!

 

Developer
Oct 27, 2009 at 1:35 AM

Property Exports on a MEF part will only ever be queried once for a given object instance, so if the property value changes MEF will not do anything, in fact it won't even know. The OnPropertyChanged("SelectedTheme") looks to me to be in implementation of the INotifyPropertyChanged interface which MEF itself doesn't do anything with.

To do what you want in MEF you would need to actually export some interface that has the property you are interested in as well as an event to subscribe to for changes. Unfortunately MEF doesn't do anything magical for you in this space. MEF does support recomposition (you would need to set the AllowRecomposition=true on the Import) but that will only detect changes to the CompositionContainer which only the Host has access to change and a given VM wouldn't be able to change the container in this way. Simply changing the value of an property with an Export attribute on it will do nothing from a MEF standpoint.

Oct 27, 2009 at 2:28 AM

Nicros,

You may want to check out Prism's EventAggregator or Laurent Bugnion's Messenger class in MVVM Light. (http://mvvmlight.codeplex.com/). Either service provides a loosely coupled way to publish messages between components. You add the service to the container and then parts import it in order to publish / subscribe to messages. Both also provide thread-safety, and a loose delegate mechanism which does not keep subscribers alive.

HTH

Glenn

Oct 27, 2009 at 11:22 PM

Checked out MVVM lite, very nice!  I just popped in the messenger stuff, replaced my viewmodelbase with theirs and it works like a charm.

Thanks for the suggestion (both!)