Wintellect  

Browse by Tags

All Tags » Managed Extensibility Framework   (RSS)

Over the past few weeks I've been exploring the concept of region management using the Managed Extensibility Framework, and for a good reason. I'm working on a project that has several different regions and controls that must be managed effectively and across the boundaries of dynamic XAP files in Silverlight 3.

Sound like a mouthful? In previous posts I demonstrated some methods for handling region management using MEF. This post is an advanced post and I'm assuming you have the fundamentals of MEF down. If not, I would come back to this post at a later time. You'll also want to be familiar with my previous experiments detailed in this article and another version in this video tutorial.

So the ultimate goal for me is to tag a view with a type, tag a region with a type, then route views to regions and vice versa. This way I can easily add controls (just tag 'em) and regions (again, tag 'em) and have a routing table that handles swapping them in and out for me.

One of the issues in the past has been having to explicitly export the region. In other words, I might have a ContentControl tagged for a particular region. I have to give it an x:Name in the XAML, like this:

...
<ContentControl x:Name="MyName"/>
...

And then export it with my custom attributes like this:

...
[TargetRegion(Region=ViewRegion.MainRegion)]
public FrameworkElement MainRegionExport 
{
   get { return MyName; }
}
...

This assumes I created a custom export attribute with a Region parameter and a base type of FrameworkElement. Where I want to go is here: eliminate the code behind, and tag my regions like this:

...
<ContentControl mef:TargetRegion.Region="MainRegion"/>
...

In the XAML, with no code behind. Can we get there? Of course, this is MEF!

The first step for me is to create to a custom export provider. I spoke briefly about this in an old post: Custom Export Provider for Attached Exports, but that was for static controls. Here, I want to export regions with meta data. The export provider looks like this:

public class RegionExportProvider : ExportProvider
{
    private static readonly Dictionary<ExportDefinition, List<Export>> _exports = new Dictionary<ExportDefinition, List<Export>>();

    private static readonly RegionExportProvider _provider = new RegionExportProvider();

    public static DependencyProperty RegionProperty = 
        DependencyProperty.RegisterAttached(
        "Region", 
        typeof(ViewRegion), 
        typeof(RegionExportProvider),
        null);       

    public static ViewRegion GetRegion(DependencyObject obj)
    {
        return (ViewRegion) obj.GetValue(RegionProperty);
    }

    public static void SetRegion(DependencyObject obj, ViewRegion value)
    {
        obj.SetValue(RegionProperty, value);
        GetRegionExportProvider().AddExport(value, obj);
    }

    private static readonly object _sync = new object();

    public static RegionExportProvider GetRegionExportProvider()
    {
        return _provider;
    }

    public void AddExport(ViewRegion region, object export)
    {
        lock (_sync)
        {
            string contractName = typeof (FrameworkElement).FullName;

            var metadata = new Dictionary<string, object>
                               {
                                   {"ExportTypeIdentity", typeof (FrameworkElement).FullName},
                               }; 

            var found =
                from e in _exports
                where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                select e;
            
            if (found.Count() == 0)
            {                    
                var definition =
                    new ExportDefinition(contractName, metadata);

                Debug.WriteLine("Region Export Provider: Add custom export: " + region);

                _exports.Add(definition, new List<Export>());
            }

            metadata.Add("Region", region); 

            var wrapper =
                new Export(contractName, 
                    metadata, 
                    () => export);

            found.First().Value.Add(wrapper);
        }
    }

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
    {
        var contractDefinition = definition as ContractBasedImportDefinition;
        IEnumerable<Export> retVal = Enumerable.Empty<Export>();
        
        if (contractDefinition != null)
        {
            string contractName =
                contractDefinition.ContractName;
            
            Debug.WriteLine("GetExportsCore: Request for contract: " + contractName);

            if (!string.IsNullOrEmpty(contractName))
            {
                var exports =
                    from e in _exports
                    where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                    && definition.IsConstraintSatisfiedBy(e.Key)
                    select e.Value;

                if (exports.Count() > 0)
                {
                    Debug.WriteLine("Export satisfied.");
                    retVal = exports.First();
                }
                else
                {
                    Debug.WriteLine("Export was not satisfied.");
                }
            }
        }

        return retVal;
    }
}

