Click here to Skip to main content
13,147,629 members (29,900 online)
Click here to Skip to main content
Add your own
alternative version


11 bookmarked
Posted 2 Dec 2009

Silverlight MEF: Custom ExportProvider for Attached XAML Exports

, 2 Dec 2009
Rate this:
Please Sign up or sign in to vote.
Use the Managed Extensibility Framework to export dictionary resources using custom ExportProvider in Silverlight

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 a while, 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.

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<FrameworkElement>();
    [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);

    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

    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<string,>());

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

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


    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 =

            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:




    <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." 

    <Ellipse HorizontalAlignment="Left" Fill="Blue" 

    Stroke="Black" Width="100" Height="50" 

    x:Key="ui4" local:XAMLProvider.MEFExport="UIPart"/>

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"





    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"

                <ResourceDictionary Source="Resources.xaml"/>
    <StackPanel Orientation="Vertical" 

    Width="Auto" local:ViewModel.ViewBinder="true"/>

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?


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).

You can download the source code from here.

Jeremy Likness


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Jeremy Likness
Architect iVision
United States United States
Jeremy Likness is a principal consultant and leads the application development practice at iVision, Inc. Jeremy, an experienced entrepreneur and technology executive, has successfully helped ship commercial enterprise software for 20 years. He specializes in catalyzing growth, developing ideas and creating value through delivering software in technical enterprises. His roles as business owner, technology executive and hands-on developer provided unique opportunities to directly impact the bottom line of multiple businesses by helping them grow and increase their organizational capacity while improving operational efficiency. He has worked with several initially small companies like Manhattan Associates and AirWatch before they grew large and experienced their transition from good to great while helping direct vision and strategy to embrace changing technology and markets. Jeremy is capable of quickly adapting to new paradigms and helps technology teams endure change by providing strong leadership, working with team members “in the trenches” and mentoring them in the soft skills that are key for engineers to bridge the gap between business and technology.

You may also be interested in...


Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170915.1 | Last Updated 2 Dec 2009
Article Copyright 2009 by Jeremy Likness
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid