Wintellect  

Browse by Tags

All Tags » prism   (RSS)

In my last post, I showed you how to dynamically load modules on demand using the latest MEF release in Silverlight 3. This post, I will take you through managing regions with MEF. This will enable us to have a 100% MEF-based solution in Silverlight 3 if the only pieces of PRISM we were using were the dynamic module loading and region management.

Download the Source Code for this Post

Quick note: technically, the Composite Application Guidance (PRISM) is more of a guidance than an actual library. The library that is often used is the reference library for the guidance. I only mention this because in using the concept of the region manager and views, technically we are implementing the PRISM concept here and using CAG, we're just using MEF as the engine instead of the included reference library.

OK, let's get going ...

The first thing I did this time around was to rip out all of the IModuleInitialization pieces. They aren't needed because MEF will initialize what we need, as it's loaded. I destroyed the classes in the modules (it was good to see them load, anyway) and updated the navigation class to look like this:

[Export(typeof(INavigation))]
public class ViewNavigator : INavigation 
{        
    [Import]
    public ICatalogService CatalogService { get; set; }
    
    private readonly Dictionary<ViewType, string> _viewMap =
        new Dictionary<ViewType, string>
            {
                { ViewType.MainView, "DynamicModule.xap" },
                { ViewType.SecondView, "SecondDynamicModule.cs.xap" }
            };   

    private readonly List<string> _downloadedModules = new List<string>();
                                                                   
    public void NavigateToView(ViewType view)
    {
        if (!_downloadedModules.Contains(_viewMap[view]))
        {
            var catalog = new DeploymentCatalog(_viewMap[view]);
            CatalogService.Add(catalog);
            catalog.DownloadAsync();
            _downloadedModules.Add(_viewMap[view]);
        }
    }           
}

Thanks to Glenn Block for pointing out the excellent sample that comes included with the MEF bits (the deployment sample) ... this shows a different way of abstracting even the XAP file from the action of loading the catalog. In this case, I'm assuming I have prior knowledge of the controls and want to make my application more official by loading them dynamically as the user selects them.

So, now we've re-factored. That's a lot cleaner! Next, I want strongly-typed regions. I created a new project just for the regions, and added this class to define the enumeration:

public enum ViewRegion
{
    MainRegion,
    SubRegion 
}

public static class ViewRegionExtensions
{
    private static readonly List<ViewRegion> _regions = new List<ViewRegion> { ViewRegion.MainRegion, ViewRegion.SubRegion };       

    public static ViewRegion AsViewRegion(this string regionName)
    {
        foreach(var region in _regions)
        {
            if (regionName.Equals(region.ToString(), StringComparison.InvariantCultureIgnoreCase))
            {
                return region;
            }
        }
        return ViewRegion.MainRegion; 
    }
}

Unfortunately, I don't believe the Silverlight version of the Enum class allows you to enumerate the values of an enumeration. Therefore, I'm simply providing a static class to hold those and putting it next to the enum so it's easy to remember for maintenance. I also added an extension method that allows me to take a string and do AsViewRegion() to convert it to the enum.

In order to make the enum appear in XAML, we need to give Silverlight a hint that tells it how to convert from the string we'll key in the XAML to an actual enum we use in code. Here is the type converter, it basically says it only knows how to convert from strings, and uses the extension method to cast the string when called:

public class ViewRegionConverter : TypeConverter 
{        
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType.Equals(typeof (string));
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        return ((string) value).AsViewRegion();
    }
}

Now we can create our behavior. The behavior is an attached property we'll use to tag a container as a region. Eventually this can become complex as we support lists and content controls, but for the sake of this blog series I'm keeping it simple and limiting our containers to panels. Panels all have children, so it is easy to add an item to the children. The behavior will simply keep a static dictionary that maps the view region to the panel it was tagged to, and exposes a method that lets us request the panel for a view region. Here it is:

public static class RegionBehavior
{
    private static readonly Dictionary<ViewRegion, Panel> _regions = new Dictionary<ViewRegion, Panel>();
    
    public static readonly DependencyProperty RegionNameProperty = DependencyProperty.RegisterAttached(
        "RegionName",
        typeof (ViewRegion),
        typeof (RegionBehavior),
        new PropertyMetadata(ViewRegion.MainRegion, null));

    public static ViewRegion GetRegionName(DependencyObject obj)
    {
        return (ViewRegion) obj.GetValue(RegionNameProperty);
    }

    [TypeConverter(typeof(ViewRegionConverter))]
    public static void SetRegionName(DependencyObject obj, ViewRegion value)
    {
        obj.SetValue(RegionNameProperty, value);
        var panel = obj as Panel;
        if (panel != null)
        {
            _regions.Add(value, panel);
        }
    }
   
    public static Panel GetPanelForRegion(ViewRegion region)
    {
        return _regions[region];
    }

}

Notice the type converter hint I give the setter. That lets the XAML know how to convert. In fact, this will even give us intellisense in the XAML, so it knows what the valid enumerations are! Now I can go into my main shell and create my first region (the intellisense quickly gave me a list to choose from ... right now there are only two choices!)

<StackPanel Orientation="Vertical" Grid.Row="2" Regions:RegionBehavior.RegionName="MainRegion"/>

We can debug at this point and see that indeed the panel is registered with the dictionary with the behavior, so we're set on that front. Now we need to get our views into the region. We're still in the special "Regions" project and namespace. For now, I'm simply going to export type UserControl for my view, and specify the region with an attribute. In MEF, we can create a strongly typed attribute for metadata:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class TargetRegionAttribute : ExportAttribute 
{        
    public TargetRegionAttribute() : base(typeof(UserControl))
    {
        
    }

    public ViewRegion Region { get; set; }
}

So the type is UserControl but we can specify a region in the meta data. Now I can add a view to my dynamic module. I'm also specifying a region here for a nested view.

<UserControl x:Class="DynamicModule.View"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Regions="clr-namespace:RegionsWithMEF.Regions;assembly=RegionsWithMEF.Regions" 
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="Left Column of Outer View"/>
        <StackPanel Grid.Column="1" Orientation="Vertical" Regions:RegionBehavior.RegionName="SubRegion">
            <TextBlock Text="Right Column of Outer View"/>
        </StackPanel>
    </Grid>
</UserControl>

We then tag the view for export with our custom attribute, like this:

[TargetRegion(Region=ViewRegion.MainRegion)]
public partial class View
{
    public View()
    {
        InitializeComponent();
    }
}

Very easy and readable. I went ahead and added another control for the second view, and tagged it to the "sub region" view.

Now we've got our custom attributes and exports, but we still need to glue it together. When the catalog is loaded, the views will be tagged as exports. We just need something to import them and we can then inspect the meta data and put them in their proper places. For this, I created the RegionManager.

First, let me back up. We want to read our meta data, so I need an interface with read only properties to pull it in:

public interface ITargetRegionCapabilities
{
    ViewRegion Region { get;  }
}

Great! Now I can define region manager. We'll use the Lazy object so we can define the capabilities with the import and inspect the meta data. I put it into an observable collection and listen to the collection. When it fires, I inspect the data for new controls, and then route them to their region based on the meta data:

[Export]
public class RegionManager
{
    private readonly List<UserControl> _controls = new List<UserControl>();

    [ImportMany(AllowRecomposition = true)]
    public ObservableCollection<Lazy<UserControl, ITargetRegionCapabilities>> Controls { get; set; }

    public RegionManager()
    {
        Controls = new ObservableCollection<Lazy<UserControl, ITargetRegionCapabilities>>();
        Controls.CollectionChanged += Controls_CollectionChanged;
    }

    void Controls_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach(var item in e.NewItems)
            {
                var controlInfo = item as Lazy<UserControl, ITargetRegionCapabilities>;

                if (controlInfo != null)
                {
                    if (!_controls.Contains(controlInfo.Value))
                    {
                        ViewRegion region = controlInfo.Metadata.Region;
                        Panel panel = RegionBehavior.GetPanelForRegion(region);
                        panel.Children.Add(controlInfo.Value);
                        _controls.Add(controlInfo.Value);
                    }
                }
            }
        }
    }
}

Note: if you are wondering why I use a list and an observable collection, it's because with recomposition, MEF is free to rebuild the entire list. I need to know specifically what changed and the "new items" might include older items that were recomposed. So the internal list allows me to keep track of what I've processed while I can parse out the newer items. With custom items you'll want to make sure you have a good implementation of Equals and GetHashCode, and if you have items that will go out of focus and disappear, you'll want to switch the internal list to a list of WeakReference instead.

That's it! The last step is to make sure that the region manager participates in the entire chain of imports and exports. I could wire it up in the container, but I know the shell view model is the top of the hierarchy, so to speak, so I'll just import the region manager directly. I haven't interfaced it because it doesn't expose any methods or properties: all of the work is internal and interfaces with the static dictionary we put into our behavior.

[Import]
public RegionManager Manager { get; set; }

OK, let's fire it up. I made a short video to show you the results.

Download the Source Code for this Post

Jeremy Likness

Recently I've been having lots of conversations about the Managed Extensibility Framework (MEF), the Composite Application Library (CAL or PRISM), and how they relate. One point of confusion that many people has comes when they try to force the two solutions to work together. In a recent conversation, I mentioned that PRISM has some great features, but that if you are only using it for dynamic module loading and view management, MEF should do fine. Then I promised to post a blog with a reference project ... and here it is.

Download the source for this project

First, let me share that I love PRISM and have been working with it in almost all of my projects for the past year. My Wintellect colleague Rik Robinson has an excellent article on PRISM you can read here. You can also scan this blog with the PRISM tag. However, I've started to really enjoy working with MEF and believe it is quickly becoming the solution of choice for composite Silverlight applications ... especially with it's inclusion in the upcoming 4.0 release. In these 2 posts I'll show you how to tackle dynamic module loading and region management using exclusively MEF instead of PRISM.

I'm working with the preview 9 of the bits and showing what can be done in the current production release of Silverlight which is version 3. To start with, I simply create a new Silverlight Application. I add a folder called "MEF" and throw the bits in there, which is really two DLLs: System.ComponentModel.Composition and System.ComponentModel.Composition.Initialization. I reference those.

The "Bootstrapper" in MEF

Next I create a new empty user control called Shell.xaml (sound familiar?) that just has a grid and a text block so I know it's there. If you are familiar with PRISM, you are familiar with the concept of the Bootstrapper class to wire everything up. With MEF, we'll do it a little different. First, I go inside the shell and simply decorate it with the "export" attribute:

[Export]
public partial class Shell
{
    public Shell()
    {
        InitializeComponent();
    }
}

Next, I go into my main application class (App.cs) and add a property to import the Shell, like this:

...
[Import]
public Shell RootView { get; set; }
...

Finally, in the application start-up method, instead of newing up a "main page" which no longer exists, I simply ask MEF to satisfy my import of the shell, then assign it to the root visual:

private void Application_Startup(object sender, StartupEventArgs e)
{
    CompositionInitializer.SatisfyImports(this);
    RootVisual = RootView;
}

That's it! When I hit F5 I see the text I placed in the shell, so I know it's being placed in the root visual. We're good to go! I'm going to tackle dynamic loading first, then look at region management. I'll need some buttons to trigger the loading, so we'll want to roll a command behavior. This is one of the nice things that comes with PRISM (the commands), but let's see how easy or difficult it is to roll our own.

Custom Commands

Microsoft Expression Blend provides a set of base triggers and behaviors that make it easy to add new functionality like commanding. If you don't have the full tool, don't despair - these are also included in the free SDK you can download. I'm including a reference to System.Windows.Interactivity.

I want to do a trigger action. A trigger action allows me to act on any event, which I prefer over hard-coding just to a button click.

Before I get ahead of myself, though, let's create our command. While Silverlight 3 doesn't have a built-in command object, it does provide the ICommand interface. I'm going to do a partial implementation. I say "partial" because the interface allows for something to be passed to the command, and I'm simply raising the command and assuming null for the sake of this blog post:

public class CommandAction : ICommand 
{
    private readonly Func<bool> _canExecute;

    private readonly Action _execute; 

    public CommandAction(Action action, Func<bool> canExecute)
    {
        _execute = action;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }

    public void RaiseCanExecuteChanged()
    {
        EventHandler handler = CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }

    public event EventHandler CanExecuteChanged;
}

While I haven't looked at the code in PRISM, I assume this is very close to how they wire the DelegateCommand. We hold a function that determines if the command is enabled, and an action to call when the command is invoked. Whoever creates the CommandAction is responsible for passing those delegates in and raising "can execute changed" when appropriate.

Now I can start to work on the command behavior. Because of my unique command type, I'm just going to allow you to pass the name of the command on the data bound object and will dissect the rest. If you bind a view model with "ActionCommand" then I'll let you wire up it up that way. Because we're using MEF to bind our view models, my behavior will get wired well before the bindings happen. I'll need to know when the data context changes, so I build a data context helper. It basically uses dependency properties to listen to a "dummy" binding for changes, then calls an action when the changes happen. It looks like this and is loosely based on a previous post I made on data context changed events:

public static class DataContextChangedHandler
{
    private const string INTERNAL_CONTEXT = "InternalDataContext";
    private const string CONTEXT_CHANGED = "DataContextChanged";

    public static readonly DependencyProperty InternalDataContextProperty =
        DependencyProperty.Register(INTERNAL_CONTEXT,
                                    typeof(Object),
                                    typeof(FrameworkElement),
                                    new PropertyMetadata(_DataContextChanged));

    public static readonly DependencyProperty DataContextChangedProperty =
        DependencyProperty.Register(CONTEXT_CHANGED,
                                    typeof(Action<Control>),
                                    typeof(FrameworkElement),
                                    null);

    
    private static void _DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var control = (Control)sender;
        var handler = (Action<Control>) control.GetValue(DataContextChangedProperty);
        if (handler != null)
        {
            handler(control); 
        }
    }

    public static void Bind(Control control, Action<Control> dataContextChanged)
    {
        control.SetBinding(InternalDataContextProperty, new Binding());
        control.SetValue(DataContextChangedProperty, dataContextChanged); 
    }
}

In this case, I'm scoping specifically to a control, which is where I believe the lowest level of "is enabled" gets implemented for controls that can react to changes, so that makes sense for our behavior. When I call bind, I pass it a control and a delegate to call when that control's data context changes. Now we can build in our behavior:

public class CommandBehavior : TriggerAction<Control>
{
    public static readonly DependencyProperty CommandBindingProperty = DependencyProperty.Register(
        "CommandBinding",
        typeof(string),
        typeof(CommandBehavior),
        null);

    public string CommandBinding
    {
        get { return (string)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private CommandAction _action; 

    protected override void OnAttached()
    {
        DataContextChangedHandler.Bind(AssociatedObject, obj=>_ProcessCommand());
    }

    private void _ProcessCommand()
    {
        if (AssociatedObject != null)
        {

            var dataContext = AssociatedObject.DataContext;

            if (dataContext != null)
            {
                var property = dataContext.GetType().GetProperty(CommandBinding);
                if (property != null)
                {
                    var value = property.GetValue(dataContext, null);
                    if (value != null && value is CommandAction)
                    {
                        _action = value as CommandAction;
                        AssociatedObject.IsEnabled = _action.CanExecute(null);
                        _action.CanExecuteChanged += (o, e) => AssociatedObject.IsEnabled = _action.CanExecute(null);

                    }
                }
            }
        }
    }

    protected override void Invoke(object parameter)
    {
        if (_action != null && _action.CanExecute(null))
        {
            _action.Execute(null);
        }
    }      
}

OK, let's step through it. I'm using the System.Windows.Interactivity namespace to define a trigger action, which can be bound to any event. I'm scoping it to a control. When my behavior is attached, I'm binding to the data context changed event. I ask it to call my method to process the command when the data context changes (presumably to bind our command). When that fires, I grab the property that is named in my behavior from the data context, cast it to a command, and wire it up to automatically change whether the host control is enabled based on the CanExecute method of the control. When my behavior is invoked, I check this again and then execute.

ViewModel Glue

There's been a lot of discussion (including in this blog) around how to glue the view model to the view. I personally like to keep it simple and straightforward. Here's a view model stubbed out for the shell that lets me click a button to dynamically load a view. I want to disable the button once clicked so they don't load the view more than once.

[Export]
public class ShellViewModel
{
    public ShellViewModel()
    {
        ViewEnabled = true;
        ViewClick = new CommandAction(_ViewRequested,
                                      () => ViewEnabled);
    }

    private bool _viewEnabled;

    public bool ViewEnabled
    {
        get { return _viewEnabled; }
        set
        {
            _viewEnabled = value;
            
            if (ViewClick != null)
            {
                ViewClick.RaiseCanExecuteChanged();
            }
        }
    }

    public CommandAction ViewClick { get; set; }

    private void _ViewRequested()
    {
        ViewEnabled = false;
    }
}

Note I use a property to determine if the command is enabled, then call a method to process it when fired. We'll add more to that method in a minute. Let's get this into our shell. Because the shell is wired up in the application through the initializer, there is no need to initialize or compose again. This is done recursively. So, let me add a little bit to my shell:

<UserControl x:Class="RegionsWithMEF.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:command="clr-namespace:RegionsWithMEF.Common.Command;assembly=RegionsWithMEF.Common"
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="Main MEF Shell"/>
        <Button Content="Load Dynamic View into Region" Width="Auto" Height="Auto" Grid.Row="1">
            <interactivity:Interaction.Triggers>
                <interactivity:EventTrigger EventName="Click">
                    <command:CommandBehavior CommandBinding="ViewClick"/>
                </interactivity:EventTrigger>
            </interactivity:Interaction.Triggers>
        </Button>
    </Grid>
</UserControl>

Notice how I use the interactivity namespace to define a trigger for the button. The trigger is for the "click" event, but the way we built the behavior, it can easily fire based on other events as well. I bring in my command behavior, and point it to the "ViewClick" property on my view model. A more advanced implementation would turn that into a full blown binding property and allow binding syntax but for now we'll stick with the simple property name.

In the code behind, I wire in my view model:

[Import]
public ShellViewModel ViewModel
{
    get { return LayoutRoot.DataContext as ShellViewModel; }
    set { LayoutRoot.DataContext = value; }
}

That's it! I run the project to test it, and get a nice text block with a button. When I click the button, it disables immediately. Now let's tackle that dynamic view!

Controlling the Catalog and Container

We want to dynamically load some modules, but first we'll need to tweak our container. By default, MEF is going to create a container in our main application and compose parts to it. Unfortunately, that means when we load other modules/xap files, they won't have access to the container! We need to fix this.

First, I'll create a service to expose an AggregateCatalog that I can add other catalogs to. I want to get the catalog and add parts to it:

public interface ICatalogService
{
    void Add(ComposablePartCatalog catalog);

    AggregateCatalog GetCatalog();

}

Next, I will implement this by creating an aggregate catalog. I'm going to assume when the service is created that we want to include the currently loaded assemblies. This assumption may be wrong and down the road we might inject the catalog, but for now we'll iterate the current deployment (set of running assemblies) and pull them in to parse into our catalog:

public class CatalogService : ICatalogService
{
    private read-only AggregateCatalog _catalog = new AggregateCatalog();

    public CatalogService()
    {
        foreach (AssemblyPart ap in Deployment.Current.Parts)
        {
            StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));

            if (sri != null)
            {
                Assembly assembly = ap.Load(sri.Stream);
                _catalog.Catalogs.Add(new AssemblyCatalog(assembly));
            }
        }
    }    

    public void Add(ComposablePartCatalog catalog)
    {
        _catalog.Catalogs.Add(catalog);
    }

    public AggregateCatalog GetCatalog()
    {
        return _catalog; 
    }
}

Now we just need to tweak the main application. We'll instantiate the service, then tell it how to expose itself (sounds weird, I know, but when I bring in a module, I want it to be able to add itself to the aggregate catalog, so the catalog service must be exported). We'll let MEF know we want to use this specific container moving forward, and then we'll initialize as before. The new method looks like this:

private void Application_Startup(object sender, StartupEventArgs e)
{
    ICatalogService service = new CatalogService();
    var container = new CompositionContainer(service.GetCatalog());
    container.ComposeExportedValue(service);
    CompositionHost.Initialize(container); 
    CompositionInitializer.SatisfyImports(this);
    RootVisual = RootView;
}

Dynamic Loading of Modules

MEF Preview 9 comes with a deployment catalog that gives us what we need. First, I want to hide the implementation details of loading a view. I'll create an enumeration of views that are available (in this case, only one) and an interface to call when I'm ready to navigate to a view.

For now, I want to just grab the view and verify it's loaded. Then we'll wrap up for today and tackle the region management in the next post.

I extended my shell view model to anticipate two views. In fact, to make the example more interesting, I will load the second view into the first view. Therefore, the second button is only enabled once the first button has been clicked, like this:

SecondViewClick = new CommandAction(
    _SecondViewRequested,
    () => !ViewEnabled && SecondViewEnabled);

Here's our views:

public enum ViewType
{
    MainView,
    SecondView
}

And the interface for our view navigation:

public interface INavigation
{
    void NavigateToView(ViewType view);
}

So now I can go back to my view model and wire in the navigation, as well as make the call. Here is the modified code:

[Import]
public INavigation Navigation { get; set; }

private void _ViewRequested()
{
    ViewEnabled = false;
    Navigation.NavigateToView(ViewType.MainView);
}

private void _SecondViewRequested()
{
    SecondViewEnabled = false;
    Navigation.NavigateToView(ViewType.SecondView);
}

Now I will add my modules. As I mentioned, I just want them to load for now. I can deal with the views later. So I create two more Silverlight applications in my solution called "DynamicModule" and then "SecondDynamicModule.cs" ... yes, the second is a typo because I thought I was adding a class, and was too lazy to re-factor it. So there. I imagine when I load a module I'll want it to do perform some "introductory" functions, so let's define an initialization interface:

public interface IModuleInitializer
{
    void InitModule();
}

In both of my dynamic modules, I add a class that implements this interface and export it. I gave them different names to show it's the interface the matters, but here's what one looks like (right now I just return, but I can set the breakpoint there to test when and if the module is loaded and called):

[Export(typeof(IModuleInitializer))]
public class ModuleInitializer : IModuleInitializer
{
    public void InitModule()
    {
        return; 
    }              
}

OK, now I can implement my INavigation interface. We're going to do two things. First, we'll map views to modules so we can dynamically load them using the DeploymentCatalog. Second, we'll import a collection of module initializers. This is the super-cool feature of MEF: recomposition. When we load the module and put it in our main catalog, it will recompose. This should fire a change to our collection of initializers. We can take the new items and call them, and we'll be initialized. Here's what it looks like:

[Export(typeof(INavigation))]
public class ViewNavigator : INavigation 
{        
    [Import]
    public ICatalogService CatalogService { get; set; }

    [ImportMany(AllowRecomposition = true)]
    public ObservableCollection<IModuleInitializer> Initializers { get; set; }

  private readonly List<IModuleInitializer> _modules = new List<IModuleInitializer>();

    private readonly Dictionary<ViewType, string> _viewMap =
        new Dictionary<ViewType, string>
            {
                { ViewType.MainView, "DynamicModule.xap" },
                { ViewType.SecondView, "SecondDynamicModule.cs.xap" }
            };   

    private readonly List<string> _downloadedModules = new List<string>();

    public ViewNavigator()
    {
        Initializers = new ObservableCollection<IModuleInitializer>();
        Initializers.CollectionChanged += Initializers_CollectionChanged;
    }
    
    void Initializers_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach(var item in e.NewItems)
            {
                var initializer = item as IModuleInitializer; 
                if (initializer != null)
                {
                    if (!_modules.Contains(initializer))
                    {
                        initializer.InitModule();
                        _modules.Add(initializer);
                    }
                }
            }
        }
    }                                                                                              
  
    public void NavigateToView(ViewType view)
    {
        if (!_downloadedModules.Contains(_viewMap[view]))
        {
            var catalog = new DeploymentCatalog(_viewMap[view]);
            CatalogService.Add(catalog);
            catalog.DownloadAsync();
            _downloadedModules.Add(_viewMap[view]);
        }
    }               
}

Right now the navigate to view isn't very flexible. It loads the catalogs but doesn't do anything with the views. I'm also not handling errors when the XAP isn't loaded. We are tracking modules and xaps that were already loaded, so we don't load them again or re-initialize the module. We'll get to that in the next installment when we wire in regions. For now, we can put a breakpoint in the "return" of the init modules, fire up the application, and click our buttons to watch them get dynamically loaded into the system (you can use Fiddler to watch the packets come over the wire). Pretty exciting!

In the next installment, I'll show you how MEF will handle region management.

Download the source for this project

Jeremy Likness

The Silverlight team recently posted a blog entry entitled "Vancouver Olympics - How'd we do That?" in which they detailed the massive effort across multiple partners to pull together the on-line solution for streaming HD videos, both live and on demand.

This was an exciting post for Wintellect and me because it detailed the effort we contributed to making the project a success. What's more important to me for the Silverlight community, however, is that you don't overlook the key detail they posted on the blog:

Development of a Silverlight application to interface with the service agents via WCF. This tool allows Microsoft to quickly publish new configuration files (such as web.config and clientaccesspolicy.xml) to groups of servers, as well as dynamically manipulate configuration settings through a visual interface (for example, turning off compression on a remote smooth streaming server when required) on multiple remote servers at once.

This is important because as a Silverlight developer I am constantly bombarded with questions about how viable Silverlight is, if it is ready for the enterprise and what practical application it has for business. This is a specific example where it was the right tool for the right job.

I won't go into more details about the tool other than what Microsoft has publicly shared, but I wanted to emphasize that this is another example of how Silverlight helps to solve real world problems. When looking at the requirements for the health monitoring, we had several options for a solution. In this case, WPF wouldn't have worked because they would have had to remote into the environment in order to access the tool. However, using ASP.NET and JavaScript would have required jumping through some major hoops and use of heavy controls to correctly render the user interface they required. The tool essentially parses any XML-base configuration file and allows on-line navigation and updates to that document. While this would have been possible using script, it would have taken much longer and required an extended cycle of testing to stabilize.

Due to Silverlight's unique data-binding model and full LINQ to XML support, we were able to build a solution quickly and effectively. We were also able to use the unit testing framework to build hundreds of unit tests that helped ensure a stable, thorough, and well-tested solution. Again, using scripting would have required more complicated tools that simulated user-clicks, etc. With Silverlight, we can place controls on a test surface and simulate the click events to test everything from behaviors down to internal class methods.

PRISM, or the Composite Application Library, was also crucial with the success of keeping the module light weight. There were literally dozens of functions the tool could provide but only a few might be used at any given time, so we separated the functions into independent modules that dynamically loaded as needed to provide a streamlined experience.

While I was excited to work on the project with my company, I am even more excited that it demonstrates yet again how Silverlight is the right tool, right here, right now for enterprise class applications. This is another "case study" to add to your arsenal as you answer questions about, "Is it ready?" or "Has it been done before." I believe the fact that it was so crucial both in the front end (with the live streaming experience) and back-end (with the management tools) for an incredible event like the Olympics really proves how mature and ready Silverlight is for business class applications.

Jeremy Likness

One reason a developer would use a technology like MEF is to, as the name implies, make an application extensible through a process called discovery. Discovery is simply a method for locating classes, types, or other resources in an assembly. MEF uses the Export tag to flag items for discovery, and the composition process then aggregates those items and provides them to the entities requesting them via the Import tag.

Download the source code for this example

It occurred to me when working with PRISM and MEF (see the recap of my short series here) that some of this can be done through traditional means and I might be abusing the overhead of a framework if all I'm doing is something simple like marrying a view to a region.

Challenges with PRISM include both determining how views make it into regions and how to avoid magic strings and have strict type compliance when dealing with regions. This post will address one possible solution using custom attributes and some fluent interfaces.

Fluent Interfaces

Fluent interfaces simply refers to the practice of using the built-in support for an object-oriented language to create more "human-readable" code. It's really a topic in and of itself, but I felt it made sense to simplify some of the steps in this post and introduce some higher level concepts and examples along the way.

There are several ways to provide fluent interfaces. One that is built-in to the C# language is simply using the type initializer feature. Instead of this:


public class MyClass 
{
   public string Foo { get; set; }
   public string Bar { get; set; }

   public MyClass() 
   {
   }

   public MyClass(string foo, string bar) 
   {
       Foo = foo; 
       Bar = bar;
   } 
}

Which results in code like this:


...
MyClass myClass = new MyClass(string1, string2); 
...

Question: which string is foo, and which string is bar, based on the above snippet? Would you consider this to be more readable and "self-documenting"?


...
MyClass myClass = new MyClass { Foo = string1, Bar = string2 };
...

It works for me! So let's do something simple in our PRISM project. If you've worked with PRISM, then you'll know the pattern of creating a Shell and then assinging it to the root visual in a Bootstrapper. The typical code looks like this in your Bootstrapper class:


protected override DependencyObject CreateShell()
{
   Shell shell = new Shell(); 
   Application.Current.RootVisual = shell;
   return shell; 
}

That's nice, but wouldn't it also be nice if you could do something simple and readable, like this? Keep in mind we're not cutting down on generated code (and in fact, sometimes fluent interfaces may increase the amount of generated code, which is a consideration to keep in mind), but we're focused on the maintainability and readability of the source code.


protected override DependencyObject CreateShell()
{
   return Container.Resolve<Shell>().AsRootVisual();             
}

In one line of code I'm asking the container to provide me with the shell (I do this as a common practice as opposed to creating a new instance so that any dependencies I may have in the shell will be resolved), then return it "as root visual." I think that is pretty readable, but how do we get there?

The answer in this case is using extension methods. In my "common" project I created a static class called Fluent which contains my fluent interfaces (this is for the example only and would not scale in production ... you will want to segregate your interfaces into separate classes related to the modules they act upon). In this static class, I create the following extension method:


public static UserControl AsRootVisual(this UserControl control)
{
    Application.Current.RootVisual = control;
    return control;
}

An extension method does a few things. By using the keyword this on the parameter, it tells the compiler this method will extend the type. The semantics in the code look you are calling something on the UserControl, but the compiler is really taking the user control, then calling the method on the static class and passing the instance in. It is common for the extension methods to return the same instance so they can be chained. In this case, we simply assign the control to the root visual, then return it so it can be used elsewhere. We're really doing the same thing we did before, but adding a second method call, in order to make the code that much more readable.

One important concern to have and address with fluent interfaces is the potential for "hidden magic." What I mean by this is the extension methods aren't available on the base class and only appear when you include a reference to the class with the extensions. This may make them less discoverable based on how you manage your code. It also means you will look at methods that aren't part of the known interface. It's not difficult to determine where the method comes from. Intellisense will flag extension methods as extensions, and you can always right click and "go to definition" to see where the method was declared.

Auto-discoverable Views

I have two main goals with this project: the first is to be able to tag views so they are automatically discovered and placed into a region, and the second is to type the region so I'm not using magic strings all over the place. My ideal solution would allow me to add a view to a project, tag it with a region, and run it, and have it magically appear in that region. Possible? Of course!

Typing the Regions

I am going to type the regions to avoid magic strings. Because the main shell defines the regions, I'm fine with the strings there ... that is sort of the "overall definition", but then I want to make sure elsewhere in the code I can't accidentally refer to a region that doesn't exist. My first step is to create a common project that all other modules can reference, and then add an enumeration for the regions. The enumeration for this examle is simple:


namespace ViewDiscovery.Common
{
   public enum Regions
    {
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight
    }
}

Enumerations are nice because I can call ToString() and turn it into the string value of the enumeration itself. I decided to adopt the convention "Region." when tagging it in the shell, so my shell looks like this:


<UserControl x:Class="ViewDiscovery.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:region="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center" Text="View Discovery"/>       
        <ItemsControl Grid.Row="1" Grid.Column="0" region:RegionManager.RegionName="Region.TopLeft"/>
        <ItemsControl Grid.Row="1" Grid.Column="1" region:RegionManager.RegionName="Region.TopRight"/>
        <ItemsControl Grid.Row="2" Grid.Column="0" region:RegionManager.RegionName="Region.BottomLeft"/>
        <ItemsControl Grid.Row="2" Grid.Column="1" region:RegionManager.RegionName="Region.BottomRight"/>
    </Grid>
</UserControl>

This is just a simple 2x2 grid with a region per cell. I used the ItemsControl so each cell can host multiple views. We're off to a good start! Now let's figure out how to tag our views.

The Custom Attribute

Custom attributes are powerful and easy to implement. I want to be able to tag a view as a region using my enumeration, so I define this custom attribute:


namespace ViewDiscovery.Common
{
    [AttributeUsage(AttributeTargets.Class,AllowMultiple=false)]
    public class RegionAttribute : System.Attribute
    {
        const string REGIONTEMPLATE = "Region.{0}";

        public readonly string Region;

        public RegionAttribute(Regions region)
        {
            Region = region.ToString().FormattedWith(REGIONTEMPLATE);              
        }
    }
}

Notice that I don't allow multiple attributes and that this attribute is only valid when placed on a class. Attributes can take both positional parameters (defined in the constructor) and named parameters (defined as properties). In this case, I only have one value so I chose to make it positional. When the region enumeration is passed in, I cast it to a string and then format it with the prefix, so that Regions.TopLeft becomes the string Region.TopLeft. Notice I snuck in another fluent interface, the FormattedWith. To me, that's a sight prettier than "string.Format" if I'm only dealing with a single parameter. The extension to make this happen looks like this:


public static string FormattedWith(this string src, string template)
{
    return string.Format(template, src);
}

