Switching between ViewModels using IoC in a MVVM WPF application
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 ViewModel
s 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 ViewModel
s 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 ViewModel
s 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 ViewModel
s 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