MEF & XAML integration

Feb 5, 2010 at 11:34 PM

Hey guys,

I've seen some examples of Importing a button or otherwise in the XAML code behind file, but is it possible to do it in the XAML instead?

Maybe something like this?

<Button mef:ImportContract="ButtonContract"/>

I'd be open to writing an ExportProvider (ImportProvider?) if it is possible to do. 


Feb 5, 2010 at 11:44 PM

ExportProvider won't necessarily help you. Are you doing this in Silverlight or WPF?

Feb 5, 2010 at 11:50 PM


Feb 6, 2010 at 12:29 AM

The type of syntax you are trying to do won't work, as XAML is responsible for creating the button. You could use a custom ContentControl though that lets you specify a contract which it imports.

The syntax might look something like this....

<CompositionContentControl ImportContract="ButtonContract"/>

Under the hood the control would either use PartInitializer or a container to pull the desired contract from the container. It would then set the ContentProperty to that value.

It would be nice if you could just set an import to a dependency prop value directly, but for that you need markup extensions which are currently not supported.

An alternative would be to have an atttached property rather than a ContentControl though you would have to somehow still map the atttached property to the underlying "value" of the control.


Feb 6, 2010 at 12:57 AM
Edited Feb 6, 2010 at 3:32 AM

Ah, I see.  That sounds similar to what I'm already doing with a ViewStub that on creation fills its content with the real View via UnityContainer.  
The problem is that if I want to set some properties in the XAML I have to make sure that I'm passing the data through the ViewStub to the 'real' view.

    Public Property SampleDependencyProperty() As Integer
            Return View.SampleDependencyProperty
        End Get
        Set(ByVal value As Integer)
            View.SampleDependencyProperty = value
        End Set
    End Property
I'll try what you suggest with my current design replacing what I'm doing with Unity with MEF Imports.  
What I'd really love to see is some extension or way to extend Silverlight XAML such that I could specify 
a MEF import an a XAML element as above and have it set the properties on the imported object when I call ComposeParts.  
Maybe this could be done with Lazy(Of T) typing when xaml.g.vb is generated somehow?
Anyway, thanks for the quick responses.  Maybe this is a Silverlight 5 feature request? =)


Feb 6, 2010 at 6:14 AM

I hear ya. We orignally planned to allow that through a markup extension, however custom markup extensions are not yet supported. With an ME you could do something like this...

<Button Content="{Import ButtonContent}"/> for example.

We will look to do this post SL4 if the ME infrastructure is rolled in. One thing you "could" do now to allow setting properties, is make the attached property actually be a complex object rather than a simple contract name. The object could contain a collection of import info objects that each specify a DP property name and a contract name. Then in the attached property you parse the collection and then pull the values from the container and push them in. It's not what I would consider optimal, but it could work :-)

Feb 8, 2010 at 12:35 AM

Thanks for the info about SL markup extensions.  I'll keep my eye on their progress in the future.  In the meantime I may see what I can do with your attached property suggestion above to see if it might be more light weight than doing a wrapper property each time.



Feb 23, 2010 at 12:07 AM

I'm back with another question related to my posts above.  Is there any way to make this situation "Blendable"?  I'm calling PartInitializer.SatisfyImports(Me) inside of my stub view'sconstructor and then setting the content of the stub view to the actual View, which contains the XAML markup.  This works at runtime, but I'm having issues when I run the control in expression blend.  Maybe this isn't possible, but I want to run it by the MEF gurus before I give up on it.  My first guess is that somehow the Partinitializer running in Expression Blend isn't looking at my Extensions assembly when PartInitializer.SatisfyImports is called, because it isn't actually running inside a Silverlight Application.

Assembly 1 ViewStubs
Assembly 2 ViewExtensions (actual view assembly)
Assembly 3 ViewContracts (interfaces used to mark the views as exports)

I'm opening Control A, which has two child controls B, and C.  Control A is located in Assembly 2, and it has two stub views on it that are defined in Assembly 1.  When those stub views are filled with content the content comes from Assembly 2.

Is a way to do this in Blend with SatisfyImports?  Is there another way I could use at design time that might work?

Looking forward to your reponse.  I can try to re-phrase if this isn't making sense.



Feb 23, 2010 at 1:42 AM

It is possible, but it requires a bunch of work and even hackery. The problem from a Blend perspective is it does not automatically load the assemblies in the current XAP, thus when SatisfyImports is called none of the catalogs are present. The way to work around this is to force the catalogs to load. Doing this requires explicitly overriding the container with one that contains the assemblies iin the main XAP. Accessing the assemblies is where the challenge lies. The hackery involves calling through WPF to get to the assemblies as is described in this post:

As a side note, we are working with the Blend team to support design time catalogs in MEF which would remove the need for doing it yourself.



Feb 23, 2010 at 4:42 PM
Thanks again for the quick and informative responses.  The working solution I derived from your comments is below for anyone else who is having the same issue. 
I'm looking forward to this being a built-in feature in Expression Blend and hopefully VS 2010 Silverlight designers at some point in the future.
Namespace CompositionManagement
    'TODO - resolve ICompositionManager from a container
    Public Class CompositionManager