Now that we have a tag, we can create a new module and get it wired in. I created a new project as a Silverlight Class Library (sorry, this example doesn't do any fancy dynamic module loading), built a folder for views, and tossed in a view. The view simply contains a grid with some text:


<Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="I am in ModuleOne." Grid.Row="0"/>
        <TextBlock Text="I want to be at the top left." Grid.Row="1"/>
    </Grid>

Tagging the view was simple. I went into the code-behind, added a using statement to reference the common project where my custom attribute is defined and then tagged the view with the attribute. Here's the code-behind with the tag:


namespace ViewDiscovery.ModuleOne.Views
{
    [Region(Regions.TopLeft)] 
    public partial class View : UserControl
    {
        public View()
        {
            InitializeComponent();
        }       
    }
}

So now it's clear where we want the view to go. Now how do we get it there?

Discovering the Views

The pattern in PRISM for injecting a module is for the module to have an initialization class that implements IModule and then adds the views in the module to the region. We want to do this through discovery. To facilitate this, I created a base abstract class for any module that wants auto-discovered views. The class looks like this:


public abstract class ViewModuleBase : IModule
{
    protected IRegionManager _regionManager;

    public ViewModuleBase(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    #region IModule Members

    public virtual void Initialize()
    {
        IEnumerable<Type> views = GetType().Assembly.GetTypes().Where(t => t.HasRegionAttribute());

        foreach (Type view in views)
        {
            RegionAttribute regionAttr = view.GetRegionAttribute(); 
            _regionManager.RegisterViewWithRegion(regionAttr.Region, view); 
        }
    }

    #endregion
}

The code should be very readable. We enforce that the region manager must be passed in by creating a constructor that takes it and stores it. We implement Initialize as virtual so it can be overridden when needed. First, we get the assembly the module lives in, then grab a collection of types that have our custom attribute. Yes, our fluent interface makes this obvious because we can do type.HasRegionAttribute(). The extension method looks like this:


public static bool HasRegionAttribute(this Type t)
{
    return t.GetCustomAttributes(true).Where(a => a is RegionAttribute).Count() > 0; 
}

This takes the type, grabs the collection of custom attributes (using inheritance in case we're dealing with a derived type) and returns true if the count of our attribute, the RegionAttribute, is greater than zero.

Next, we iterate those types and get the region attribute, again with a nice, friendly interface (GetRegionAttribute) that looks like this:


public static RegionAttribute GetRegionAttribute(this Type t)
{
    return (RegionAttribute)t.GetCustomAttributes(true).Where(a => a is RegionAttribute).SingleOrDefault();
}

Now we have exactly what we need to place the view into the region: the region it belongs to, and the type. So, we register the view with the region and we're good to go!

In my module, I add a class for the module initializer called ModuleInit. I'm only using the auto-discovery so there is nothing more than an implementation of the base class that passes the region manager down:


namespace ViewDiscovery.ModuleOne
{
    public class ModuleInit : ViewModuleBase
    {
        public ModuleInit(IRegionManager regionManager)
            : base(regionManager)
        {
        }
    }
}

Now we go back to the main project and wire in the module catalog. I'm not using dynamic modules so I just reference my modules from the main project and register them by type:


protected override IModuleCatalog GetModuleCatalog()
{
    return new ModuleCatalog()
        .WithModule(typeof(ModuleOne.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module One"));            
}      

OK, so I had some fun here as well. I wanted to extend the module catalog to allow chaining WithModule for adding multiple modules, and be able to take a type name as a string, then make it a module with a name. Working backwards, we turn a string into a named ModuleInfo class like this:


public static ModuleInfo AsModuleWithName(this string strType, string moduleName)
{
    return new ModuleInfo(moduleName, strType);
}

Next, we extend the catalog to allow chaining on new modules like this:


public static ModuleCatalog WithModule(this ModuleCatalog catalog, ModuleInfo module)
{
    catalog.AddModule(module);
    return catalog;
}

Notice this simply adds the module then returns the original catalog.

At this point, we can run the project and see that the view appears in the upper left.

View Discovery with One View

I then added a second view with a rectangle:


<UserControl x:Class="ViewDiscovery.ModuleOne.Views.Rectangle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <Rectangle Width="100" Height="100" Fill="Red" Stroke="Black"/>
    </Grid>
</UserControl>

... and tagged it:


namespace ViewDiscovery.ModuleOne.Views
{
    [Region(Regions.TopRight)] 
    public partial class Rectangle : UserControl
    {
        public Rectangle()
        {
            InitializeComponent();
        }
    }
}

An finally compiled and re-ran it. The rectangle shows up in the upper right, as expected:

View Discovery with Two Views

Next, I added a second module with several views ... including a few registered to the same cell. Adding the new module to the catalog was easy with the extension for chaining modules:


protected override IModuleCatalog GetModuleCatalog()
{
    return new ModuleCatalog()
        .WithModule(typeof(ModuleOne.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module One"))
        .WithModule(typeof(ModuleTwo.ModuleInit).AssemblyQualifiedName.AsModuleWithName("Module Two"));            
}   

Compiling and running this gives me the final result:

View Discovery with Multiple Views

And now we've successfully created auto-discoverable views that we can strongly type to a region and feel confident will end up being rendered where they belong.

Download the source code for this example

Jeremy Likness

Series recap:

In the final part of this series, I will show a dynamically loaded module (using PRISM) that takes full advantage of MEF.

Here is a preview of the final product, illustrating the different modules and areas I have pulled together to demonstrate (click for a full resolution view):

Download the Source for this Example

Why even bother with dynamic modules? Dynamic module loading can be a powerful way to build scalable (and more stable) applications in Silverlight. By creating dynamic modules, you ensure the user only loads what they need, when they need it. The dynamic module only comes into play when the user demands a feature that requires the module.

Before we dive into the new MEF-based module, let's break down a few best practices when using dynamically loaded modules:

  • The best option I've found for this so far is to use PRISM's "on demand" functionality for loading modules.
  • Typically, you will want to put your main dependencies in the "main" or "host" Silverlight project.
  • Create a new dynamic module by adding a Silverlight Application project, not a Silverlight Class Library.
  • Use a XAML catalog to reference the dynamic modules. This gives PRISM something to resolve when the new module is requested, but avoids direct dependencies on the satellite modules by the main application.
  • When referencing projects or DLLs that are part of the main application in a satellite module, be sure to set "copy local" to false. This ensures these are not compiled into the XAP, because the module can leverage the fact that the main module has already loaded the dependencies. This leads to very lightweight XAP files.

When everything comes together as planned, you can scan traffic with a tool like Fiddler to see what happens. Take a look at this example. Here, you can clearly see the satellite modules are loaded dynamically. In fact, the MEF module, which displays a list and dynamically displays a child view, weighs in at only 5,000 bytes!

Click here to view the Fiddler snapshot

I started by adding a new Silverlight Application and calling it MEFModule.

The MEF ViewModel

The MEF view model looks like this:


[Export]
public class MoreStuffViewModel : IPartImportsSatisfiedNotification
{        
    private IService _service; 

    [Import]
    public IService Service
    {
        get { return _service; }
        set
        {
            _service = value;
            if (_service != null)
            {
                _service.GetMoreStuff(_ServiceLoaded); 
            }
        }
    }

    [ImportMany("MoreStuff",AllowRecomposition=true)]
    public List<string> ImportedStuff { get; set; }

    [Import]
    public IRegionManager RegionManager { get; set; }

    public DelegateCommand<object> DynamicViewCommand { get; set; }

    [Import("DynamicView")] 
    public object DynamicView { get; set; }

    private ObservableCollection<string> _listOfMoreStuff;

    public MoreStuffViewModel()
    {
        // initialize all lists
        _listOfMoreStuff = new ObservableCollection<string>();
        DynamicViewCommand = new DelegateCommand<object>(o =>
            {
                RegionManager.RegisterViewWithRegion("MainRegion", () => DynamicView);
            });
    }

    private void _ServiceLoaded(List<string> values)
    {
        foreach (string value in values)
        {
            _listOfMoreStuff.Add(value);
        }
    }
       
    public ObservableCollection<string> ListOfMoreStuff 
    {
        get
        {
            return _listOfMoreStuff;
        }

        set
        {
            _listOfMoreStuff = value; 
        }
    }

    #region IPartImportsSatisfiedNotification Members

    public void OnImportsSatisfied()
    {
        foreach (string importedValue in ImportedStuff)
        {
            _listOfMoreStuff.Add(importedValue);
        }
    }

    #endregion
}

I've purposefully loaded this view model with tons of goodies to help understand and take advantage of MEF to its fullest. You'll notice two things right away about the view model: it is exported using the Export attribute, and it implements an interface called IPartImportsSatisfiedNotification. When you implement this interface, MEF will automatically call OnImportsSatisfied, allowing you to react to the new imports.

You'll notice I have a collection called ImportedStuff that imports a contract with a magic string (tip: in a production project this would probably be a type or an enumeration or at least a static class with a constant to allow for type checking) called MoreStuff. We'll give this collection what it needs somewhere else, for now it is simply waiting for imports and when those imports are satisfied, we merge them into our master ListOfMoreStuff collection.

We also reference IService. If you remember, when we set that up back in part 1, we went ahead and added an Export tag. Here, we import it. Notice that on the setter, when the import happens, I go ahead and call the GetMoreStuff method, which returns me the Spanish numbers. When these are loaded, we merge them into our master ListOfMoreStuff. So the list will contain the results of the service call and any MoreStuff imports we may find.

We also want to dynamically display another view, but we don't know what that view is yet. Remember in part 2 I explicitly set the export value of IRegionManager using Unity to resolve it? This is where we will import it!

The DynamicViewCommand gives us a command to bind to in order to show that view. The view gets imported with another magic string (again, just stating I know we don't like them, but they are there for the sake of brevity in this example only) called DynamicView. In the constructor for the view model, we bind the command to a call to RegisterViewWithRegion and pass in the dynamic view.

This demonstrates how powerful MEF really is: we are able to specify an action to dynamically show a view here in the view model without any prior knowledge of where the view is or even what it is composed of!

The rest of the view model code simply initializes lists, combines them, etc. We've got our view model in place. How about some views that use it?

The MEF Views

In the views folder, I created two views. The first or "main" view is simply called MoreStuffView and it binds to the ListOfMoreStuff collection as well as the dynamic view command:


<ListBox ItemsSource="{Binding ListOfMoreStuff}">
   <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button Grid.Column="1" cal:Click.Command="{Binding DynamicViewCommand}" Content="Add View"/>

The code behind requires two pieces: first, we need to import the view model and bind it:


[Import]
public MoreStuffViewModel ViewModel
{
   get { return (MoreStuffViewModel)LayoutRoot.DataContext; }
   set { LayoutRoot.DataContext = value; }
}

Next, we need to call our friend, the PartInitializer class, to satisfy all of the imports in the constructor:


public MoreStuffView()
{            
    InitializeComponent();           
    PartInitializer.SatisfyImports(this);                
}

And that's it ... all of the services, exports, etc will be wired in elsewhere. I created a second view called DynamicView. This view simply contains a text block that indicates it was dynamically loaded. Remember how we had our "magic string" import for a view in the view model? Here, we will export the dynamic view in the code behind. There is only one change to the auto-generated code behind file, and that is to add the Export tag:


[Export("DynamicView")]
public partial class DynamicView : UserControl
{
    public DynamicView()
    {
        InitializeComponent();
    }
}

That's it for the view model and the views!

Providing Exports

The exports can obviously be supplied in a variety of ways. For this example, I simply created a class and exported a few values to demonstrate that the imports were working and merging with the main list:


public class MoreStuffExports
{        
    [Export("MoreStuff")]
    public string Item1
    {
        get { return "MEF Export 1"; }
    }

    [Export("MoreStuff")]
    public string Item2
    {
        get { return "MEF Export 2"; }
    }            
}

The MEF Module Initializer

Now it's time to wire everything together. There is actually almost nothing to the module initializer class. Because we base it on the PartModule we defined in the last post, the MEF-specific actions happen as part of the base class. In this class, we simply register the main view:


public class MEFInit : PartModule
{
    IRegionManager _regionManager;

    public MEFInit(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    #region IModule Members

    public override void Initialize()
    {
        base.Initialize(); // gotta call base for the MEF magic to happen
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(MoreStuffView));
    }

    #endregion
}

That's it!

Conclusion

The goal of this this small series is to demonstrate how well PRISM and MEF work together, and how accessible modular and extensible applications can be in Silverlight 3. You've learned several ways to marry the view model to the view using different types of dependency injection containers and patterns. You've also seen how to take advantage of dynamically loaded modules to create application extensions that have an extremely small footprint but can easily integrate with the flexibility provided by both Unity and MEF in the context of PRISM.

Download the Source Code for this example

Jeremy Likness

In the first part of this series, we explored using the Unity container to bind the view model to the view. The next logical step is to explore how to use MEF. PRISM provides several useful mechanisms that relate directly to views and modules, such as the region manager and the module manager. This allows us to dynamically assign views to regions on the display and dynamically load modules.

Logically, it seems we could create a MEF module, dynamically load it through PRISM, and glue its parts together as well. We'd probably start with a view model that looks like this:


[Export]
public class MEFViewModel 
{
    [Import]
    public IService { get; set; }

    public DelegateCommand<object> Command { get; set; }
}

And then easily pull it into a view like this:


public partial class MEFView : UserControl
{
   [Import]
   public MEFViewModel ViewModel { get; set; }

   public MEFView() 
   {
      InitializeComponent();
      PartInitializer.SatisfyImports(this);
      LayoutRoot.DataContext = ViewModel; 
   }
}

That is the essence of how it works, right?

Unfortunately, if you try this (like I did) you'll quickly find that your parts won't compose. You'll receive errors, and the view won't render. The view model won't get instantiated. Why is this? Where did we go wrong?

Stable Composition

The first thing to understand before we can start fixing things is a concept known as "Stable Composition." This feature, which is described in detail in Glenn Block's blog entry Stable Composition in MEF, is a fail-safe used to prevent unstable parts from being composed into your application. The pro is that if a failure exists somewhere down the chain of imports and exports, the part is simply discarded and not considered for import. The con is that it takes a little bit more debugging and troubleshooting to discover exactly why the composition failed. In this case, we were unable to find an import for IService, so the view model could not be imported into the view, which caused the PartInitializer to complain because, well, it couldn't "get no satisfaction."

If you recall in part 1, we flagged our service implementation with the Export property. What went wrong?

MEF and Silverlight XAP files

One frustration I've had with a lot of online examples of using MEF with Silverlight is that everything is contained within a single XAP file. For larger, scalable, and pluggable applications, this simply won't be the case. This makes straightforward examples suddenly break when you start to distribute your classes between various projects or PRISM modules.

The PartInitializer class is a helper class in MEF that helps compose parts where they might not normally be seen. By this I mean in pages like user controls that are constructed by the XAML parser. The XAML parser doesn't understand MEF, so it is unaware of how to reach out and satisfy imports. By including the PartInitializer in the constructor and calling the SatisfyImports method with the view, this allows MEF to inspect the view and XAML-generated parts and begin composition.

By default, however, the PartInitializer only "knows" about the current XAP file. It has no way of knowing what other assemblies and XAP files exist in the project. In our example, because the interface for the service and implementation both exist in separate projects (and XAP files), MEF choked on the import because it did not know where to find the export.

The Silverlight 4 toolkit includes the PackageCatalog. This facilitates dynamic loading of XAP files as well as composition using different XAP files. In Silverlight 3, without the benefit of this type of catalog (which may become available in future previews), we must build our own infrastructure to facilitate the composition across XAP boundaries. (Tip: if you want to use the package catalog in Silverlight 3, the source is available for the toolkit).

Introducing the Catalog Service

To begin, we need a service for the modules to communicate with and help aggregate catalogs between XAP files. This is the piece that Glenn Block helped build and explained to me, so many thanks to him. Be sure to subscribe to his blog and Twitter feed, lots of useful information there!

We start with a simple definition:


public interface ICatalogService 
{
   void Add(ComposablePartCatalog catalog); 
}

The ComposablePartCatalog is the base catalog class that allows us to add catalogs to our service.

In the implementation of the service, we use an AggregateCatalog to hold the other catalogs in one place:


public class CatalogService : ICatalogService
{
    private AggregateCatalog _catalog;

    public CatalogService(AggregateCatalog catalog)
    {
        _catalog = catalog;
    }

    public void Add(ComposablePartCatalog catalog)
    {
        _catalog.Catalogs.Add(catalog);
    }
}

Notice that the constructor expects us to pass a catalog. Where does this catalog come from?

This is where things will start to get a little interesting, so bear with me.

First, in our bootstrapper, we'll want to aggregate all of the existing parts into one catalog. Let's take a look at a new method GetHostCatalog that creates a new AggregateCatalog and returns it:


private AggregateCatalog GetHostCatalog()
{
    var catalog = new AggregateCatalog();

    foreach (AssemblyPart ap in Deployment.Current.Parts)
    {
        StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));
        
        if (sri != null)
        {
            Assembly assembly = ap.Load(sri.Stream);        
            catalog.Catalogs.Add(new AssemblyCatalog(assembly));
        }
    }

    return catalog;
}

So the "deployment" is the active Silverlight application. We iterate each part, then stream the actual assembly. The assembly is then added to the catalog. This will take care of all of the assemblies available when the bootstrapper runs. Let's wire that in and then see how we can grab the dynamic modules as well.


private void InitializeCompositionHost()
{
    var catalog = GetHostCatalog();
    var container = new CompositionContainer(catalog);
    container.ComposeExportedValue<IService>(Container.Resolve<IService>()); 
    container.ComposeExportedValue<IRegionManager>(Container.Resolve<IRegionManager>()); 
    Container.RegisterInstance<ICatalogService>(new CatalogService(catalog));
    CompositionHost.InitializeContainer(container);
}

Now we are starting to see pure play between Unity and MEF. First, we start the catalog. Next, we create a composition container using the catalog. Now we can interface between Unity and MEF using the ComposeExportedValue method. Here, I am providing MEF with an explicit export for a given import, and using the Unity container ("big C") to resolve the dependencies. This will give us the exports for IService and IRegionManager. The Unity container is also given a single instance of ICatalogService.

Finally, a very key step is to tell MEF to use our special container. One of the features of MEF is that it effectively hides the container from your view. You can literally build applications using nothing other than the Import and Export attributes. However, sometimes we need to explicitly manage or configure the container. This is one of those cases: we've built our own container with the aggregate catalogs and even provided explicit hints to the container for marrying imports and exports. To allow the PartInitializer to use our container, we register it through a static method on the composition host. This is the InitializeContainer call you see, passing it the MEF container ("little c").

All of this happens in the bootstrapper. We'll call the InitializeCompositionHost from an override used to configure the Unity container: ConfigureContainer.

Now we've set up the initial application and configured our container. We still need a way to register dynamic modules as they are loaded. For this, we'll go to our common project and make a new base class for modules that will play in the MEF space. Instead of basing these modules on IModule, we'll base them on the new base class that implements IModule, called PartModule. This is what the part module base class looks like:


public abstract class PartModule : IModule
{
    [Dependency]
    public ICatalogService CatalogService { get; set; }

    public virtual void Initialize()
    {
        var assembly = this.GetType().Assembly;

        var types = assembly.GetTypes().Where(t => !typeof(IModule).IsAssignableFrom(t));

        CatalogService.Add(new TypeCatalog(types));
    }
}

First, we go ahead and implement IModule as is required by PRISM for a module. Next, notice that we let Unity provide us our singleton ICatalogService instance by providing a property and decorating it with the Dependency attribute.

Next, we implement Initialize and grab the assembly. We grab all of the types available in the assembly and add them to our aggregate catalog using a type catalog. This literally makes all types in the current assembly available for export. Notice, however, we ignore IModule ... we don't want to create a circular reference or dependency and accidentally import the module itself!

Now we have all of the pieces in place to make PRISM friendly with MEF. We can now export and import across XAP boundaries and even handle dynamically loaded modules (in this case, we're letting PRISM handle loading and managing the modules).

There is no source for this entry because there is nothing to show yet. In the next and final installment, I will create a dynamic module based on MEF and complete the loop by demonstrating yet another dynamically loaded module along with a dynamically inserted view, all using MEF to resolve dependencies for us.

Jeremy Likness

PRISM, also known as Composite WPF, has established itself as a very popular framework for building modular, scalable Silverlight applications. A newer contender, the Managed Extensibility Framework (MEF), has also grown in popularity. In fact, these two frameworks have left people scratching their heads wondering which one to use, when, how, and why.

Download the source code for this project.

Special note: the source won't run "as is." You need to take two steps: first, right click the PRISMMEF.Web project and choose, "set as start project." Second, right click the PRISMMEFTestPage.aspx and choose "set as start page." Then the project will run fine.

MEF will be packaged with Silverlight 4, and indeed has several preview releases available that will work on Silverlight 3 and 4. PRISM is coming out with newer releases that embrace the MEF framework. In fact, both frameworks work well together and know how to talk to each other's containers.

In this series of posts I want to explore some concepts and aspects of solving the Silverlight application problem using both PRISM and MEF. I will use PRISM primarily for its ability to integrate views into regions, to dynamically load modules, and to provide an abstract messaging contract with the event aggregator. MEF will be used for extensibility and to really tap into the ability to go out, find exports, and glue them into imports.

My primary goal in this short series will be to establish patterns for binding the view model to the view, and to dynamically load views and modules. We'll look at how to do this in the current version of Silverlight 3. It's important to note that future MEF releases may address some of the issues I tackle here and will make some workarounds obsolete, so stay tuned with that. I also want to express my sincere gratitude to Glenn Block (or, if you prefer, @gblock), a key member of the MEF team (and former member of the PRISM team, I believe, as well) for helping me with some of these examples and providing invaluable insights related to the inner workings of MEF.

Today we're going to leave MEF to the side and focus on what PRISM and the IoC container that comes with it, Unity, provide. The challenge is something I see discussed quite often, and that is how to meld the view model and the view together. Some people seem to abhor using code-behind at all, so I want to tackle a few solutions to this while also providing my own pragmatic way that, ahem, does use a little bit of code behind (and explain why I really don't care).

So, let's get started. We're going to have three main views today. The first will be the outer shell, which binds to a message and a button to dynamically load a second module. The module will have a second view that, in turn, will activate a third view. I am also going to show you three ways to bind your view model to your view using Unity. I will use view models with depedencies because these are the ones that cannot be referenced directly in XAML because the XAML parser doesn't implicitly know how to resolve dependencies.

The pattern for establishing a PRISM project is fairly well-established by now. We create a new Silverlight Application, blow away the default user control provided, then make a shell and a bootstrapper class that inherits from UnityBootstrapper.

I'll also add a class project called "common" to hold interfaces, base clases, and other services or parts that are used by the entire application.

In common, we'll define our service behavior. This could be wired to a "real" service but for now is just a mock one to demonstrate how these various methods work. The service contract looks like this:

public interface IService
{
   void GetStuff(Action<List<string>> action);

   void GetMoreStuff(Action<List<string>> action); 
}

I'm using the method outlined in Simplifying Asynchronous Calls in Silverlight Using Action. We call the service, and send it a method to call back on us with the returned value. In this case, it is just two different lists of strings.

I created a separate project "service" to implement the interface. The code is simple, and is also the first place I use a little MEF. I'm simply exporting the service so that if I want to use MEF to import it, I can. Today we'll let Unity wire it up and I'll show you how.

The service implementation is straightforward. Again, we'll add some MEF so it's ready when we look into it. In this case, instead of calling a "real" service, I just hit the callback with a pre-determined list of numbers that most will recognize. The second method does the same, only in Spanish. The class looks like this:

[Export(typeof(IService))]
public class Service : IService
{
    public void GetStuff(Action<List<string>> action)
    {
        action(new List<string> { "One", "One", "Two", "Three", "Five", "Eight", "Thirteen" });
    }

   public void GetMoreStuff(Action<List<string>> action)
    {
        action(new List<string> { "Uno", "Uno", "Dos", "Tres", "Cinco", "Ocho", "Trece" }); 
    }

    #endregion
}

Method 1: Provider

So now we can work on our view models. The main shell simply shows a title and exposes a button to click to dynamically load another module. The model looks like this:

public class ShellViewModel 
{
    const string APPLICATION = "This is the PRISM/MEF project demonstration.";

   public ShellViewModel(IModuleManager moduleManager) 
    {
        ModuleCommand = new DelegateCommand<object>(o =>
        {
            moduleManager.LoadModule("Module");
        });           
    }

    public ShellViewModel()
    {            
    }

    public string Title
    {
        get { return APPLICATION; }
    }

    public DelegateCommand<object> ModuleCommand { get; set; }    
}

Our problem with instantiating this in XAML is that the XAML parser doesn't understand how to resolve the dependency for IModuleManager. This is needed because I am going to dynamically load another module when you click the button bound to the ModuleCommand. As I mentioned, there are several ways to make the glue and one way is to use a provider.

The provider is a base class which has only two purposes. First, it is typed to a class so that multiple view models will generate multiple type instances. We need this so we can have different ways to resolve our classes. Second, it exposes a mechanism to resolve our models. In this way, I'm not tightly coupled to Unity. I recognize that there has to be some external force supplying me with the object to resolve dependencies, but I'll hold off on understanding just what that is.

This leaves me with something like this:

public abstract class ViewModelProviderBase<T> : INotifyPropertyChanged where T: class
{
    public static Func<T> Resolve { get; set; }

    public ViewModelProviderBase()
    {
        T viewModel = Resolve();
        if (viewModel != null)
        {
            _viewModel = viewModel; 
        }
    }

    private T _viewModel;

    public T ViewModel
    {
        get { return _viewModel; }
        set
        {
            _viewModel = value;
            OnPropertyChanged("ViewModel");
        }
    }        

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName)); 
        }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

So what we have is a base class typed to something. It exposes a static method to resolve that something. This is why the generic type works, so we have one method for resolution per type. It holds a reference to "whatever" and exposes it in the ViewModel property, all the while playing nice with the property changed notifications to update any bindings. What does this buy us?

Now, to resolve my main view model, I can create a provider like this:

public class ShellViewModelProvider : ViewModelProviderBase<ShellViewModel>
{        
}

Fairly straightforward, now we have a typed instance. In my bootstrapper or somewhere that "knows" what I've chosen to manage my objects, I can assign the resolver function like this:

ShellViewModelProvider.Resolve = Container.Resolve<ShellViewModel>;

Now the provider knows how to ask for a new instance of the type, with all dependencies sorted out. Then, in the XAML, we can simply bind the view model with no code behind by pointing to the provider, like this:

<UserControl.Resources>
   <vm:ShellViewModelProvider x:Key="ViewModelProvider"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModelProvider},Path=ViewModel}">

The resource creates a new instance of the provider. This calls to our resolver (in this case, the Unity container) and returns the view model, then binds it through the exposed ViewModel property.

We've achieved a binding without code behind, but it feels a little "artificial." While there wasn't code behind, we did have to do some extra work up front to glue the resolver to the type. Let's try something a little more natural in our dynamic module.

Method 2: View Injection

To me, this method feels like it makes the most sense. It is able to facilitate giving me objects and resolving dependency trees without the classes really knowing "how" it's done. In the last example, we had a base provider that was a sort of liason and had knowledge of the model and the way the model is resolved. With constructor injection, you simply have a class and are given your concrete instances. You program to the interface, and don't worry about how those interfaces were resolved. It's the pure essence of a Unity pattern where the bootstrapper wires it up, then starts making objects and injecting what they need.

To make our dynamically loaded module, we add a new project as a Silverlight Application (this is important, it's added as an application, not as a class library). I called this just "Module." I can add all of the references that the parent project has, then right click and set "copy local" to false. The references will be there when the module is loaded, so doing this lets you code to the references without having a bloated XAP file. Most of the modular XAPs with dynamic PRISM are a few kilobytes as opposed to the 100K+ "main" XAPs that get generated due to this layering and reuse.

Set up a module catalog by adding a type of "Silverlight Resource Dictionary" which generates a XAML file with no code behind and a content type of "page." You can change this to extend to the PRISM module namespace and declare your modules, like this (mine is in a subfolder called Modules, and I called the file ModuleCatalog.xaml).

<m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:sys="clr-namespace:System;assembly=mscorlib"
                 xmlns:m="clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">
    <m:ModuleInfoGroup Ref="PRISMMEF.Module.xap" InitializationMode="OnDemand">
        <m:ModuleInfo ModuleName="Module"
                      ModuleType="PRISMMEF.Module.ModuleInit, PRISMMEF.Module, Version=1.0.0.0"/>
    </m:ModuleInfoGroup>   
</m:ModuleCatalog>

Here, I'm giving the module all it needs: a name, the XAP it will load from, and how the assembly and types marry in. PRISM wants the type of the module class to call to initialize everything once the XAP file is loaded. You wire this type of catalog into PRISM by doing this in the bootstrapper:

protected override IModuleCatalog GetModuleCatalog()
{
   return ModuleCatalog.CreateFromXaml(
       new Uri("PRISMMEF;component/Modules/ModuleCatalog.xaml", UriKind.Relative));
}

If you don't remember, in the main view model we took in a reference to the module manager and wired a command to do this: moduleManager.LoadModule("Module");. This causes the module manager to look up in the catalog, find the entry, note that it is not yet loaded, then pull in and parse the XAP. This is the dynamic loading.

Let's hop over to the dynamically loaded module. This module is going to use the service and bind a list of controls to the first method (the one that returns numbers in English). The view model looks like this:

public class StuffViewModel : INotifyPropertyChanged
{
    public StuffViewModel(IService service)
    {
        ListOfStuff = new ObservableCollection<string>();
        service.GetStuff(stuff =>
            {
                foreach (string thing in stuff)
                {
                    ListOfStuff.Add(thing);
                }
            });       
    }

    private DelegateCommand<object> _dynamicViewCommand;

    public DelegateCommand<object> DynamicViewCommand
    {
        get { return _dynamicViewCommand; }
        set
        {
            _dynamicViewCommand = value;
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("DynamicViewCommand"));
            }
        }
    }
 
   public ObservableCollection<string> ListOfStuff { get; set; }


    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

A few things to notice here. First, there is a dependency on the service and when constructed, it will immediately call to the service to get the list of strings. Second, we have a command to dynamically load view (in this case, the view is loaded with the module, so a better term would be dynamically display the view), but we leave the resolution or implementation of the command up to external forces to decide.

Back in our Bootstrapper class, I need to tell Unity how to resolve the service. I override ConfigureContainer and give it this code:

protected override void ConfigureContainer()
{
    base.ConfigureContainer();
    Container.RegisterType&type;IService, Service.Service>();                                                                  
}     

Now Unity knows that when I ask for IService, I want Service.

In my new module, everything is set up in the ModuleInit. This is the type referenced in the catalog, and also implements IModule. We're going to to do two key things here. First, we'll take in a region manager and register the main view for this module. Second, we're going to tell Unity how to give us the view we'll show dynamically when we ask for it. This happens here:

public class ModuleInit : IModule
{
    IRegionManager _regionManager;
                    
    public ModuleInit(IUnityContainer container, IRegionManager regionManager)
    {
        container.RegisterType<UserControl, DynamicView>("DynamicView"); 
        _regionManager = regionManager;          
    }

    #region IModule Members

    public void Initialize()
    {            
        _regionManager.RegisterViewWithRegion("MainRegion", typeof(StuffView));
    }

    #endregion
}

Don't worry about the DynamicView control just let. We set up Unity to say, "If I want a UserControl, labeled DynamicView, give me the DynamicView type." We could just as easily made the label "foo" and provided the type "bar". The module initializer is a great place to configure the parts of the container specific to that module. The StuffView is what is displayed.

You've seen the view model, so let's talk about the view. The XAML looks like this:

<Grid x:Name="LayoutRoot" Background="White">   
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding ListOfStuff}"/>
        <Button Grid.Column="1"
                Content="Add View"
                cal:Click.Command="{Binding DynamicViewCommand}"/>
    </Grid>

Two columns, one for the list of stuff, and the other a button to show the next view.

How do we glue our view model? As I mentioned, this does involve code behind but makes the most sense to me. We take advantage of the way Unity resolves dependencies and code our view like this:

public partial class StuffView : UserControl
{            
    public StuffView()
    {
        InitializeComponent();          
    }

    public StuffView(StuffViewModel viewModel, IUnityContainer container) : this()
    {
        LayoutRoot.DataContext = viewModel;
        viewModel.DynamicViewCommand = new DelegateCommand<object>(o =>
        {
            container.Resolve<IRegionManager>().RegisterViewWithRegion("MainRegion",
                () => container.Resolve<UserControl>("DynamicView")); 
        });
    }      
}

We could do this with properties and attribute them with the Dependency attribute as well. In this case, we reference the view model so it is wired in by Unity with any dependencies. Because we get the container, we're also able to resolve the IRegionManager and tell it to add the dynamic view to the region when the command is executed. Notice that here we are resolving UserControl, which we set up in the module initialization function. The important part is that my view doesn't have to understand how a region manager does what it does or know what the other view is, it simply calls the contract and passes along what the container resolves for us.

Of course, that command is not going to do much unless we have the actual view.

The dynamic view will share the same view model and show the same list for the sake of simplicity, but I wanted to show another way of wiring the view model to the view.

Method 3: Behaviors

Again, our challenge is that XAML doesn't know how to resolve dependencies. So, we can use constructors or decorated properties and let Unity wire them in, or create our own constructs that have to be notified about what to do and then supply the needed classes.

This method uses an attached property to create the view model and attach it to the view. This time instead of keeping it overly generic, I went ahead and referenced the unity container. The behavior needs to be wired up with the container so it can resolve view models, but the view model type is passed dynamically.

The behavior looks like this:

public static class ViewModelBehavior
{
    // this is the part I like the least, could abstract it
    // but this example is long enough already!
    public static IUnityContainer Container { get; set; }

    public static DependencyProperty ViewModelProperty = DependencyProperty.RegisterAttached(
        "ViewModel",
        typeof(string),
        typeof(ViewModelBehavior),
        new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnModelAttached)));

    public static string GetViewModel(DependencyObject obj)
    {
        return obj.GetValue(ViewModelProperty).ToString();
    }

    public static void SetViewModel(DependencyObject obj, string value)
    {
        obj.SetValue(ViewModelProperty, value);
    }

    public static void OnModelAttached(object sender, DependencyPropertyChangedEventArgs args)
    {
        FrameworkElement element = sender as FrameworkElement;

        if (element != null)
        {
            if (args.NewValue is string)
            {
                string viewModelContract = args.NewValue.ToString();
                if (!string.IsNullOrEmpty(viewModelContract))
                {
                    Type type = Type.GetType(viewModelContract);
                    element.DataContext = Container.Resolve(type); 
                }
            }
        }
    }
}

