As you already know you cannot do constructor injection with Wpf but you can have property injection defined in the Xaml. What I consider to be a "neat" solution is to use a MarkupExtension
such as this:
public sealed class Resolver : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
var provideValueTarget = (IProvideValueTarget)serviceProvider
.GetService(typeof(IProvideValueTarget));
// Find the type of the property we are resolving
var targetProperty = provideValueTarget.TargetProperty as PropertyInfo;
if (targetProperty == null)
{
throw new InvalidProgramException();
}
// Find the implementation of the type in the container
return BootStrapper.Container.Resolve(targetProperty.PropertyType);
}
}
And with a behaviour such as this:
public sealed class InitialiseWebBrowser : Behavior<MyVM>
{
public IQueryHandler<Query.Html, string> HtmlQueryHandler { private get; set; }
// ...
}
We can configure the property injection in the Xaml like so:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:inf="clr-namespace:abc"
xmlns:behaviours="clr-namespace:def"
x:Class="MyVM">
<i:Interaction.Behaviors>
<behaviours:InitialiseWebBrowser HtmlQueryHandler="{inf:Resolver}"/>
</i:Interaction.Behaviors>
The Resolver
MarkupExtension will:
- analyse the type of the property it is defined against (in the example
HtmlQueryHandler
is an IQueryHandler<Query.Html, string>
)
- resolve the type from whatever underlying Container/Resolver you are using
- inject it into the behaviour.