#Region "Constructors"

#End Region
#Region "Properties"
        Private _CompositionHostInitialized As Boolean

        Private Shared _Current As CompositionManager
        Public Shared ReadOnly Property Current() As CompositionManager
                If _Current Is Nothing Then
                    _Current = New CompositionManager
                End If
                Return _Current
            End Get
        End Property
#End Region
#Region "Methods"
        Public Sub SatisfyImports(ByVal instance As Object)
                If DesignerProperties.IsInDesignTool AndAlso Not _CompositionHostInitialized Then
                    'HACK - Suggested by Glenn Block to get around issues with SatisfyImports in Blend.
                    Dim catalog As New AggregateCatalog
                    Dim assemblies() As Assembly = GetType(AppDomain) _
                        .GetMethod("GetAssemblies") _
                        .Invoke(AppDomain.CurrentDomain, Nothing)
                    For Each assembly As Assembly In assemblies
                        'assembly.Location will fail with an error for dynamic assemblies
                        If TryCast(assembly, Emit.AssemblyBuilder) Is Nothing Then
                            If assembly.Location.Contains("\Local Settings\Application Data\Microsoft\Expression\Blend\Project Assemblies\") _
                            AndAlso Not assembly.FullName.ToLower.StartsWith("system.") _
                            AndAlso Not assembly.FullName.ToLower.StartsWith("microsoft.") Then
                                Dim assemblyCatalog As New AssemblyCatalog(assembly)
                            End If
                        End If
                    Dim container As New CompositionContainer(catalog)
                    _CompositionHostInitialized = True
                End If
            Catch ex As Exception
                Throw ex
            End Try
        End Sub
#End Region

    End Class

End Namespace
Feb 23, 2010 at 5:00 PM

Now that I'm seeing this control in Blend, I'm looking for a way to make all of my controls blendable.  Right now I'm using MEF both to resolve the View and the ViewModel inside my StubView class.  Here is a snippet of a View class.  IView is marked as an InheritedExport.  In order to make it blendable I had to add the parameterless constructor to my class directly referencing the ViewModel, which I dont' like.  I would like to have my View class import the viewmodel in my BaseView(Of T1, T2) class to be able to eliminate the constructors.  Ideally, I'd like my codebehind for my views to only include the class definitions and any attributes.  Is there a way to do this?  In the past when I tried this MEF complained telling me that I could not have an Imported property inside of a class that was marked as an Export.  I was able to work around the issue before, but now since blend requires a parameterless constructor in the ConcreteView class I need a way to avoid the strong reference to the ViewModel class, and I would like to use MEF rather than a normal DI container like Unity (used this in the past).

<PartCreationPolicy(CreationPolicy.NonShared)> _
Partial Public Class View
    Inherits ConcreteView
    Implements IView

    Public Sub New()
        Me.New(New ViewModel))
    End Sub

    <ImportingConstructor()> _
    Public Sub New(ByVal vm As IViewModel)
    End Sub
End Class

Public Class ConcreteView
    Inherits BaseView(Of IViewStub, IViewModel)

    Public Sub New()
        Me.New(New ViewModel)
    End Sub

    Public Sub New(ByVal vm As IViewModel)
    End Sub
End Class
Feb 23, 2010 at 6:19 PM

Hi Nick

I'd suggest looking into attached behaviors for this. With an attached behavior you can have the View/VM get wired up through XAML without requring either to know directly about the other. I did a prototype of using an attached behavior for wiring design time / runtime VMs with good results.


Feb 23, 2010 at 8:10 PM

This is great! Now I'll be able to hide those constructors in the base class.  The attached behavior that composes the parts worked.  I set it via a Style in my View class so I wouldn't have to set it all over the place in the XAML where the View was instanced.  That should be the finishing touch on making the controls blendable.

One more question.  This might be an easy one, but I didn't see an explicit example of it on the "Exports and Metadata" page.  I would like to specify some versioning information on my View so that only the current view is picked up as MEF composes parts.  An example of this would be attaching some metadata for an effective and expiration date, and then somehow hooking into composition somehow that would allow me to tell MEF only to compose the parts that are effective for the current system date (>=effective date and <=Expirationdate).

Thanks again,


Feb 23, 2010 at 8:21 PM

Come to think of it I'd probably only want to specify the effective date on each View.  Ideally, I'd sort the list of IViews by effective date and then assign whichever ones are currently effective based on the system date.  This way if a new View was added it wouldn't be a requirement to update the expiration date on the old view (might be useful with Silverlight 4 when MEF will allow me to add XAPs at runtime).  I guess that means I'd need a way to override MEFs default metadata filtering.


Feb 24, 2010 at 7:02 PM

I think I've got a solution.  This article helped out.

Mar 25, 2011 at 12:25 AM

Thanks guys.  I did come up with a solution that worked for me with help from this thread and a post from John Papa