8

I have an IValueConverter implemented class and I need it to be injected using my DI container (Ninject).

The problem is, in XAML, there's no immediately obvious way to get control over the instantiation of the Converter object.

So my XAML contains a line something like this:

Source="{Binding Path=CurrentMessage, Converter={StaticResource ImagePathConverter}}"

Where, the ImagePathConverter will be created for me.

I suppose I could create a "service locator" static class and call it to resolve my dependency and change the StaticResource to a property "MyServiceLocator.TheImageConverter", but that makes me want to vomit.

I am hoping this question can be answered with a few snippets of code that specifically target the code supplied - and perhaps a supporting link to an example. Not simply a recommendation to take a look somewhere.

Also, very importantly, assume that the XAML does not have a code-behind - and that I cannot use one. I'm creating a skin and do not want a code behind. So I cannot set a class variable in the class constructor and reference it. Maybe that's unreasonable, I'm not sure yet.

PandaWood
  • 8,086
  • 9
  • 49
  • 54
  • I'm interested to know why you need the converter to be resolved with DI..? – NotDan May 23 '09 at 04:36
  • Because the Converter uses (depends) on a formatting class, which has dependencies of it's own and each of those dependencies may have dependencies as well. This is the whole point of DI - to wire up all these dependencies for me. I'm wondering if many people are just using it to new up objects and don't realise the main purpose? – PandaWood May 23 '09 at 10:45
  • If I understand correctly, you do not actually want to inject the Converter itself into another class, but you want to inject dependencies into the converter, right? – Oliver Giesen Feb 18 '22 at 11:00

2 Answers2

9

A common way to handle this is for your converter to also be a MarkupExtension. That is:

public class MyConverter : MarkupExtension, IValueConverter

Your ProvideValue() method can return an instance of your converter, thus allowing you to use it like this:

Source="{Binding CurrentMessage, Converter={local:MyConverter SomeParameterToConverter}}"

This isn't really anything to do with DI, but it does address your requirement to eliminate the code behind. I don't really see the point of having converters registered with your DI container.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 1
    Thanks, it's a fair concern about converters. By not seeing the points of having converters registered with the DI container, I think your assuming that the DI container is just being used to 'new up' objects. The point is that the Converter class in question has other dependencies that can only be resolved by the DI container (eg "configuration" objects registered in singleton scope) – PandaWood May 23 '09 at 10:07
  • I think this is a good answer, when I can fix the error 'Missing XmlNamespace, Assembly, or ClrNamespace in Mapping instruction' I'll come back to it (ie despite adding xmlns:local="clr-namespace:MyNamespace" – PandaWood May 24 '09 at 03:13
  • 1
    Got it! Fixed the error and it works nicely. I still needed to call my DI in a service locator fashion in the ProvideValue method, but I don't think there's any way around that) – PandaWood May 24 '09 at 11:19
0

An alternative approach is, to resolve the dependency via MarkupExtension and set it to the converter's property in XAML.

See the following answer for details:

https://stackoverflow.com/a/41611854/2115905

Community
  • 1
  • 1
JanDotNet
  • 3,746
  • 21
  • 30