I am creating a WPF application using .NET core 3.1 I have developed ASP.Net applications in the past and I was excited to use this in WPF. I did some searching and realized DI in WPF isn't as straightforward as it is in ASP.Net, meaning you have to register Views and ViewModels.
My structure is like this
MainWindow
|---BalanceIntegrationPage
|---BalanceIntegrationViewModel
Everything is handled in XAML with the MainWindow.xaml.cs having only generated code, and the BalanceIntegrationPage.xaml.cs has a single line added to it in the constructor
DataContext = new ScaleIntegrationViewModel();
That could not be handled in the xaml because DI requires parameters in the constructor.
Here is my app.xaml.cs:
protected override async void OnStartup(StartupEventArgs startupEventArgs)
{
base.OnStartup(startupEventArgs);
ServiceCollection services = new ServiceCollection();
services.AddScoped<MainWindow>();
services.AddScoped<ScaleInterfacePage>();
services.AddScoped<ScaleIntegrationViewModel>();
services.AddScoped<IScale>(provider => new Scale("1234"));
ServiceProvider serviceProvider = services.BuildServiceProvider();
MainWindow mainWindow = serviceProvider.GetService<MainWindow>();
mainWindow.Show();
}
My ScaleIntegrationViewModel looks like:
public ScaleIntegrationViewModel(IJMDataIntegration jmContext = null, IBalanceIntegrationContext localContext = null, IScale scale = null)
{
_jmContext = jmContext ?? new JMDataIntegration();
_localContext = localContext ?? new BalanceIntegrationContext();
_scale = scale ?? new Scale("1234");
//JK read from config
_commPort = "1234";
}
I also attempted to use the pattern described here
When I step through the code, my IScale object in the ViewModel constructor is always null.
Any Suggestions??
edit:
Based off a comment, I removed the ViewModel call in the page constructor and instead assigned it on the .xaml This forced me to create a default paramaterless constructor which then breaks DI.
It almost starts to seem like I need to inject the services into the MainWindow ctor and then pass them down to everything I call from there. Makes no sense to me, since at that point, I may as well throw away DI and just new them up when I need them.