views:

47

answers:

2

Hello,

I got my hands om MEF for a week now and I am trying to build up a WPF application that loads imported controls from MEF.

I created a WPF application project and removed the default window and application start up URI. Then I handled the application startup event to compose the application:

public partial class App : Application, IPartImportsSatisfiedNotification
{
    {...}

    private void App_Startup(object sender, StartupEventArgs e)
    {
        this.Compose();
    }

    public void Compose()
    {
        try
        {
            globalCatalog.Catalogs.Add(new DirectoryCatalog(extensionsDirectoryPath));
            CompositionContainer container = new CompositionContainer(globalCatalog);
            container.ComposeParts(this);
        }
        catch (Exception ex)
        {
            // Do something
        }
    }

    {...}
}

Actually, when debugging and watching objects after imports are satisfied, everything has hierarchically composed fine like I wanted. But when I try to show up the MainWindow of the application an exception is thrown on MainWindow.Show() call:

"Specified element is already the logical child of another element. Disconnect it first."

Though my code in OnImportsSatisfied method seems fine as it is working when not using MEF mecanism:

public void OnImportsSatisfied()
{
    Window mainWindow = new Window();
    mainWindow.Content = this.importedControl;
    this.MainWindow = mainWindow;
    this.MainWindow.Show();
}

I insist on the fact that this works perfectly when not importing controls with MEF. What is surprising is that this code does not work too:

Window mainWindow = new Window();
//mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();

So I suspect that ComposeParts is doing a bit more than what it says as it is the only member acting on my actual application instance.

Hope someone can help me (Glenn?). Thanks.


Edit:

I discovered that when I remove the IPartImportsSatisfiedNotification interface from my parts, no exception is thrown and the window shows up. But of course the window is empty as I need this OnImportsSatisfied method to set the DataContext of the window to its associated imported view model.

A: 

I finally discovered that I was importing my WPF user controls by using the default ImportAttribute constructor, which in fact will make a shared instance of the class if the creation policy is not specified during export. And as many of my controls were implementing the same interface and I was binding them in my views, I was actually trying to add this shared user control instance to different visual elements, which is not permited by WPF (and so the exception).

I marked my imports using the RequiredCreationPolicy set to NonShared and everything got back in order! That was all about learning MEF...

Ucodia
+1  A: 

The sample applications of the WPF Application Framework (WAF) show how to use MEF within a WPF application.

jbe
Thanks for the link.
Ucodia