I am building a WPF Application, which has a single Window, a tabbed interface with multiple view models (2 view models, the first tab is ViewModel1 and the rest will always be ViewModel2) these are loaded by user controls using data triggers.
Finally there are also a other windows such as Dialogs/Settings etc.
Project Structure
My project is split into several layers as described below:
- Core Layer (Base Code Layer/Interfaces very little 3rd party libraries)
- Repo Layer (Repository Layer with EF, basic CRUD functions without business logic)
- Service Layer (Individual service layers which make use of the repos, also contain business logic)
- WPF Layer (Main UI Layer with View Models)
One of the issues I have is using DI within an WPF/MVVM setting, I have seen many resources online and a lot of this is ASP.NET Core DI which is not relevant to what I am focusing on. The issue I find is that in WPF there seems to be a single applications Start-up point (MainWindow) which when using DI everything is injected into the constructor, this is then passed down further to other dialogs/models this seems very cumbersome (or I am doing it wrong). For example I currently have something similar to this in the App code behind using Microsoft DI.
(Dialog is for creating dialogs/opening windows etc, Messaging is for Message Boxes)
services.AddSingleton<IRepo1, Repo1>();
services.AddSingleton<IRepo1Service, Repo1Service>();
services.AddSingleton<IDialog, Dialog>();
services.AddSingleton<IMessaging, Messaging>();
To use these within a viewmodel, they needed to be injected within the MainWindow constructor like so
MainWindow(repo1service, dialog, messaging)
These are then passed down to the viewmodels
MainWindowViewModel(repo1service,dialog,messaging)
This process seems like I am awfully doing a lot of work within the constructors and traversing down from a single application point, also some of these viewmodels may not even use dialogs or messaging, but only the DB context
MainWindowViewModel has the tabbed control, this then calls the corresponding viewmodel when adding another Tab, so for example I will need to do :
Tabs.Add(new ViewModel1(repo1service,dialog,messaging))
When a user clicks new tab.
I have realized I can use DI and add the viewmodel like as a Singleton:
services.AddSingleton<ViewModel1>();
but, if this viewmodel is called only after a button click, I still have the issue of needing to pass parameters down to the constructor.
How can I avoid passing many parameters to viewmodels, how can DI resolve this for me? Could I pass the IServiceCollection to the models and retrieve as needed or is this a bad approach?
I have read up on these resources, but I am still unsure about how I can resolve my issue.