So what's interesting here is that we have a reference to the unity container, and what happens when the property is attached. It is expecting a fully qualified type passed in a string. We use the Type class to resolve the type, then use the containe to resolve the instance and bind it to the data context of the element that had the behavior attached.

This leaves our code-behind clean:

public partial class DynamicView : UserControl
{
    public DynamicView()
    {
        InitializeComponent();
    }
}

And gives us flexibility to use the behavior to wire in whatever we want in the XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Text="This list was bound using the behavior."/>
    <ListBox 
        Grid.Row="1" 
        vm:ViewModelBehavior.ViewModel="PRISMMEF.Module.ViewModel.StuffViewModel, PRISMMEF.Module, Version=1.0.0.0" 
        ItemsSource="{Binding ListOfStuff}"/>


Notice the fully qualified view model type on the ListBox, which uses the behavior to resolve and then bind the view model. Wrapping Up

What we can do now is show a view with a button that was bound with no code behind and let Unity wire in dependencies. Clicking the button dynamically loads a new module that takes in a service reference, calls the service, and shows items returned from the service. This is wired in and bound in the code behind and uses constructor injection. This new view then displays the list next to a button that adds another view, bound to the same list.

All of these scenarios require a bit of work to get where we need to go. Will MEF give us something better? Perhaps. Next post, I will explore why out of the box in Silverlight 3 we can't simply glue pieces together using MEF without digging into the internals and providing some infrastructure. Much of that infrastructure will be out of the box in future versons, but this will help us understand what is going on behind the scenes. We will set up the infrastructure in anticipation of using MEF, then the third and final installment will involve another dynamically loaded module that wires it all together using MEF with a little help from Unity.

Stay tuned!

Download the source code for this project.

Special note: the source won't run "as is." You need to take two steps: first, right click the PRISMMEF.Web project and choose, "set as start project." Second, right click the PRISMMEFTestPage.aspx and choose "set as start page." Then the project will run fine.

Jeremy Likness

This post explores how to manage multiple view models across modules in a Prism-based Silverlight application.

One powerful feature of Prism is the ability to dynamically load modules. This allows reduction of the XAP file size, as well as encourages a smaller memory footprint as certain modules are not brought into the application until they are needed. A common issue I find developers struggle with is the consistent use of view models. I've seen some elegant solutions that involve storing values in isolated storage to move the values between modules (elegant, but overkill) when in fact a common view model shared between modules would have been fine.

I'm going to assume you are familiar with Prism and know how to build an application that dynamically loads modules as they are accessed. You may want to refer to my article Dynamic Module Loading with Silverlight Navigation if you need more background information.

Assume you have a project that is dynamically loading modules and injecting them into the shell. For my example, I'm going to assume the application does not require deep linking, so it is not based on the navigation framework (it could be fit easily). In order to facilitate my own navigation, I create a navigation service. The navigation service is a singleton and has the module manager injected to it. It contains an enumeration of controls to display, and a "module map" that maps the control to the module the control lives in. It also exposes a "view changed" event that it fires with the enumeration whenever a new view is navigated to.

The logic is quite simple (in this example, my enumeration is passed in as view, and the value of the enumeration maps nicely to the index of an array of modules that host views). MODULEINIT is just a shell based on the module naming convention, for example "MyApp.Module{0}.ModuleInitializer" or similar.

The module manager is injected in the constructor. Each time we navigate to a view, we call this so the module can be loaded if it hasn't been already. Prism keeps track of loaded modules and won't try to pull the XAP across the wire more than once.

_moduleManager.LoadModule(string.Format(MODULEINIT,_moduleMap[(int)view]));
            
EventHandler<ViewChangedEventArgs> handler = ViewChanged;
            
if (handler != null)
{
   ViewChangedEventArgs args = new ViewChangedEventArgs(_currentView, view);
   handler(this, args); 
}

As you can see, very straightforward. We remember the current view and send that with the new view to the event. The views themselves can register to the event. If the views are built with a VisualStateGroup to handle swapping them into and out of view, then the logic is simply: if I am the old view, go to my hidden state, else if I am the new view, go to my visible state. Then the views can live in an ItemsControl with only one view showing at a time.

For my views, I create a ViewBase class that is, in turn, based on UserControl. This lets me manage some common housekeeping for the views that will be bound to view models. First, I exposed a protected method called _ViewBaseInitialize to call after the component is initialized. This takes in the view model and binds it, as well as wires into the navigation change event. I know some people won't like injecting the view model and there are certainly other ways to marry the view and its model, but for our example this will do.

Our logic looks simply like:

protected void _ViewBaseInitialize(object viewModel)
{
   Loaded += (o, e) =>
      {
         MasterModel model = DataContext as MasterModel;
         model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
                
         if (viewModel != null)
         {
            model.ModuleViewModel = viewModel;
         }
      };

      if (currentView.Equals(e.OldView))
      {
         VisualStateManager.GoToState(this, "HideState", true); 
      }
      else if (page.Equals(e.NewView))
      {
         VisualStateManager.GoToState(this, "ShowState", true);
      }
}

You'll note the introduction of the MasterModel. This view model is bound at the shell level, so it is available to all of the views hosted in that shell. Typically, a shell as a Grid or similar item as the root layout panel, so in my bootstrapper I handle wiring up the master view model:

protected override DependencyObject CreateShell()
{
    Container.RegisterType<NavigationManager>(new ContainerControlledLifetimeManager());
    NavigationManager nm = Container.Resolve<NavigationManager>();
  
    Container.RegisterType<MasterModel>(new ContainerControlledLifetimeManager());           
               
    Shell shell = Container.Resolve<Shell>();
    Application.Current.RootVisual = shell;
    
    nm.NavigateToView(NavigationManager.NavigationPage.Login);
    
    return shell; 
}

Because the constructor of the master model takes in a "navigation manager" instance, it receives the instance we just configured. Likewise, the shell will receive the instance of the view model and bind that to the data context of its main grid.

For all practical purposes, the MasterModel definition looks like this:

public class MasterModel : IViewModel
{
   public NavigationManger Navigation { get; set; }

   public MasterModel(NavigationManager nm)
   {
      Navigation = nm;
   }

   public IViewModel SubModel { get; set; }
}

You can see that it takes the navigation manager as well as a sub model where needed. This is key: it doesn't have knowledge about the modules it will be interacting with, so it only knows about the IViewModel. We'll get more specific in a bit. The master module can hold things like settings, static lists, authentication, etc, to pass down to sub modules as needed.

Now let's get down to an actual module that will use this. Let's say I have a module called ModuleUserManager and it has a view model called UserManagerModel. It needs a token for security that is stored in the master module.

First, let's extend the ViewBase to make it easier to grab a model. We can't type the view base because we are basing our controls on UserControl, which isn't typed. We can, however, type methods. I added this method as a simple helper:

protected T _GetViewModel<T>() where T: IViewModel 
{
    MasterModel model = DataContext as MasterModel;
    return model == null ? null : (typeof(T).Equals(typeof(MasterModel)) ? model as T : model.ModuleViewModel as T); 
}

Remember, we bound the master to the shell, so the hierarchical nature of data-binding means the data context will continue to be that until I override it. We'll override it in our view, but at this level we still see the master model. The method simply casts the data context and then either returns it the master model is being requested, or access the ModuleViewModel property and returns that (also typed). This was set earlier in the call to the _ViewBaseInitialize.

Now my view can be based on ViewBase. Simply add a user control, go into the XAML, reference the namespace for the view base and then switch from UserControl to ViewBase. The XAML will look like this:

<vw:ViewBase x:Class="MyApp.ModuleUserManager.Views.UserView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"  
    xmlns:vw="clr-namespace:MyApp.Common.Base;assembly=MyApp.Common"
    >
    <Grid DataContext="{Binding ModuleViewModel}"/>
</vw:ViewBase>

In this example, we've taken the user control and exposed it as a ViewBase because the partial class must have the same base in both XAML and code behind. I've also bound the grid to the "module view model" so it has access to the local view model. In the code behind, we pass the module-specific view model to the initializer:

public partial class UserView : ViewBase
{
    public UserView()
    {
        InitializeComponent();
        _ViewBaseInitialize(new UserManagerModel());
    } 
}

Note that the master model is going to be shared. Even though I dynamically loaded the module and the view with Prism, the data context for the control itself remains bound to the "master" (shell) and therefore can reference all of the properties I've set in previous screens. My new, local view model gets bound as a property to this master view so the local properties can be accessed in the XAML. What if I have a property called Token in my master that I need to reference in my local view model? I can simply add a hook into the loaded event (so I'm sure all of the binds, etc have taken place) and then use my new helper method. I'll add this after the _ViewBaseInitialize call:

        Loaded += (o, e) =>
            {
                MasterModel master = _GetViewModel<MasterModel>();
                UserManagerModel userModel = _GetViewModel<UserManagerModel>();
                userModel.Token = master.Token; 
            };


That's it. Obviously there are more elegant ways to bind the view models together other than the code-behind, but I tend not to be the fanatic purist some others might be when it comes to simple actions and tasks that coordinate views and view models. If that task has "awareness" of an event triggered in the view and the view model, I don't see the issue with tapping into that action to glue things together.

The final thought I'll leave you with is the possibility of the sub modules being a stack. In this scenario, each view would push the view model onto the stack. Then, if you clicked the back button, the previous view could pop its view from the stack and restore the state it was in. This way the master model would help coordinate undo/redo functionality without having knowledge the specific models it collects.

Jeremy Likness

Oh wait, even better...

After posting this, I realized there was even a better way to class the base view. If I do this:

protected void _ViewBaseInitialize<T>(Action<MasterModel,T> onLoaded) where T: IViewModel, new()
{
    // must fire when loaded, as this is when it will be in the region
    // and ready to inherit the view model
    Loaded += (o, e) =>
    {
        MasterModel model = DataContext as MasterModel;
        model.Navigation.ViewChanged += new EventHandler<ViewChangedEventArgs>(nm_ViewChanged);
        
        if (typeof(T) != typeof(MasterModel))
        {
            model.ModuleViewModel = new T();
        }

        if (onLoaded != null)
        {
            onLoaded(model, model.ModuleViewModel as T);
        }
    };
}

Then I simply changed my derived view to this:

public UserView()
{
    InitializeComponent();
    _ViewBaseInitialize<UserManagerModel>((masterModel, userModel) =>
        {
            userModel.Token = masterModel.Token;
        });           
}

Even better!

I started a project to update my personal website using Silverlight. The goal is to use Prism/Composite Application Guidance to build out a nice site that demonstrates some Silverlight capabilities and make the source code available as a reference. One of the first pieces I chose to tackle was ensuring I could facilitate deep linking using Silverlight navigation and still take advantage of dynamic module loading using the Prism framework.

The initial research I did was not promising. Most sites claimed that Prism broke the Silverlight navigation, while others had partial solutions that didn't really cut it for me. Mapping a separate view in the main module to have a named region for every dynamically loaded module seems to be overkill. So, I set out to see for myself if it could be done. The answer, of course, is yes!

While the project is a simple pair of pages, I've built in a few more advanced pieces of functionality to extend its richness as a reference project. In addition to dynamic loading the module for the "biography" page, I've trimmed the size of the XAP files, sprinkled in a little search engine optimization, and used the visual state manager to handle some animations to boot.

You can download the full source code by clicking here. For a working demo, click here. You can use a sniffer or proxy like Fiddler 2 to confirm for yourself that the Biography module doesn't load until you click that tab, BUT you can also navigate directly:

I do apologize in advance for the vanity built into the project ... it is a project with the goal of replacing my biography website so it made since to name it after, well, me.

The first step in creating a deep linking navigation website is to go ahead and create a Silverlight Navigation Application. I called mine JeremyLikness.Main and it gave me JeremyLikness.Web to host it. Go ahead and trash everything in the views folder but the error window (I like that functionality, some might find it annoying), leave the App pieces alone but rename the main page to Shell.xaml.

Here's when things start to get interesting. First, I've seen a lot of implementations that want the pure "my module gets added magically" functionality, so they do things like inject the link to the module when the module itself gets loaded, etc. This is all great but then they also stuff a view in the main application that maps one-to-one with the module, give a new named region per module, and leave me scratching my head wondering, "What did we gain?" To me, the main portion of my app is a single region that can have multiple modules inject their views into it, so that's how I approached this project.

I'm going to be a bit more pragmatic and go ahead and map my links in the main shell because I'm assuming right now the shell is like the overall "controller" and is aware of the other modules. It should, however, be very easy and minimal overhead for me to add a new module later on. I'm not going to worry about the modules injecting the links because then I have to load the module before I can show the link, and that defeats the purpose of dynamically loading the modules. Ideally, your browser doesn't fetch that extra 100K of XAP download if you don't care about reading my biography!

I end up keeping the generated code for the links (I'll go back and rearrange and style it later ... getting it functioning for me comes before making it pretty). I'm starting with two links, so that section looks like this:


 <Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}">
                <StackPanel x:Name="LinksStackPanel" Style="{StaticResource LinksStackPanelStyle}">

                    <HyperlinkButton x:Name="homeLink" Style="{StaticResource LinkStyle}" 
                                     NavigateUri="/Home" TargetName="ContentFrame" Content="Home"/>
          
                    <Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>
     
                    <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}" 
                                     NavigateUri="/Bio" TargetName="ContentFrame" Content="Bio"/>
                </StackPanel>
            </Border>

Not bad. Now we're going to start butchering the generated template, so bear with me.

Dynamic Modules

Setting up modules to be dynamic is fairly straightforward. While there are many ways to approach this, the method I used has two key features:

  1. I'm using a XAML configuration for the module, not programmatic, and
  2. to add the module in a way that Prism can dynamically load it, I add it as a Silverlight Application, not a Class Library

That's it! We're going to work a bit backwards and live without the project compiling for a bit until we get all of the pieces put into place. I know I'm going to have a Home and a Bio module. For the sake of simplicity and this example, I'm doing one view per module, but you could obviously do more. You'll see why this makes it easy for me in a minute. First, let's set up the XAML that will describe the modules.

Right click on the main project (the one with your shell) and add a new Resources File. Name it ModuleCatalog.xaml. Blow away everything in there and instead put in the Prism notation for a module, like this:


<m:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:sys="clr-namespace:System;assembly=mscorlib"
                 xmlns:m="clr-namespace:Microsoft.Practices.Composite.Modularity;assembly=Microsoft.Practices.Composite">
    <m:ModuleInfoGroup Ref="JeremyLikness.ModuleHome.xap" InitializationMode="WhenAvailable">
        <m:ModuleInfo ModuleName="JeremyLikness.ModuleHome.InitModule"
                      ModuleType="JeremyLikness.ModuleHome.InitModule, JeremyLikness.ModuleHome, Version=1.0.0.0"/>
    </m:ModuleInfoGroup>
    <m:ModuleInfoGroup Ref="JeremyLikness.ModuleBio.xap" InitializationMode="OnDemand">
        <m:ModuleInfo ModuleName="JeremyLikness.ModuleBio.InitModule"
                      ModuleType="JeremyLikness.ModuleBio.InitModule, JeremyLikness.ModuleBio, Version=1.0.0.0"/>
    </m:ModuleInfoGroup>
</m:ModuleCatalog>
                 

I've purposefully set the home page to load when available and the bio to load on demand to show the difference between the methods ... I could just as easily load both modules on demand. This simply points to the class that defines the module, and the assembly to find it in. Prism will assume it's available for download in the same directly as the hosted XAP and kindly pull down the XAP when it's needed for us.

We're now referring to some modules we don't have yet. At this point, you could go ahead and create the shells for the applications. In order for the project to be set up correctly for dynamic loading, instead of adding a Silverlight Class Library, you're going to add a new Silverlight Application. Pick the same web page to host it but don't bother with the generation of a test page as it will load into the same test page we used for the main. I called my projects JeremyLikness.ModuleBio and JeremyLikness.ModuleHome.

Once the projects are created, blow away the all of the generated XAML files. You won't need the App object because this will be hosted in our main application. I simply added the references needed for Prism, then created a Views folder and added a Home.xaml in my home project and a Bio.xaml in my bio project. These are UserControl types, not pages. In the root, I created InitModule classes for both projects (note that I referenced this in the ModuleCatalog.xaml). The code looks almost identical - here is the bio:


namespace JeremyLikness.ModuleBio
{
    public class InitModule : IModule
    {
        private IRegionManager _regionManager;

        public InitModule(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }

        #region IModule Members

        public void Initialize()
        {
            _regionManager.RegisterViewWithRegion("ModuleRegion", typeof(Bio));
        }

        #endregion
    }
}

Simple: reference the region manager in the constructor. The Prism will use Unity to resolve the reference and inject it. On the Initialize method, we register our view with the region. The home project will register to the same region, but with typeof(Home) home instead.

Now we've got the catalog and the modules, what's next?

Bootstrapping

We need to tell the Prism framework how to "get started." This means a bootstrapper. Back to JeremyLikness.Main, I add a class called Bootstrapper and base it on UnityBootstrapper. I need to create the shell and set it as the root visual:


protected override DependencyObject CreateShell()
{
    Shell shell = Container.Resolve<Shell>();
    Application.Current.RootVisual = shell;
    return shell;
}

I also need to supply a module catalog. For this, I'll point to the XAML file we created earlier:


protected override Microsoft.Practices.Composite.Modularity.IModuleCatalog GetModuleCatalog()
{
    return Microsoft.Practices.Composite.Modularity.ModuleCatalog.CreateFromXaml(
        new Uri("JeremyLikness.Main;component/ModuleCatalog.xaml", UriKind.Relative));
}

You can see I'm telling it to look to the XAML to create the catalog, then specifying the path to it. The last thing I need to do is go into the App.cs code behind and change the application start up to just run the boot strapper:


private void Application_Startup(object sender, StartupEventArgs e)
{
   new Bootstrapper().Run();
}

Adapting to the Region

Prism works with defined regions that can host views. There are a number of different ways those regions can be implemented. I would ask that you refer to the Prism documentation for this, but basically something like a ContentControl can have a single view active at any given time, while something like a ItemsContentControl can hold multiple views. One source of confusion is what "active" really means. Active views doesn't necessarily mean "visible" or "hidden." I had two challenges for this application: the first was how to host the view, and the second was how to manage the visibility of the views. Ideally, something would hold all of the views as they are selected, then simply make them visible or invisible as they are selected/deselected.

We'll tackle visibility in a minute. ContentControl wasn't an option because it only holds one view at a time. The problem with ItemsControl was related to layout. As each view is injected, it takes up space in the container (this is the same whether it's a items control or a stack panel, etc). Even when I'd collapse the visibility of a control, the original space would still cause the other controls (views) to be shifted, which was not the effect I wanted. I needed something like a Grid where I could stack the views one on top of the other.

Fortunately, making your own type of region is easy. After reading John Papa's excellent post, I made a PrismExtensions folder and built my GridRegionAdapter to allow Prism to use a grid as a container. You can read his article to understand the how/why and see how the adapter is constructer. I had to revisit the boot strapper and tell Prism how to map the adapter to the grid:


protected override RegionAdapterMappings ConfigureRegionAdapterMappings() 
{ 
    RegionAdapterMappings mappings = base.ConfigureRegionAdapterMappings(); 
    mappings.RegisterMapping(typeof(Grid), Container.Resolve()); 
    return mappings; 
}

Now I was ready to give the solution a go!

The Problem with Navigation

The first iteration I tried was to declare a single page with the region adapter to process the requests. In my Views folder in the main project, I created a Silverlight Page (Page, not UserControl) and called it Module.xaml. The XAML for the module looked like this:


<navigation:Page x:Class="JeremyLikness.Main.Views.Module" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           mc:Ignorable="d"
           xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           xmlns:local="clr-namespace:JeremyLikness.Main.Views"
                 d:DesignWidth="640" d:DesignHeight="480"
           Title="Module Page">
    <Grid x:Name="MainGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" cal:RegionManager.RegionName="ModuleRegion">
    </Grid>
</navigation:Page>
      

Going back to the main shell, I mapped all requests to the module, like this:


<Border x:Name="ContentBorder" Style="{StaticResource ContentBorderStyle}">

    <navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}" 
                      Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">
        <navigation:Frame.UriMapper>
          <uriMapper:UriMapper>
            <uriMapper:UriMapping Uri="" MappedUri="/Views/Module.xaml"/>
            <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/Module.xaml"/>
          </uriMapper:UriMapper>
        </navigation:Frame.UriMapper>
    </navigation:Frame>