Let's step through it. First, I need to keep a catalog of my exports. These are unique type definitions and contract names that we are going to satisfied with our custom export provider. I use the singleton pattern because I'm going to double this class as an attached behavior. Probably violating the single responsibility principle here, and could break it out, but let's run with it for now. Sometimes it makes sense to keep the code together for readability and maintainability.

The attached property just takes the type of the region. Because we type it to the enumeration, intellisense will work in the XAML when adding the behavior, which is nice, because it makes it less of a "magic string" for us to use.

The key to note is the setter. When we set the value, we add the export. The export itself is going to be the contract name and the type identity. This is why we add the first bit of meta data, the ExportTypeIdentity, and then see if we've already made an entry or not. If not, we add a new entry with an empty list of the actual exports.

Adding the exports is easy. Metadata on an export is really just a dictionary of labels and values. We know this particular export has one label ("Region") and that it is the enum of the region type. Therefore, once we find or create our export definition, we go ahead and add the export with the region itself (a content control, items control, or other container) and meta data for that region (in this case, the "Region" tag and the enumeration value).

Now we just need to be prepared to supply the exports when our custom provider is queried. This is the GetExportsCore. Fortunately, we get it easy. Instead of having to keep track of all of the rules, the import definition comes with a IsConstraintSatisfiedBy method that calls the Constraint provided to filter the export values. We simply find the definition that matches the contract and the constraint, then provide all of the exports we have. These will then have their meta data parsed and if a capabilities interface is provided, it will be populated with the values so that the Lazy<Type,ITypeCapabilities> target can be populated. Notice I added some debug lines to help troubleshoot.

Now I can tag my export the way I wanted to:

...
<ContentControl mef:RegionExportProvider.Region="MainRegion" .../>
...

There is only one more step I need to take in order for this all to work. Remember back when I showed you how to override the container so we could continue to compose new DeploymentCatalogs into an AggregateCatalog as they became available? When we create that special container, we need to add our secret sauce. We do it like this:

...
var container = new CompositionContainer(catalogService.GetCatalog(), RegionExportProvider.GetRegionExportProvider());
...

Now we've told the container to query our own custom export provider when trying to satisfy parts.

If you recall from my prior posts, I used a routing class to map view types to regions, and loaded the regions like this:

[ImportMany(AllowRecomposition = true)]
public Lazy<FrameworkElement, ITargetRegionCapabilities>[] RegionImports { get; set; }

Our new provider kindly exports the tagged regions, which are then imported with the routing class and used to swap views in and out of the display.

Jeremy Likness

This is a video tutorial to introduce beginners to how to use both MVVM (Model-View-ViewModel) and MEF (Managed Extensibility Framework) with Silverlight (should work for versions 3 and 4). Of course, some "veterans" may want to watch as well in case you've missed some of the fundamentals, or have a clever way to do something that you can share in the comments for future visitors to the page.

In this edition, I build a simple application that allows the user to check a preference on the screen (whether they prefer squares over circles) and then displays a square or a circle. We use MVVM and wire everything together with MEF.

Download the source code: MEFMVVMDemoSln.zip

Click here to watch the video directly if it doesn't appear in the frame below (recommended to watch in full screen): Watch the video in a separate window

Here is the final application:

Download the source code: MEFMVVMDemoSln.zip

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

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

I've been enjoying learning more about the Managed Extensibility Framework (MEF) and exploring various ways to integrate it with applications. After toying with MEF on Silverlight for awhile, I began to wonder about using it to export/import UI pieces or even define data elements in XAML. After a tweet to @gblock confirmed there was not native support, I set out to see what I could do. (If you're not familiar with MEF, take a look at my 10 minute walkthrough.)

The result is by no means ideal and is certainly a contrived "proof of concept" solution, but I believe it will help expose some of the custom extension points available with MEF and just how flexible it truly can be.

Download the Source

My goal was to minimize code behind for a common scenario of having pages with groups of widgets. Widgets will most likely be defined as user controls, but we've already seen plenty of examples there. I wanted to be able to define them as resources in pure XAML, no code behind, then import them into something like a StackPanel as child elements.

The Attachable View Model

The first thing I created was an attachable view model. It would get a list of FrameworkElement for binding to a control. To make it even more interesting, I wired in an attached property. This way I can simply attach the view model to a control and it will automatically pull in the parts and populate the children.

The initial shell looked like this:


