Is Dependency Injection possible with a WPF application?

Scott Weinstein picture Scott Weinstein · Nov 12, 2008 · Viewed 14.8k times · Source

I want to start using dependency injection in my WPF application, largely for better unit testability. My app is mostly constructed along the M-V-VM pattern. I'm looking at Autofac for my IoC container, but I don't think that matters too much for this discussion.

Injecting a service into the start window seems straightforward, as I can create the container and resolve from it in App.xaml.cs.

What I'm struggling with is how I can DI ViewModels and Services into User Controls? The user controls are instantiated via XAML markup, so there's no opportunity to Resolve() them.

The best I can think of is to place the container in a Singleton, and have the user controls resolve their ViewModels from the global container. This feels like a half-way solution, at best, as it still required my components to have a dependency on a ServiceLocator.

Is full IoC possible with WPF?

[edit] - Prism has been suggested, but even evaluating Prism seems like a big investment. I'm hoping for something smaller.

[edit] here's a code fragment where I'm stopped

//setup IoC container (in app.xaml.cs)
var builder = new ContainerBuilder();
builder.Register<NewsSource>().As<INewsSource>();
builder.Register<AViewModel>().FactoryScoped();
var container = builder.Build();

// in user control ctor -
// this doesn't work, where do I get the container from
VM = container.Resolve<AViewModel>();

// in app.xaml.cs
// this compiles, but I can't use this uc, 
//as the one I want in created via xaml in the primary window
SomeUserControl uc = new SomeUserControl();
uc.VM = container.Resolve<AViewModel>();

Answer

Glenn Block picture Glenn Block · Nov 15, 2008

It's actually very easy to do. We have examples of this in Prism as jedidja mentioned. You can either have the ViewModel get injected with the View or the View get injected with the ViewModel. In the Prism StockTraderRI, you will see that we inject the View into the ViewModel. Essentially, what happens is that the View (and View interface) has a Model property. That property is implemented in the code-behind to set the DataContext to the value, for example: this.DataContext = value;. In the constructor of the ViewModel, the View gets injected. It then sets View.Model = this; which will pass itself as the DataContext.

You can also easily do the reverse and have the ViewModel injected into the View. I actually prefer this because it means that the ViewModel no longer has any back reference to the view at all. This means when unit-testing the ViewModel, you don't have a view to even Mock. Additionally, it makes the code cleaner, in that in the constructor of the View, it simply sets the DataContext to the ViewModel that was injected.

I talk a bit more about this in the video recording of the Separated Presentation Patterns talk that Jeremy Miller and I gave at Kaizenconf. The first part of which can be found here https://vimeo.com/2189854.