</Border>

As you can see, pretty much every request is handled by the Module page. In the code behind, I had to work a little bit of magic to ensure the appropriate module would be loaded. First, I added a reference to the module manager:


public partial class Shell : UserControl
{
    private IModuleManager _moduleManager;

    public Shell(IModuleManager moduleManager)
    {
        _moduleManager = moduleManager;
        InitializeComponent();
    }

    private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
    {
    
        string module = e.Uri.ToString().Substring(1);
        string moduleName = string.Format("JeremyLikness.Module{0}.InitModule", module); 
       
        _moduleManager.LoadModule(moduleName);

...

}

The key here was getting the reference to the module manager, then calling the module load on the request. The module manager is smart enough to know when a module has already been loaded, so I didn't have to worry about that. The idea here is that when I request the "bio" tab, the string manipulation maps it to JeremyLikness.ModuleBio.InitModule, then calls the manager. The manager checks to see if it is loaded. If not, it will download the required XAP file and initialize the module. The module would then register the view with the region and it would magically appear!

There were two problems that arose immediately. The first issue was visibility: the different pages were stacking on each other. I'd load the application and see the home page, then click on the bio tab and watch the bio appear overlaid on top of the home page. Definitely not the right solution! We'll address visibility in a minute.

The second was a little more disturbing. The pages were behaving a little strangely so I fired up the debugger and found something disturbing: every time I would navigate to a link, the navigation framework would generate a new instance of the Module.xaml. This, in turn, would create new instances of the views. Just a few clicks of the tab and suddenly I had lots of instances hanging out that I just didn't need.

The solution for this was to create a static view that would live between navigation requests and hold the views as they are stacked in place. The first step was to build the container for the views. Under the Views folder, I created ViewContainer.xaml. The XAML contained the region mapping:


<UserControl x:Class="JeremyLikness.Main.Views.ViewContainer"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
   >
    <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
          cal:RegionManager.RegionName="ModuleRegion">
       </Grid>
</UserControl>

The code behind implemented the singleton pattern:


public partial class ViewContainer : UserControl
{
    private static readonly ViewContainer _viewContainer = new ViewContainer();

    private ViewContainer()
    {
        InitializeComponent();
    }

    public static ViewContainer GetViewContainer()
    {
        if (_viewContainer.Parent != null)
        {
            Grid grid = _viewContainer.Parent as Grid;
            grid.Children.Remove(_viewContainer); 
        }

        return _viewContainer;
    }
}

Note that an element can only have one parent, and cannot be added as a child to another element. The GetViewContainer method first detaches the view from its previous parent before returning the instance so that the consumer of the method can use the orphaned view. I removed the region reference from the Module.xaml and added this to the code behind:


public Module()
{
    InitializeComponent();
    MainGrid.Children.Add(ViewContainer.GetViewContainer()); 
}

Now the navigation will still create a new instance of Module every time we navigate, but the module will simply reuse the same container for the views. This ensures that the views persist once they are added and don't have to be reloaded or recreated.

Next, I needed to manage showing and hiding the views so they don't remain stacked on top of each other.

Managing Visibility

To manage the views, I decided to create a service that the views will register to. The service is called when navigation takes place, and then calls back to the views to manage their visibility.

First, I created a new project that would be common across other projects. This was named, ironically, JeremyLikness.Common. First was an interface that the views could use. They provide a name for themselves as well as a method to call to either show or hide. This offloads the need for the view manager to understand how to show or hide a view ... since the view is a UserControl, it should have a pretty good idea.


public interface IPrismView
{
    void Show();

    void Hide();

    string ViewName { get; }
}

Next, I added a reference to the common project in both modules and implemented IPrismView. This is what the Bio.xaml.cs looked like:


#region IPrismView Members

public void Show()
{
    this.Visibility = Visibility.Visible; 
}

public void Hide()
{
    this.Visibility = Visibility.Collapsed;
}

public string ViewName
{
    get { return "Bio"; }
}

#endregion

Now I can create my view manager. In the same common project, I created a class called ActivationManager (continuing the Prism concept of "activating" a view although it is probably misnamed in retrospect). ActivationManager contains a collection of views. It allows a view to register with it, then exposes a method called SwapToView that iterates the views and calls their Show or Hide methods. It looks like this:


public class ActivationManager
{
    List<WeakReference> _views = new List<WeakReference>();

    public void Register(IPrismView view)
    {
        _views.Add(new WeakReference(view));
        view.Show();
    }

    public void SwapToView(string viewName)
    {
        foreach (WeakReference weakRef in _views)
        {
            if (weakRef.Target != null)
            {
                IPrismView view = (IPrismView)weakRef.Target;
                
                if (view != null)
                {
                    if (view.ViewName.Equals(viewName))
                    {
                        view.Show();
                    }
                    else
                    {
                        view.Hide();
                    }
                }
            }
        }
    }
}

Now we need to wire the activation manager in. We only need one copy, so in the boot strapper in the main project, I set up the instance:


protected override DependencyObject CreateShell()
{
    Container.RegisterInstance<ActivationManager>(
        Container.Resolve<ActivationManager>());
    Shell shell = Container.Resolve<Shell>();
    Application.Current.RootVisual = shell;
    return shell;
}

Notice I did this before creating the shell. There is a reason: we need the shell to coordinate the views. The shell has a method that fires when the navigation changes. If you recall, we used this method to tell the module manager to load the appropriate module. Now we'll need to pass in the activation manager and ask it to activate the views. These are the changes to the Shell code-behind:


private ActivationManager _activationManager;

public Shell(IModuleManager moduleManager, ActivationManager activationManager)
{
    _moduleManager = moduleManager;
    _activationManager = activationManager;
    InitializeComponent();
}

private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
{

    string module = e.Uri.ToString().Substring(1);
    string moduleName = string.Format("JeremyLikness.Module{0}.InitModule", module); 
   
    _moduleManager.LoadModule(moduleName);

    _activationManager.SwapToView(module); 

    foreach (UIElement child in LinksStackPanel.Children)
    {
        HyperlinkButton hb = child as HyperlinkButton;
        if (hb != null && hb.NavigateUri != null)
        {
            if (hb.NavigateUri.ToString().Equals(e.Uri.ToString()))
            {
                VisualStateManager.GoToState(hb, "ActiveLink", true);
            }
            else
            {
                VisualStateManager.GoToState(hb, "InactiveLink", true);
            }
        }
    }
}

The last step is to take each module and pass the activation manager into the constructor so the view can register itself. This could probably be moved back into the module initialization (i.e. when the view is injected into the region) and perhaps even something extended on the framework to handle it. However, this works for now, using Bio.xaml.cs as our example:


public Bio(ActivationManager activationManager) : this()
{
    activationManager.Register(this);
}

Notice that I use this() to ensure it calls the default parameterless constructor to InitializeComponent etc etc.

At this point, I claimed victory. After compiling and publishing the project, I was able to navigate between the home and bio tabs, and watch the bio module loaded dynamically when I navigated to the tab. The views swapped in and out nicely. If you were reading this for dynamic module loading ... there it is!

To round out the example, I wanted to show two more things. First, I wanted to take the idea of Show and Hide a step further, and second, I don't believe navigation or deep linking makes sense to discuss unless we also cover search engine optimization.

Visual State Manager

The visual state manager is the key to managing visual states on controls (seems like it was well-named, huh?). I have to thank Justin Angel for pointing this out to me when I was doing a lot of behaviors and triggers for animations that truly belonged in the VSM instead. Really, when we're swapping our views, we are changing the state of the view ("show me" or "hide me"). If we do this programmatically, then we're stuck with the attributes we set. However, if we do this through the VSM, then all of the the transition becomes customizable through the designer and in Expression Blend, so our designers can then tinker with the transitions without touching the code behind.

To demonstrate this, I decided to take both views and give them a ShowState and a HideState. To show the power of the Visual State Manager, I created two different transitions: the home page will explode in using a scale transform, while the biography page will fade in using an opacity animation.

Because there are a million examples that show how to add custom view states using Blend, I decided to document the code behind approach. The main container in our views is a grid, so that's what we're going to manipulate. I want the view to hide immediately, but when it goes to show, it should have a nice animation. This is what the Bio.xaml ends up looking like:


<Grid x:Name="LayoutRoot" Background="White">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="VisualStates">
                <VisualState x:Name="ShowState">
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:01.0000000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Opacity)">
                            <EasingDoubleKeyFrame KeyTime="00:00:01" Value="1"/>
                        </DoubleAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:01.0000000" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Visible</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="HideState">
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0000100" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Opacity)">
                            <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                        </DoubleAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:01.0000100" Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <TextBlock>This is my bio. It tells people about me and my background.</TextBlock>
    </Grid>

