The MadProps.MvvmLight ScreenConductor

Over the past couple of days, shiftkey and I have been working on a fork of MadProps.MvvmLight to add a new feature, and we've just pushed a new version which includes it.

The idea was to create a very lightweight version of Caliburn.Micro's "screen conductor" pattern for MVVM Light. A screen conductor, for those (like me) who hadn't heard of it before, is basically a simple class to manage a set of ViewModels that are available to the view, and allow you to switch between them. It's handy for user interfaces like wizards, where one step has to be active at a time, or multiple document interfaces (MDI) where you have several views open at once and can switch between them.

The public face of the ScreenConductor class in MadProps.MvvmLight looks like this:

public class ScreenConductor : ViewModelBase
{
    protected virtual void OnActiveScreenChanged() { }

    public IList<IScreen> Screens { get; }
    public IScreen ActiveScreen { get; set; }

    public bool CanNavigate(IScreen screen) { ... }
    public void Navigate(IScreen screen) { ... }
}

So basically you have a collection of "screens", and the ability to activate one. If you try to activate a screen that isn't in the Screens collection, it will be added for you.

The CanNavigate and Navigate methods do an extra check before activating a screen. Let's look at the IScreen interface to understand what:

public interface IScreen
{
    bool CanActivate { get; }
    bool CanDeactivate { get; }

    void OnActivated();
    void OnDeactivated();

    object Header { get; }
}

So we have some methods that let the screen tell you whether it can be switched to or switched away from, and some methods that let the conductor notify the screen when that happens. We've also included an abstract ScreenBase class (deriving from ViewModelBase) that you can derive from to get a default implementation of this interface.

IScreen also includes a Header property which is useful for binding to UI elements like TabControl tabs or buttons - it can be anything you like that might visually represent the screen it belongs to.

If you simply set the ActiveScreen property on the conductor, we assume that you know what you're doing and don't bother asking the screens if they can be deactivated or activated.

If you use the Navigate method, though, we'll call CanDeactivate on the active screen to give it a chance to stop the switch (in case the user has entered invalid data or some such).

We've left the CanActivate method in there for completeness, but right now we're not calling it from the conductor. If you need to check that too, you can do so in a derived class.

You'll notice that our ScreenConductor class derives from ViewModelBase, so it's easy to shoehorn into your existing MVVM Light ViewModels without any issues. I've done so in Comicster and was able to remove a lot of code in the process.

The screen conductor bits are available on NuGet right now. Have a play and let us know what we missed!

mvvm wpf silverlight
Posted by: Matt Hamilton
Last revised: 02 Oct, 2014 08:23 AM History

Trackbacks

Comments

Goran
Goran
21 May, 2012 05:54 PM

Hi, screen conductors do make life easier. I am curious why you didn't implement a close behavior for the IScreen? Also, in source code I see that you have also implemented ActivityBase, but you dont mention it in the article. Did you blog somewhere about it?

Nice work, btw.

21 May, 2012 11:07 PM

Hi Goran,

You're testing my memory a bit now. :)

I think the reason we didn't add a "Close" behaviour for IScreen is that a "screen" as we defined it was not necessarily something you could "close". It might just be a panel on your window, or a tab in a tab control.

Of course, that's not to say that you couldn't add your own Close() method to the implementing ViewModel class. The implementation can add whatever behaviours it likes.

Re: ActivityBase - that's used by the coroutine stuff in MadProps.MvvmLight, which is quite separate from the screen conductors. See this article for more info about that.

krish
krish
28 Feb, 2013 06:04 PM

I am newbie, I would greatly appreciate if you can add sample project or point to a link that explains how to use ScreenConductor.

28 Feb, 2013 09:56 PM

krish,

The Bitbucket repository contains two different sample apps that use the ScreenConductor.

No new comments are allowed on this post.