Messaging to the Shell in an MVVM RI Scenario

Topics: Prism v4 - WPF 4
Dec 17, 2010 at 5:32 PM

I now have my head around how the MVVM RI works. Contrary to other posts here, is does use Prism bits (NotificationObject and Interactivity). Anyway, I'd like to add a status bar to my Shell (MainPage in RI) and update it. Do I need to go the full Bootstrapper route, create a VM for my Shell, and use the EventAggregator? Further, if I go the Bootstrapper route, do I abandon the UIService and rely on Prism view composition? Thanks.

Dec 17, 2010 at 5:42 PM

Using EventAggregator would be what I would use.  Since it sounds as if you already have a service in place for UI communication, I wouldn't up and change just to satisfy the need to change your routine or the pattern implemented.

Dec 17, 2010 at 6:04 PM

Therefore requiring the use of a Bootstrapper, yes?

Dec 17, 2010 at 7:56 PM

Hi,

There is no need to use the Bootstrapper to make use of the Event Aggregator. From this chapter of the Prism MSDN Documentation: “It is important to note that Prism was designed so that you can use any of Prism's capabilities and design patterns individually, or all together, depending on your requirements and your application scenario. Prism was designed so that it could be incrementally adopted, allowing you to use the capabilities and design patterns that make sense for your particular application without requiring major structural changes.

As an example, you could check this post in which a standalone event aggregator for Silverlight is portrayed. Take into account that a similar scenario could be implemented in WPF.

You can read more about Event Aggregator in Chapter 7:  Composing the User Interface

In fact, if you decide to use a boostrapper, you don’t necessarily have to use the UI Composition mechanisms provided by Prism. However, the Bootstrapper registers, for example, the Region Manager, the Region Adapter Mappings, among other components of the UI Composition mechanisms, so if you intend not to use them, you should modify your boostrapper to register your implementations instead.

I hope you find this information useful.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic

Dec 20, 2010 at 5:20 PM

I went through the code for the MefBootstrapper, and discovered that all I needed was to create a class the derived from EventAggregator and adorn it with an [Export(typeof(IEventAggregator))] attribute like this:

[Export(typeof(IEventAggregator))]
public class ContractLoaderEventAggregator : EventAggregator {
}

The MVVM RI adds itself to the container, and this in turn registered the event aggregator. The other change I had to do was to modify the SingleViewUiService and the ViewFactory. This is because I needed the container to compose my Shell and it's ViewModel.

The first change was to the SingleViewUiService. I commented out the instantiation of the TMainView in the ctor. I moved it to the MainWindow get accessor like so:

public IMainView MainWindow {
    get { return _mainWindow ?? (_mainWindow = ViewFactory.GetView<TMainView>()); }
}

The next step was to create an overload for GetView in the ViewFactory class like this (this could be refactored along with the other GetView) :

public T GetView<T>() where T : ContentControl {
    var view = _container.GetExportedValueOrDefault<T>();
    if(view == null)
        throw new InvalidOperationException(String.Format("Unable to locate view with type {0}.", typeof(T)));
    return view;
}

Now, for my Shell, all I added was the [Export] attribute in my Shell.xaml.cs file, because the factory wasn't going to instantiate it by contract name (hence no [ExportView(string)] attribute). I import my ViewModel into the Shell via a property just like the other Views in the MVVM RI. My ShellViewModel looks like this:

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ShellViewModel : WorkspaceViewModel {
    private string _statusMessage;

    [ImportingConstructor]
    public ShellViewModel(IEventAggregator eventAggregator)
        : base(eventAggregator) {
        Subscribe();
    }

    public string StatusMessage {
        get { return _statusMessage; }
        set {
            _statusMessage = value;
            RaisePropertyChanged(() => StatusMessage);
        }
    }

    private void Subscribe() {
        EventAggregator.GetEvent<StatusEvent>().Subscribe(
            OnStatusEvent,
            ThreadOption.UIThread,
            true,
            StatusEventPredicate
            );
    }

    private static bool StatusEventPredicate(StatusEventPayload payload) {
        return true;
    }

    private void OnStatusEvent(StatusEventPayload payload) {
        StatusMessage = payload.Status;
        Debug.WriteLine(StatusMessage);
    }
}
WorkspaceViewModel is an abstract class of mine with some extra stuff in it, which derives from NotificationObject. The event notifications work like a charm.

 

 

Developer
Dec 20, 2010 at 5:28 PM

Hi,

Thanks for sharing your findings with the rest of the community, as other users might find them useful for their situations.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Dec 20, 2010 at 5:32 PM
Perhaps they could find there way into the RI, or at least a contrib.

On Mon, Dec 20, 2010 at 1:28 PM, guidomaliandi
<notifications@codeplex.com> wrote:
> From: guidomaliandi
>
> Hi,
>
> Thanks for sharing your findings with the rest of the community, as other
> users might find them useful for their situations.
>
> Guido Leandro Maliandi
> http://blogs.southworks.net/gmaliandi
>
> Read the full discussion online.
>
> To add a post to this discussion, reply to this email
> ([email removed])
>
> To start a new discussion for this project, email
> [email removed]
>
> You are receiving this email because you subscribed to this discussion on
> CodePlex. You can unsubscribe on CodePlex.com.
>
> Please note: Images and attachments will be removed from emails. Any posts
> to this discussion will also be available online at CodePlex.com



--

---
David B. Bitton
Code No Evil, LLC

Code Made Fresh Daily.