I’m quite familiar with ASP.NET Core and the support for dependency injection out of the box. Controllers can require dependencies by adding a parameter in their constructor. How can dependencies be achieved in WPF UserControls? I tried adding a parameter to the constructor, but that didn’t work. I love the IOC concept and would prefer to bring this forward to WPF.
I have recently come across this requirement to my project and I solved it this way.
For Dependency Injection in .NET Core 3.0 for WPF. After you create a WPF Core 3 project in your solution, you need to install/add NuGet packages:
Microsoft.Extensions.DependencyInjection
In my case, I created a class called LogBase that I want to use for logging, so in your App class, add the following (and ya this is just a basic example):
private readonly ServiceProvider _serviceProvider;
public App()
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
_serviceProvider = serviceCollection.BuildServiceProvider();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ILogBase>(new LogBase(new FileInfo($@"C:\temp\log.txt")));
services.AddSingleton<MainWindow>();
}
private void OnStartup(object sender, StartupEventArgs e)
{
var mainWindow = _serviceProvider.GetService<MainWindow>();
mainWindow.Show();
}
In your App.xaml, add Startup="OnStartup" so it looks like this:
<Application x:Class="VaultDataStore.Wpf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VaultDataStore.Wpf"
Startup="OnStartup">
<Application.Resources>
</Application.Resources>
</Application>
So in your MainWindow.xaml.cs, you inject ILogBase in the constructor like this:
private readonly ILogBase _log;
public MainWindow(ILogBase log)
{
_log = log;
...etc.. you can use _log over all in this class
In my LogBase class, I use any logger I like in my way.
I have added all this together in this GitHub repo.
Meanwhile, I have been asked how to use injection inside user control. I come up with this solution if some one get the benefit of it. Check it here.
maytham-ɯɐɥʇʎɐɯ answer to configure Dependency Injection from App class and Startup method is good except I implement IServiceProvider as a property
public IServiceProvider ServiceProvider { get; private set; }
The next step is "how to inject viewmodels" ?
I don't like the viewmodel injection in the window constructor (in code behind) My cleaner solution was to create a view model provider to use in xaml To do this, you can implement it as a MarkupExtension
public class ViewModelProvider : MarkupExtension
{
#region ctor
public ViewModelProvider()
{
}
public ViewModelProvider(Type viewModelType)
{
ViewModelType = viewModelType;
}
#endregion ctor
#region properties
public Type ViewModelType { get; set; }
#endregion properties
#region methods
public override object ProvideValue(IServiceProvider serviceProvider)
{
return ((App)Application.Current).ServiceProvider.GetService(ViewModelType);
}
#endregion methods
}
Then in xaml, you can ask the viewmodel type you want to ViewModelProvider
DataContext="{local:ViewModelProvider local:MainViewModel}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With