# Switching between ViewModels using IoC in a MVVM WPF application

I have a project that uses Caliburn.Micro to implement the MVVM pattern. For IoC, I am using MEF. All the ViewModels are marked with attribute [Export(typeof(IScreen))]. IScreen is defined in Caliburn.Micro.

In my BootStrapper file I have set up MEF like so:

private CompositionContainer container;

protected override void Configure()
{

//Set up MEF

container = new CompositionContainer(new AggregateCatalogAssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));

var batch = new CompositionBatch();

batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
container.Compose(batch);

...
}


Now, I show the first ViewModel using:

protected override void OnStartup(object sender, StartupEventArgs e) => DisplayRootViewFor<ViewModels.Main.MainViewModel>();


All that is fine and dandy. Now, the problem starts when I want to switch from one ViewModel to another.

An example of a ViewModel is:

[PartCreationPolicy(CreationPolicy.NonShared), Export(typeof(IScreen))]
sealed class SampleViewModel: ScreenVMwithUoW<IAddItemUoW>
{
[ImportingConstructor]
public SampleViewModel(IAddItemUoW uow, IEventAggregator eventAggregator) : base(uow, eventAggregator)
{

}

...
}


So far so good.

Let's say I want to open SampleViewModel and close my MainViewModel. How do I do it using MEF?

Here is what I am doing now. I am using ExportFactory of MEF. I have a class that holds a collection of ExportFactory, one for each IScreen.

[Export(typeof(IScreenFactory))]
class ScreenFactory : IScreenFactory
{
private Dictionary<Type, ExportFactory<IScreen>> _screenDictionary { get;  set; }
private IEnumerable<ExportFactory<IScreen>> _screenfactoryCollection { get; set; }
private ExportLifetimeContext<IScreen> _currentScreenLifeTimeCtx { get; set; }

[ImportingConstructor]
public ScreenFactory([ImportMany(AllowRecomposition = true)] IEnumerable<ExportFactory<IScreen>> screenList)
{
_screenfactoryCollection = screenList;
_reportfactoryCollection = reportsList;
}

public IScreen GetScreen(Type t)
{
if (_screenDictionary == null)
{
PopulateScreenDictionary(_screenfactoryCollection);
}

_currentScreenLifeTimeCtx = _screenDictionary[t].CreateExport();
return _currentScreenLifeTimeCtx.Value;
}

private void PopulateScreenDictionary(IEnumerable<ExportFactory<IScreen>> screenfactories)
{
_screenDictionary = screenfactories.ToDictionary(c => c.CreateExport().Value.GetType(), c => c);
}

public void DisposeCurrentScreenContext()
{
_currentScreenLifeTimeCtx?.Dispose();
}

public void Dispose()
{
DisposeCurrentScreenContext();
}
}


Whenever I need a new instance of a ViewModel, I just publish a message using the EventAggregator and the MainViewModel does this:

DeactivateItem(ActiveItem, true);
_vmFactory.DisposeCurrentScreenContext();
ActivateItem(_vmFactory.GetScreen(NextViewModelName));


This CANNOT be the normal way to do so. Also, this adds a huge hit in performance, especially the startup time of the application, when the number of ViewModels increase to about 25-30. That is because of how ExportFactory is messily implemented in the ScreenFactory class.

I would also like to avoid the Service Locator Pattern, if possible. I am also open to using a proper IoC Container instead of MEF, but MEF allows me to add ViewModels with very little effort. Just adding the annotation [Export(typeof(IScreen))] does the job.