0

I'm familiar with using MEF in .NET Framework 4.6.* but not in .NET Core. I'm messing about with the Hamburger template from Template 10 to see if it is suitable for my needs but I haven't been able to figure out how to compose my view models using MEF.

My question is how can I navigate to a view using the navigation service in such a way that its view model will be injected by MEF?

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • Keep in mind that T10 is more of a page first framework, where as something like Caliburn.Micro is more fitting for MEF (which is a first class inclusion in that framework), since it is a ViewModel first framework. In answer to the question pretty damn hard. Since the VMs in T10 are usually bound to the Page at design time. – mvermef Jan 20 '17 at 05:26
  • Thanks. Will check out Caliburn.Micro to see if it is more suitable. –  Jan 23 '17 at 08:16

2 Answers2

0

I have one way of getting this working but it seems a bit code smelly so better answers are welcomed. I created a static class holding an instance of the CompositionHost. It has a method for resolving imports. The view's code behind calls the static class to create its view model.

public static class Container
{
    public static CompositionHost Host { get; set; }

    public static T Get<T>()
    {
        T obj = Host.GetExport<T>();
        Host.SatisfyImports(obj);
        return obj;
    }
}

In the App class:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
    {
        var config = new ContainerConfiguration();
        Container.Host = config.WithAssembly(GetType().GetTypeInfo().Assembly).CreateContainer();

        await NavigationService.NavigateAsync(typeof(Views.MainPage));
    }

In the view's code behind:

public sealed partial class MainPage : Page
{
    private MainPageViewModel ViewModel { get; }

    public MainPage()
    {
        InitializeComponent();
        NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
        ViewModel = Container.Get<MainPageViewModel>();
        DataContext = ViewModel;
    }
}
  • keep in mind that reflection might throw a curve in uwp (not exactly .net core, but close, only other thing I remember with MEF at least the version in 4.6 didn't handle open generics MEFContrib I think had some solutions for this). – mvermef Jan 21 '17 at 07:23
  • Thanks. Do you happen to know a way of getting the assembly without reflection? –  Jan 23 '17 at 08:32
  • That is the design of MEF. Can't remove the basic blocks out. – mvermef Jan 23 '17 at 18:21
0

My bad, I hadn't spotted this:

How do I use a Unity IoC container with Template10?

In the end, I went for a solution like this:

public interface IView
{
    ViewModelBase ViewModel { get; }
}

[Export]
public sealed partial class MainPage : Page, IView
{
    public ViewModelBase ViewModel
    {
        get
        {
            return VM as ViewModelBase;
        }
    }

    [Import]
    public MainPageViewModel VM { get; set; }

    public MainPage()
    {
        InitializeComponent();
        NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
    }
}

And in the App.xaml.cs:

public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
    {
        var config = new ContainerConfiguration();
        _container = config.WithAssembly(GetType().GetTypeInfo().Assembly).CreateContainer();
        await NavigationService.NavigateAsync(typeof(Views.MainPage));
    }       

    public override INavigable ResolveForPage(Page page, NavigationService navigationService)
    {
        _container.SatisfyImports(page);
        return (page as IView)?.ViewModel;
    }