So there are a few things going on here. First, we define a "group" of visual states that I call, sure enough, VisualStates. I am defining two states: a HideState and a ShowState. The hide state has an animation with a zero duration and simply sets the Opacity to 0. The show state animates for a second (you'd normally make this faster, but it helps demonstrate my point) and fades in. While many people are used to the color and double animations, did you know there existed an object animation as well? This allows you to manipulate almost any property on your target control using the visual state. In this case, I won't even have to set the Visibility property in my code behind - I simply define the value in the view state! Notice in the ShowState that the property is set immediately so it becomes visible in time for the animation to fire and fade it in.

So now we simply go to the code-behind for our control and set the state. The VSM expects a control when you set the state, but it will traverse the hierarchy and find the state you specify. So while we set the state on our control, it will use the state definitions that are contained within the grid object. We also make sure we set a default state in the constructor. In this case, it will be hidden because the activation manager will call show when it is registered. This is what our new code-behind looks like:


public partial class Bio : UserControl, IPrismView
{
    public Bio()
    {
        InitializeComponent();
        VisualStateManager.GoToState(this, "HideState", false);
    }

    public Bio(ActivationManager activationManager) : this()
    {
        activationManager.Register(this);
    }

    #region IPrismView Members

    public void Show()
    {
        VisualStateManager.GoToState(this, "ShowState", true);
    }

    public void Hide()
    {
        VisualStateManager.GoToState(this, "HideState", true);
    }

    public string ViewName
    {
        get { return "Bio"; }
    }

    #endregion
}

As you can see, we simply move to a new state and leave it up to the designer to add any fancy animations or other transitions when that happens.

Getting Along with Search Engines

The final piece here is to get along with search engines. Deep linking is nice if you just want to add it to your favorites and jump right in, but doesn't really do much for search engines when they are scanning the page. The search enginges need to have some points like a page title and description to properly index your pages.

In the common project, I created a class called SEOHelper to contain my title, description, and keywords. It exposes a method called PageUpdate that then parses these values into the HTML page. Let's take a look at the class:


public class SEOHelper
{
    private const string TEMPLATE = "metatags = document.getElementsByTagName(\"meta\");"
        + "for (x=0;x<metatags.length;x++) {{"
        + "var name = metatags[x].getAttribute(\"name\");"
        + "if (name == '{0}'){{"
        + "var content = metatags[x].getAttribute(\"content\");" 
        + "metatags[x].setAttribute('{0}','{1}');break;}}}}";

    private List<string> _keywords = new List<string>();

    public string Title { get; set; }

    public string Description { get; set; }

    public void AddKeyword(string keyword)
    {
        _keywords.Add(keyword);
    }

    public void UpdatePage()
    {
        HtmlPage.Document.SetProperty("title", Title);

        string titleSet = string.Format(TEMPLATE, "title", Title);
        HtmlPage.Window.Eval(titleSet);

        string descriptionSet = string.Format(TEMPLATE, "description", Description);
        HtmlPage.Window.Eval(descriptionSet);

        if (_keywords.Count > 0)
        {
            StringBuilder keywordList = new StringBuilder();
            bool first = true;
            foreach (string keyword in _keywords)
            {
                keywordList.Append(keyword);
                if (first)
                {
                    first = false;
                }
                else
                {
                    keywordList.Append(",");
                }
            }
            string keywordSet = string.Format(TEMPLATE, "keywords", keywordList);
            HtmlPage.Window.Eval(keywordSet);
        }
    }
}

I'm not a big fan of burying JavaScript inside of C# classes, so I included it here only to help keep the solution in one place. Ordinarily I'd have some methods defined in a .js file that this would link to.

Setting the title is a call into the document object. Setting the meta tags is a little more convuluted. You could create the tags but in this example, I'm stubbing out empty title, description, and keywords meta-tags, then finding them and updating the content attribute. The TEMPLATE contains the code to iterate the tags, then update the content attribute. The PageUpdate method simply updates the meta tag name and content then asks the page to evaluate the javascript.

Now we just place the object inside of the appropriate view and call it when the view becomes visible. Here is the new Home.xaml.cs:


public partial class Home : UserControl, IPrismView
{
    SEOHelper _helper = new SEOHelper { Title = "Home Page", Description="Home page for the website." }; 

    public Home()
    {
        InitializeComponent();
        VisualStateManager.GoToState(this, "HideState", false);
        _helper.AddKeyword("Home");
        _helper.AddKeyword("SEO"); 
    }

    public Home(ActivationManager activationManager)
        : this()
    {
        activationManager.Register(this);
    }

    #region IPrismView Members

    public void Show()
    {
        VisualStateManager.GoToState(this, "ShowState", true);
        _helper.UpdatePage();
    }

    public void Hide()
    {
        VisualStateManager.GoToState(this, "HideState", true);
    }

    public string ViewName
    {
        get { return "Home"; }
    }

    #endregion
}

As you can see, the helper takes in the settings for the page, then whenever the view is shown (the Show) method, the helper is called to update the page. For testing, this could be abstracted even further to a ISEOHelper to avoid trying to actually access the html page when its not needed.

Trimming the XAP Size

Last but not least is trimming the XAP size. I put most of my references in the main XAP file, so they aren't needed in the modules. By going to the project properties, I can check "Reduce XAP size by using appliciation library caching." This will create a new ZIP file that contains some of the referenced controls on my modules when they build, and not include them in the main XAP. Fortunately, these are already loaded by the main XAP, so there is nothing more to do when the XAP is loaded.

There it is ... I know this was a long blog post for what, in the end, is a simple page with two tabs. However, I hope this has proven that you can combine Prism with Silverlight Navigation and use dynamic module loading will keeping your pages search engine friendly. The VSM piece might have made sense in a separate post but I also wanted to get a good example out there that shows how to wire it in when you're not making a custom control or using Blend. Enjoy!

Download the source

View the demo

Jeremy Likness

For all of the Prism fans out there, a newer version has been released. You can download it here.

Jeremy Likness

In yesterday's post about Decoupled ChildWindow Dialogs in Silverlight using Prism, I demonstrated a way to use EventAggregator to decouple the implementation of a dialog from the code that requires the confirmation. In one example, I showed a code-behind click event that fired off the process, something like this:

private void Button_Delete_Click(object sender, System.Windows.RoutedEventArgs e)
{
    Button src = e.OriginalSource as Button;
    if (src != null)
    {
        _eventService.GetEvent<MessageBoxEvent>().Publish(
            MessageBoxPayload.GeneratePayLoad(src.DataContext, true, "Please Confirm", "Are you sure you wish to delete this item?",
                                      DeleteItem));
    }
}    

This, in my opinion, is way too much information for a view to know and understand. It has to know about my event aggregator service? Is that really necessary?

If you are not familiar with the Model-View-ViewModel (MVVM) pattern, you'll want to Google/research it now. It is important because a lot of the marshalling of data will happen in the ViewModel, and the view will simply be bound to the view model.

Prism provides a commanding interface that works well with buttons. You can use an attached property to bind the click to a command (which is in turn a DelegateCommand). The command will disable the button if it can't execute and fire when the button is clicked. The button becomes a binding, like this:

...
<Button Commands:Click.Command={Binding SearchCommand} .../> 
...

In the view model, the SearchCommand is defined like this:

...
public DelegateCommand<object> SearchCommand { get; set; }
...
SearchCommand = new DelegateCommand<object>(o => 
   _service.GetEventService().GetEvent<SearchEvent>().Publish(
      SearchCriteria),o => _CanSearch());

In this example, we are assuming the form fields are bound to a search criteria object in the view model. Presumably once the criteria meet our validation requirements, _CanSearch will return true, the button will be enabled, and the command will publish an event to begin the search using the populated criteria entity.

While I intend to dig more in depth in that pattern, I wanted to present something I believe is a common issue and describe how I addressed it. In this case, the view model contains the search criteria as well as a collection of objects for the results grid. This becomes problematic with binding, because my grid row is bound to the item in the list, not the view model itself. Unfortunately, Silverlight does not support (to my knowledge) the relative binding syntax available in WPF, so it can be troublesome to try to bind the click in the grid to a command.

If there is a simple way to do this I'd love to learn more, but any examples I've seen were fairly complex to maintain the "purity" of leaving everything out of the code behind. Me? I'm a bit more pragmatic. I'd rather go ahead and bind the click event (I know, some of you are shuddering ... that means a code behind ...) like I did above. However, there is a compromise!

Instead of making my view aware of the event aggregator service, I can do a bit better. The view model already knows about the service. Let's assume we could bind directly to a command. We'll create a command like this, in the view model:

public DelegateCommand<MyEntity> DeleteCommand { get; set; }

We can then wire the command to publication of a delete event:

DeleteCommand = new DelegateCommand<MyEntity>(
                _service.GetEventService().GetEvent<DeleteMyEntityEvent>().Publish, o => true);

Notice we don't supply parameters to Publish. That's because our event is already wired to act on an instance of MyEntity, and so the event will fire and pass that entity as a parameter.

Now we can clean up our code behind to look like this:

private void Button_Delete_Click(object sender, System.Windows.RoutedEventArgs e)
{
    Button src = e.OriginalSource as Button; 
    if (src != null)
    {
        MyEntity entity = src.DataContext as MyEntity;
        if (entity != null)
        {
            if (_ViewModel.DeleteCommand.CanExecute(entity))
            {
                _ViewModel.DeleteCommand.Execute(entity);
            }
        }
    }
}

So, it's not "pure" in the sense that I do end up with code behind ... but ask me, do I really care? Is it all that bad? The view is aware of the view model, so why not allow it to response to what views do well (view events) and marshall them to the view model? The implementation of the command is still hidden from view.

With some clever attached properties, we could also make the button disable if CanExecute is false, and because of data virtualization we'd only be evaluating it for the grid items that are in the view.

Jeremy Likness

A common user interface component is the confirmation or message box, which is often presented as a dialog returns a boolean (OK/Cancel). There are a variety of ways to achieve this, but how can you decouple the implementation of the popup from the request itself? This is necessary, for example, for unit testing when you may not have a UI available. This article demonstrates one solution using Silverlight and the Composite Application Guidance library, also known as Prism.

The first piece we are going to build is a payload that allows us to deliver the popup message. The payload looks like this:

public class MessageBoxPayload
{
    public object DataContext { get; set; }

    public bool AllowCancel { get; set; }

    public string Title { get; set; }

    public string Message { get; set; }

    public Action<MessageBoxPayload> ResultHandler { get; set; }

    public bool Result { get; set; }

    private MessageBoxPayload()
    {            
    }

    public static MessageBoxPayload GeneratePayload(object dataContext, bool allowCancel, 
        string title, string message, Action<MessageBoxPayload> resultHandler)
    {
        MessageBoxPayload retVal = new PopupEntity {AllowCancel = allowCancel, Title = title, Message = message, 
            ResultHandler = resultHandler,
        DataContext = dataContext};
        return retVal; 
    }
}

Because we are implementing this completely decoupled, we cannot make any assumptions about state. Therefore, the payload carries a data context that can be passed back to the requestor. This is done using an Action of the payload type, allowing the requestor to provide a method to get called when the dialog closes.

Next, we'll define the event we use to request the message box. That is based on the event mechanism supplied by Prism:

public class MessageBoxEvent : CompositePresentationEvent<MessageBoxPayload>
{
}

Notice that we derive from the CompositePresentationEvent. This is a base class for all events that will participate in the event aggregator service. Now that we have our payload and our service defined, we can easily begin to pubish to the event. If you had a data grid with a delete button, the event would look something like this (for simplicity's sake I'm not using DelegateCommand):

private void Button_Delete_Click(object sender, System.Windows.RoutedEventArgs e)
{
    Button src = e.OriginalSource as Button;
    if (src != null)
    {
        _eventService.GetEvent<MessageBoxEvent>().Publish(
            MessageBoxPayload.GeneratePayLoad(src.DataContext, true, "Please Confirm", "Are you sure you wish to delete this item?",
                                      DeleteItem));
    }
}      

public void DeleteItem(MessageBoxPayload payload)
{
    if (payload.result) 
    {
       MyItem item = payload.DataContext as item;
       Delete(item);
    }
}

For unit tests, you can now simply build an object that subscribes to the delete event and returns the desired results.

As you can see, the delete click wraps the message into a payload and publishes the event. A delegate is provided to call back to "DeleteItem" with the result of the dialog. If the user confirmed, then the data context is used to pull the entity for the given row and the delete command is performed.

The _eventService is defined like this:

...
private readonly IEventAggregator _eventService;
...

Because IEventAggregator is supplied as a parameter in the constructor for the view, it is automatically wired in by the dependency injection framework. There are two steps required to get the event aggregator to your objects.

First, in your bootstrapper, you'll want to register a single instance:

protected override void ConfigureContainer()
{
    base.ConfigureContainer();

    // provide a reference to the event aggregator
    Container.RegisterInstance<IEventAggregator>(Container.Resolve<EventAggregator>());

}

Notice that I use "resolve" to get the instance. This is good practice when using a dependency injection/inversion of control framework. When you new your objects, you must select the appropriate constructor and inject the appropriate values. By calling Resolve you ask the container to read the signature of the constructors and provide implementations based on your current configuration and registrations.

The second step is to inject the service to the appropriate handler for the popup. Let's focus on implementing the actual popup. The easiest way to handle common infrastructure items is to create a common module. That module can contain elements that are shared between projects. First, we'll create a new child window and call it "Popup." The XAML looks like this (in my case, the project is Modules.Common and the Popup is in a subfolder called Views).

<controls:ChildWindow x:Class="Modules.Common.Views.Popup"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
           Width="Auto" Height="Auto" 
           Title="{Binding Title}">
    <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock TextWrapping="Wrap" Text="{Binding Message}" FontFamily="Arial" FontSize="12" TextAlignment="Center" Grid.Row="0"/>
        <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
    </Grid>
</controls:ChildWindow>

The main thing to note is the use of Auto to ensure the dialog resizes based on the content. Now for the code behind.

public partial class Popup
{   
    public Popup()
    {
        InitializeComponent();
    }

    public Popup(MessageBoxPayload payload)
    {
        InitializeComponent();
        DataContext = payload;
        CancelButton.Visibility = payload.AllowCancel ? Visibility.Visible : Visibility.Collapsed;
    }                

    private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = true;
        MessageBoxPayload result = (MessageBoxPayload) DataContext;
        result.Result = true; 
        result.ResultHandler(result);
    }

    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = false;
        MessageBoxPayload result = (MessageboxPayload)DataContext;
        result.Result = false;
        result.ResultHandler(result);
    }
}

The key here is that we have a constructor that takes in the payload and sets the data context, then sets the visibility of the cancel button. Then there are events bound to the buttons that will set the appropriate result then call the handler specified for the dialog close event.

One confusing topic here may be how to get the view into the application. If this is truly a decoupled module, how will it "know" about the regions you've defined? Furthermore, even if you iterated the region collection and injected it to the first one you found, you will find a goofy, empty popup window just hanging out. Not exactly what we want! In order to manage this popup, we'll use a controller.

The popup controller looks like this:

public class PopupController
{
    public PopupController(IEventAggregator eventService)
    {
        eventService.GetEvent<MessageBoxEvent>().Subscribe(PopupShow);
    }

    public void PopupShow(MessageBoxPayload payload)
    {
        Popup popupWindow = new Popup(payload);
        popupWindow.Show();          
    }
}

Now we can set up our module to invoke the controller.

public class CommonModule : IModule
{               
    private readonly IUnityContainer _container;

    public CommonModule(IUnityContainer container)
    {
        _container = container;
    }

    public void Initialize()
    {
        _container.RegisterInstance(_container.Resolve(typeof (PopupController)));         
    }
}

Notice we aren't registering with a region. Instead, we simply resolve a single instance of the controller. This will subscribe to the popup event. Because we use the container to resolve the controller, the container will automatically reference the EventAggregator and inject it into the constructor. Last but not least, this module simply needs to get registered with the module catalog:

protected override IModuleCatalog GetModuleCatalog()
{
    ModuleCatalog catalog = new ModuleCatalog();
    catalog.AddModule(typeof (MySpecificModule));
    catalog.AddModule(typeof (CommonModule)); 
    return catalog; 
}

Again, because we registered the EventAggregator earlier, it will pass the container along to the module and inject the aggregator into the controller. Now, when we publish the event, a nice child window will appear for us:

Silverlight popup

Of course, you can extend this to have the controller manage multiple windows, customize the button text or add nice images as well. This is just one of the many ways use of dependency injection and the event aggregator pattern can help the need (give me a response) from the implementation (show a popup) and provide an easy way to reuse components across applications.

Jeremy Likness

Thanks to those of you who read my Twist on the Observer pattern and gave me the feedback. You said,

"Hey, Jeremy, that's neat, but there is already a pattern established for what you're talking about, and a few great solutions ready to use. Besides, they are much, much more powerful..."

Thanks to Microsoft MVP Jason Rainwater for taking the time to give me an excellent explanation and for really delving into the inner workings of the solution.

The solution is the event aggregator pattern. For a good introduction, check out Jeremy Miller's brain dump on the topic.

The PRISM/CAL comes with its own event aggregator. It supplies a IEventAggregator that you can wire into your dependency injection container, then reference throughout the project.

In my base service class (seen by all) I create an event like this:

...
public class EntitySelectedEvent : CompositePresentationEvent<MyEntity>
{
}
...

In the view model for the module that has to "wake up" when the entity is selected, I inject the aggregator into the constructor and then do this:

...
eventAggregator.GetEvent<EntitySelectedEvent>().Subscribe(u=>this.entity=u); 
...

When the entity is selected (in a completely different module), I can simply publish:

...
eventAggregator.GetEvent<EntitySelectedEvent>().Publish(entity);
...

That's it! One module listens for the selection and reacts, not caring where/who or how it is published (which means we can publish a test entity in our unit test and test the subscription mechanism) ... while another module publishes the event and doesn't care who is out there listening.

For those of you who weren't familiar with the pattern or the implementation, I hope this helps get you excited and adds another element to your arsenal of coding techniques!

Jeremy Likness

The observer pattern is well established and used. The typical scenario is to register to an class and then allow your Notify method to be called. This often involves keeping an internal list of observers and then iterating them to notify that something has changed. I had a situation recently that warranted a lighter weight approach that allows a many-to-many observation (multiple listeners, multiple objects to observe).

I was working with the Composite WPF/PRISM framework and had an interesting situation. One of my regions is implemented as a TabControl, so modules that register with the RegionManager inject their views into the tabs. This is a very powerful model because now I can add as many modules/views as I like and not worry about the implementation details of wiring up the tab control. I created a view interface IViewable to implement with my controls that exposes the name of the view along with a boolean indicating whether the view should be enabled (this allows me to restrict going to certain tabs if they depend on data from another tab).

The issue was figuring out the best way to handle the tab focused event. By default, the views are wired up and ready to go when you click the tab. I tried searching for a solution to allowing my view to know when it was "active" but didn't find much that was satisfactory. It could be I'm completely off on my approach because there is some pattern already existing, but I decided to go with something very lightweight ... even lighter than the observer pattern. I don't want to know the details of what the other views or modules are, I just want to know when I'm getting focus and that is controlled by my parent container (I also shouldn't know that my parent container is a TabControl - it could be any ItemsControl for that matter).

The pattern was quite simple, really. First, I created an interface:

public interface IObservableHelper 
{
   void Notify(object obj); 
   event EventHandler<EventArgs> Notified; 
}

The implementation was easy too:

public class ObservableHelper : IObservableHelper
{
   public void Notify(object obj) 
   {
      if (Notified != null) { Notified(obj, EventArgs.Empty); }
   }

   public event EventHandler<EventArgs> Notified;
}

See, very easy. I don't have to keep track of the objects observing because objects who want to know about this event simply register to the event. In my boot strapper class I make sure there is exactly one instance of the helper:

...
Container.RegisterInstance<IObservableHelper>(new ObservableHelper()); 
...

With the dependency injection, the helper can be injected simply by asking for it in the constructor. That means in my view, I can do this:

public MyView(IObservableHelper helper)
{
   helper.Notified += (obj,args) =>
   {
      if (obj == this) { DoSomething(); }
      else if (obj is ISomeInterface) { DoSomethingElse((ISomeInterface)obj); }
   }; 
}

// observe "me" 
public void DoSomething()
{
} 

// observe "ISomeInterface" 
public void DoSomethingElse(ISomeInterface someInterface)
{
}

I've just registered to, eh, observe "myself." That's OK ... as a view, what I really want to know is when I am activated. So in the shell, I simply tap into the selection changed event for the Tab Control. That will resolve IObservableHelper then call notify with the element that was selected. Notified will fire, I'll see its "me" and then call DoSomething. Very lightweight and decoupled ... and if there are other objects participating, I can interact with them as well!

Jeremy Likness