Search code examples
wpfshellscreenmefcaliburn.micro

MEF import does not work with a Shell that has more than one active screen


Hi I user WPF/Calibur Micro/MEF. I I try have more active screen in shell. First I define screens - User controls.

  1. Screen - View model
public interface IProjectsViewModel
{

}
[Export(typeof(IProjectsViewModel))]
public class ProjectsViewModel:Screen,
    IProjectsViewModel
{

}

2.Screen -View Model

public interface IProjectInfoViewModel
{

}

[Export(typeof(IProjectInfoViewModel))]
public class ProjectInfoViewModel :Screen, 
    IProjectInfoViewModel
{
    [Import]
    internal IMessageBox MsgBox { get; set; }

    public void BtnClick()
    {
        MsgBox.ShowInfo("Btn click",string.Empty);
    }
}

I second screen I have only one button if user click on the button it showed message box.

No most important part shell. Shell is WPF window.

View:

<Window x:Class="CaliburnSkelet.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:Views="clr-namespace:CaliburnSkelet.Views" 
        xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" 
        Title="ShellView" Height="300" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <!--<ContentControl x:Name="Projects" Grid.Column="0"/>
        <ContentControl x:Name="ProjectInfo" Grid.Column="1"/>-->
        <Views:ProjectsView  cal:View.Model="{Binding Projects}" 
                             Grid.Column="0"/>
        <Views:ProjectInfoView cal:View.Model="{Binding ProjectInfo}"
                               Grid.Column="1"/>
    </Grid>
</Window>

ShellViewModel:

public interface IShellViewModel :IScreen
{
    ProjectInfoViewModel ProjectInfo { get; set; }
    ProjectsViewModel Project { get; set; }
}

[Export(typeof(IShellViewModel))]
public class ShellViewModel:Conductor<IScreen>.Collection.AllActive,
    IShellViewModel, IPartImportsSatisfiedNotification

{
    [Import]
    public ProjectInfoViewModel ProjectInfo { get; set; }

    [Import]
    public ProjectsViewModel Project { get; set; }

    public void OnImportsSatisfied()
    {
    }
}

If I try compile this code I get error:

Could not locate any instances of contract CaliburnSkelet.ViewModels.IShellViewModel.

StackTrace:

  at CaliburnSkelet.BootStraper.MefBootStrapper.GetInstance(Type serviceType, String key) in E:\C# PROJECTS\CaliburnSkelet\CaliburnSkelet\BootStraper\MefBootStrapper.cs:line 69
   at Caliburn.Micro.Bootstrapper.DisplayRootViewFor(Type viewModelType)
   at Caliburn.Micro.Bootstrapper`1.OnStartup(Object sender, StartupEventArgs e)
   at System.Windows.Application.OnStartup(StartupEventArgs e)
   at System.Windows.Application.<.ctor>b__1(Object unused)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

I tried make a test and change properties shell view model class.

[Export(typeof(IShellViewModel))]
public class ShellViewModel:Conductor<IScreen>.Collection.AllActive,
    IShellViewModel, IPartImportsSatisfiedNotification

{
    //[Import]
    public ProjectInfoViewModel ProjectInfo { get; set; }

    //[Import]
    public ProjectsViewModel Project { get; set; }

    public void OnImportsSatisfied()
    {
        ProjectInfo=new ProjectInfoViewModel();
        Project=new ProjectsViewModel();
    }
}

I don’t import view models classes to shell view model with MEF but I create new instances in method OnImportsSatisfied.

Application run but if I click on button variable MsgBox is null.

Code from ProjectInfoViewModel class:

        [Import]
        internal IMessageBox MsgBox { get; set; }

        public void BtnClick()
        {
//MsgBox is null
            MsgBox.ShowInfo("Btn click",string.Empty);
        }

Where can be problem?

here? Conductor.Collection.AllActive


Solution

  • On your ShellViewModel type, the ProjectInfo and Project properties should be of type IProjectInfoViewModel and IProjectsViewModel, as these are the types you have exported, and you should be working against those interfaces.