Switching between ViewModels using IoC in a MVVM WPF application

 Clash Royale CLAN TAG#URR8PPP
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
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 AggregateCatalog``AssemblySource.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.
c# wpf mvvm mef
add a comment |Â
up vote
2
down vote
favorite
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 AggregateCatalog``AssemblySource.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.
c# wpf mvvm mef
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
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 AggregateCatalog``AssemblySource.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.
c# wpf mvvm mef
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 AggregateCatalog``AssemblySource.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.
c# wpf mvvm mef
edited Jun 25 at 4:48


Jamalâ¦
30.1k11114225
30.1k11114225
asked Jun 20 at 18:15
Mycroft Holmes
112
112
add a comment |Â
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196911%2fswitching-between-viewmodels-using-ioc-in-a-mvvm-wpf-application%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password