public class ViewModel
{
    private static List<FrameworkElement> _uiParts = new List();
    
    [ImportMany("UIPart", AllowRecomposition = true)]
    public List<FrameworkElement> UIParts
    {
        get { return ViewModel._uiParts; }
        set { ViewModel._uiParts = value; }
    }

    public ViewModel()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    static ViewModel()
    {
        new ViewModel();
    }

    public static readonly DependencyProperty ViewBinderProperty = DependencyProperty.RegisterAttached(
        "ViewBinder", typeof(bool), typeof(ViewModel), new PropertyMetadata(new PropertyChangedCallback(OnViewBound)));

    public static void OnViewBound(object sender, DependencyPropertyChangedEventArgs args)
    {
        // make sure we want this ...
        if (args.NewValue != null && args.NewValue.GetType().Equals(typeof(bool)) && (bool)args.NewValue)
        {
            Panel panel = sender as Panel;
            if (panel != null)
            {
                // iterate the parts
                foreach (FrameworkElement element in _uiParts)
                {
                    // clone it
                    FrameworkElement newElement = Clone(element);
                    
                    // give it a unique name
                    newElement.SetValue(FrameworkElement.NameProperty, Guid.NewGuid().ToString());
                    
                    // inject it
                    panel.Children.Add(Clone(newElement));
                }
            }
        }
    }

    public static bool GetViewBinder(DependencyObject obj)
    {
        return (bool)obj.GetValue(ViewBinderProperty);
    }

    public static void SetViewBinder(DependencyObject obj, bool value)
    {
        obj.SetValue(ViewBinderProperty, value);
    }
}

So far it feels pretty much like a standard class hosting a dependency property. You'll notice it's a bit strange, however, as the class itself is not static. This is because MEF is expecting an instance to compose the parts in. To facilitate that, I have an instance constructor that follows the general MEF pattern ... throw the catalog into the container and compose the parts. The "instance" getter and setter is really a facade that populates the static list of parts, in this case I'm just asking for any type of FrameworkElement. Obviously, those will have to come from somewhere else.

Because my intention is to use a resource dictionary, I must be able to share the elements. Silverlight won't let you take an element that is already the child of another element and then move it somewhere else. I have to assume I may reuse some of these elements as well (for example, this could be extended with a filter to choose the types of elements). So, instead of adding the elements directly to the parent, I am cloning them.

Thanks here goes to Justin Angel for his very functional clone method that I found here. I left it out of the code snippet above to keep it simple, but it is included in the source.

Now we need to tackle the task of exporting the framework elements. Ideally, I just want to put them into a resource dictionary, tag them somehow, and have the magic work. Fortunately, MEF gives us a nice ExportProvider we can derive from to do just that. There's an excellent article I started with by the "Code Junkie" you can access here.

It may have made more sense to split out the dependency properties and the provider to separate classes, but I figured, why not? So here is a custom export provider that also hosts some attached properties to facilitate exporting XAML:


public class XAMLProvider : ExportProvider
{
    private static readonly Dictionary<ExportDefinition, List<Export>> _exports = new Dictionary<ExportDefinition, List<Export>>();

    private static readonly XAMLProvider _provider = new XAMLProvider();

    public static DependencyProperty MEFExportProperty = DependencyProperty.RegisterAttached("MEFExport", typeof(string), typeof(XAMLProvider),
        new PropertyMetadata(new PropertyChangedCallback(OnMEFExport)));

    public static void OnMEFExport(object sender, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue != null && !string.IsNullOrEmpty(args.NewValue.ToString()))
        {
            string contract = args.NewValue.ToString();
            _provider.AddExport(contract, sender);
        }
    }

    public static string GetMEFExport(DependencyObject obj)
    {
        return (obj).GetValue(MEFExportProperty).ToString();
    }

    public static void SetMEFExport(DependencyObject obj, string value)
    {
        obj.SetValue(MEFExportProperty, value); 
    }

    private static readonly object _sync = new object();

    public static XAMLProvider GetXAMLExportProvider()
    {
        return _provider;
    }

    public void AddExport(string contractName, object export)
    {
        lock (_sync)
        {
            var found =
                from e in _exports
                where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                select e;

            if (found.Count() == 0)
            {
                ExportDefinition definition =
                    new ExportDefinition(contractName, new Dictionary());

                _exports.Add(definition, new List<Export>());
            }

            Export wrapper =
                new Export(contractName, () => export);

            found.First().Value.Add(wrapper);
        }
    }

    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
    {
        var contractDefinition = definition as ContractBasedImportDefinition;
        IEnumerable<Export> retVal = Enumerable.Empty<Export>();

        if (contractDefinition != null)
        {
            string contractName =
                contractDefinition.ContractName;

            if (!string.IsNullOrEmpty(contractName))
            {
                var exports =
                    from e in _exports
                    where string.Compare(e.Key.ContractName, contractName, StringComparison.OrdinalIgnoreCase) == 0
                    select e.Value;

                if (exports.Count() > 0)
                {
                    retVal = exports.First();
                }
            }
        }

        return retVal; 
    }
}

