I have started to move various common Image
s into a ResourceDictionary
and noticed an odd behavior in my WPF application. If the Image
is used in a MenuItem
and in a Button
on a ToolBar
, when I open the Menu
the image disappears on the Button
.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Image x:Key="NewImage"
Source="/SomeApplication;component/Resources/NewDocumentHS.png"
Stretch="None"/>
<!-- ... -->
Relevant XAML from the Window
:
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_New"
Command="{Binding NewCommand}"
Icon="{DynamicResource NewImage}" />
<!-- ... -->
<ToolBarTray>
<ToolBar>
<Button Command="{Binding NewCommand}"
Content="{DynamicResource NewImage}" />
I assume this is a caveat of resources in a ResourceDictionary
, but I am unable to discover the appropriate fix for this. Behavior occurs with both StaticResource
and DynamicResource
. It also doesn't appear to be affected by if the ResourceDictionary
stands on its own or if it is merged with others. No other resource shares that key either.
Edit: Additionally, adding PresentationOptions:Freeze="True"
to the images did not change the situation.
The Image class is a visual, so it can only appear in the visual tree in one location. Therefore, you cannot share it among multiple MenuItems/Buttons/etc.
You can however share the ImageSource (i.e. Image.Source) value.
In WPF, I believe you can use x:Shared="False" to force WPF to create a new instance for each request though.
You cannot use an Image control in multiple places, it can only be appear in the Visual Tree at one place, so if the call to the resource is made the image is being snatched from the previous owner.
Edit:
x:Shared="False"
Is obviously a better solution than all of my suggestions below, i wonder why such an important property does not show up in the Intellisense -_-This behaviour is a bit of a pain, i normally use to predefine a
IconStyle
and theBitmapImages
for the Source of the images but create new Images for everyMenuItem
where i might need it.You can also create a DataTemplate for your Icon:
Resources:
Usage:
Since templates are created via factories this will work, still significantly inflates the XAML though...
To get around this you could for example write a markup extension, this one is very simple and only copies the values of the
Source
andStyle
properties, you could also use reflection or other means to create a complete copy:Can be used like this: