Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using MEF in controls instantiated from XAML

Tags:

c#

.net

wpf

xaml

mef

I have a UserControl I've created which imports several parts using the [Import] attribute.

public class MyUserControl : UserControl, IPartImportsSatisfiedNotification
{
    [Import]
    public IService Service { get; set; }

    public MyUserControl()
    {
    }

    public void OnImportsSatisfied()
    {
        // Do something with Service.
    }
}

This UserControl is instantiated from XAML, so its imports aren't being satisfied and OnImportsSatisfied isn't being called.

<local:MyUserControl />

My question is how can I satisfy my class's imports when it's being created in XAML.

like image 882
Adi Lester Avatar asked Dec 29 '11 12:12

Adi Lester


1 Answers

From MSDN:

To be instantiated as an object element in XAML, a custom class must meet the following requirements:
The custom class must be public and must expose a default (parameterless) public constructor. (See following section for notes regarding structures.)
The custom class must not be a nested class. The extra "dot" in the full-name path makes the class-namespace division ambiguous, and interferes with other XAML features such as attached properties.
If an object can be instantiated as an object element, the created object can fill the property element form of any properties that take the object as their underlying type.
You can still provide object values for types that do not meet these criteria, if you enable a value converter. For more information, see Type Converters and Markup Extensions for XAML.

From there, you have two choices:
1) Using a TypeConverter:
Using a type converter will allow you to instantiate an object without a parameterless constructor, but you will have to provide a TypeConverter that will do the instantiation.

Now, I never had to use it, I cannot help you further with that.

2) Retrieve IService using the ServiceLocator:

public class MyUserControl : UserControl
{    
    public IService Service { get; set; }

    public MyUserControl()
    {
       Service = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IService>();
       // You can do something with Service here already.
    }
}

I realize it is a change in the design of your class, but hopefully you can cope with it.

Hope this helps,

Bab.

like image 198
Louis Kottmann Avatar answered Oct 15 '22 10:10

Louis Kottmann