How can I specify resources in an MVVM view model?
- by gix
Suppose I want to show list of objects where each object should have a name and a suitable image (for example MenuItems with Icons, or buttons with text and image).
All examples and programs exposed the image in the viewmodel as a path to a PNG file and then bound the Source of an Image to that. But what if I want to use vector images (for example as a DrawingImage in a local ResourceDictionary)? Exposing the DrawingImage from the view model seems bad because I would have to store a reference to the application/window/user control/... (and it is advised to not expose such XAML objects from view models).
So a better approach would be to use a string identifier in the view model and then somehow select the appropriate resource. If that identifier is the resource key this snippet looks tempting but does not work:
<Image Source="{StaticResource {Binding Icon}}"/>
I found two workarounds for that though they did not work for me.
The first one was using a normal binding to the icon with a converter that looked up the resource in Application.Current. This does not work if the resource is stored somewhere else I think (and the situation where I initially bumped into this problem had no Application running yet since it was a Window choosing the Application to launch!).
The second workaround was using a markup extension derived from StaticResourceExtension that fetched its ResourceKey from the passed binding:
<Image Source="{local:BindableStaticResource {Binding Icon}"/>
This one looks really neat because it could use local resources, also be used for other things. But when using it I always got an exception ("Resource named {FooIcon} could not be found.", showing the correct XAML file and position of the extension). Even an empty resource extension derived from StaticResourceExtension that just passed the resource key to the base constructor did not work and I cannot explain why. Just using StaticResourceExtension worked just fine.
Any ideas how I could fix the second approach, or even better solutions?
Edit
I noticed that it does work when used directly like this:
<Window>
<Window.Resources>
<DrawingImage x:Key="SomeIcon"/>
</Window.Resources>
<Image Source="{BindableStaticResource {Binding Icon}}"/>
</Window>
but fails for example in a DataTemplate. Though a normal StaticResourceExtension works on both occasions so I am puzzled what is going wrong.