Using MEF in XAML Controls

I have a UserControl that I created that 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 created from XAML, so its import is not performed and OnImportsSatisfied not called.

 <local:MyUserControl /> 

My question is how can I satisfy the import of my class when it is created in XAML.

+6
source share
3 answers

From MSDN:

To create an instance as an element of an object in XAML, a custom class must meet the following requirements:
The user class must be publicly accessible and must provide a public default constructor (no parameters). (See the next section for notes on structures.)
A custom class should not be a nested class. An additional β€œdot” in the path with the full name makes the separation of the class namespace ambiguous and prevents other XAML functions, such as attached properties.
If the object can be created as an element of the object, the created object can fill in the form of the property element of any properties that accept the object as the main type.
You can still provide object values ​​for types that do not meet these criteria if you enable the value converter. For more information, see Type Converters and Markup Extensions for XAML.

From there you have two options:
1) Using TypeConverter :
Using a type converter will allow you to instantiate an object without a constructor without parameters, but you will have to provide a TypeConverter that will execute the instance.

Now I never had to use it, I can not help you with this.

2) Extract the IService using 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 understand that this is a change in the design of your class, but I hope you can handle it.

Hope this helps,

Women.

+2
source

If you do not want mef to create your usercontrol, you need to use the compound connector in your usercontrol and call GetExport direct. but then you have a problem to get an instance of your composition container :)

ps: i let mef create my wpf views in my applications.

0
source

(I resurrect this in case anyone encounters this. As an expression of disclaimer, I am not an expert, and these are just solutions that I found working.)

I found that calling CompositionContainer.ComposeParts(myUserControl) works. I call this on the management constructor. You need to somehow get a link to the CompositionContainer:

 public MyUserControl() { compositionContainer.ComposeParts(this); } 

Additional solution:

This is probably unnecessary, but here is another way. This is much more confusing, but allows you to " Import " control the user in XAML.

For your import to be satisfied, MyUserControl needs to be exported and then an instance of MEF created. My solution was to have a static field in the class that contains the Locator object. This locator object is responsible for importing and returning exported objects. Then I could refer to this static field in XAML, like so:

<ContentControl Content="{Binding MyUserControl, Source={x:Static v:SomeClass.Locator}}">

SomeClass has a static property called Locator , which is assigned early in the application life cycle. The locator can have the MyUserControl property, which gets Import ed.


(Disclaimer: The links below refer to my own structure, and a solution as rude as it is should be used with caution.)

To give an example of the above, I will explain how I implemented it in my environment:

In my case, SomeClass is a subclass of System.Windows.Application that replaces App.xaml , and the ViewLocator is assigned to its OnStartup , as can be seen here .

The ViewLocator class is a System.Dynamic.DynamicObject that imports views that have their own ViewExport attribute. Views are identified using the ViewExportAttribute.Alias property.

This is an example of an export that is assigned an alias.

Finally, an instance of the MEF view instance can be used in XAML as follows:

<ContentControl Content="{Binding HomeView, Source={x:Static v:FrameworkApp.ViewLocator}}">

0
source

Source: https://habr.com/ru/post/904662/


All Articles