I'm trying to use both MVVM and Dependency Injection pattern in my WPF MDI application. I'm using VM first approach.
Basically, my app starts with the App.xaml.cs class which is supposed to be, if I understood the thing well, my composition root (where all dependencies are resolved). Here's a sample :
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
...
var login = new LoginView();
login.DataContext = new LoginViewModel(Dependency1, Dependency2);
loginView.ShowDialog();
if (loginView.DialogResult.GetValueOrDefault())
{
var app = new MainWindow();
var mainVM = new MainViewModel(Dependency3, Dependency4);
app.DataContext = mainVM;
app.Show();
}
}
}
No problem so far, I can resolve dependencies for both LoginViewModel and MainViewModel whether I use a DI container or Dependency Injection by hand. Now let's dig into MainViewModel.
I was inspired by Rachel Lim's approach and used a SelectedViewModel property to get/set the currently used ViewModel which is bound to its View using DataTemplates. I'll let you look at the link for more details on the process since it is quite unrelated to my issue here. The important thing is that my MainViewModel is in charge of switching ViewModels when needed. But my children ViewModels have dependencies. Here's a simplified sample :
class MainViewModel
{
private ViewModel1 vm1;
private ViewModel2 vm2;
public MainViewModel(Dependency1, Dependency2)
{
...
}
...
// Method used by an ICommand to display the ViewModel1's associated View
private void DisplayView1()
{
vm1 = new ViewModel1(Dependency3, Dependency4, Dependency5);
// Method used by an ICommand to display the ViewModel2's associated View
private void DisplayView2()
{
vm2 = new ViewModel2(Dependency3, Dependency6);
SelectedViewModel = vm2;
}
...
}
As you can see, some dependencies are shared between several children ViewModels and some are not. My problem is, I have trouble injecting those from the composition root. So far, I have found only two solutions :
- Having two composition root (kinda) : resolving LoginViewModel and MainViewModel in App.xaml.cs and children ViewModels in MainViewModel. This implicates, when using an IOC container, referencing the container in both classes.
- Passing children ViewModels as MainViewModel's constructor parameter and treat them like any other dependencies. My problem with this approach is that, if I have, let's say, ten ViewModels, the MainViewModel's constructor will become huge.
I read that one could pass a factory to the MainViewModel and delegate the responsibility to create the children ViewModels to it, but I didn't see any sample using children ViewModels with constructor parameters.
I don't understand how I could use this method without passing all children's dependencies to the MainViewModel's constructor and hence, without making it huge again.
Maybe there's something I don't see, but it seems like a deadend to me.
Please help me getting this right and show me the right direction.
Thanks.