The only override provided is to actually get the exports for a provided input definition. Everything else is left to us.

The first thing I did was create a dictionary. The key is the contract name (in MEF, the contract name is just a string ... if you use a type or an interface, then the fully qualified name becomes the string for the contract). The value is a list of all exports attached to that contract.

The dependency property allows me to attach "MEFExport" to any XAML object and give it a contract name. When this property is attached, it will look for the name in the dictionary and then either create a new entry or add the element to the existing list. It's as simple as that!

When the GetExportsCore is called, we are given an import definition. For a more complex example, we could look at attributes and other extensions. In this case, I'm simply extracting the contract name, finding the key in the dictionary and then sending off any exports that were loaded with the key.

Now I can add a resource dictionary and tag my elements for export. Mine looks like this:


<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MEFExtension">
    <TextBlock FontSize="32" Text="This is a text block." x:Key="ui1" local:XAMLProvider.MEFExport="UIPart"/>
    <Rectangle Width="100" Height="100" Fill="Red" x:Key="ui2" local:XAMLProvider.MEFExport="UIPart"/>
    <TextBlock FontSize="16" Text="This won't get imported." x:Key="ui3"/>
    <Ellipse HorizontalAlignment="Left" Fill="Blue" Stroke="Black" Width="100" Height="50" x:Key="ui4" local:XAMLProvider.MEFExport="UIPart"/>
</ResourceDictionary> 

I threw in a dummy text block without tagging it to show that it won't get exported because the property is not attached. So now when that resource dictionary is pulled in, we can parse the XAML and export the elements. We need to let MEF know about our custom provider. Going back to my view model, I'll change the container creation to this:


var container = new CompositionContainer(catalog, XAMLProvider.GetXAMLExportProvider());
            

Notice I now passed in our custom export provider.

Now all of the elements are in place. The custom export provider knows how to scan XAML and load up elements for export, we've added a resource dictionary with some elements to export, and the view model is asking for imports and has its own attached property so that we can push the elements to any type of panel.

Last step: I go into my main page, pull in the resource dictionary and bind the view model:


<UserControl x:Class="MEFExtension.MainPage"
    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" d:DesignWidth="640" d:DesignHeight="480"
    xmlns:local="clr-namespace:MEFExtension">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <StackPanel Orientation="Vertical" Width="Auto" local:ViewModel.ViewBinder="true"/>
</UserControl>

So the resource dictionary will get pulled in. As the keys are processed, it will fire the attached properties and load them into exports. I gave them the "UIPart" contract. When the view model is attached, it will new an instance that fires the composition container for MEF. This will use the custom provider. Because we have the list of elements marked "UIPart", the exports will match and get loaded. The attach event will clone these objects and add them as children to the stack panel.

The result?

Silverlight MEF ExportProvider

There you have it, an example of extending the, ah, Managed Extensibility Framework, to support exporting using attached properties in XAML (I did this in Silverlight 3, so I had to add the reference to the System.ComponentModel.Composition from the download ... it is included in Silverlight 4).

Download the Source

Jeremy Likness

In preparing for an upcoming talk I'll be giving on the Managed Extensibility Framework (MEF), I wanted to demonstrate how fast and easy it is to use in a sample, reference application. This application creates a dynamic plugin. I first link a plugin and show it active, then I create a second plugin and show how it is dynamically added to the program during runtime. It all takes under 10 minutes and would be faster if I didn't want to pace the demo to show the steps involved.

Here is a direct link to the video

Here it is embedded:

Jeremy Likness