我已经开始将各种常见的Image
移动到ResourceDictionary
,并注意到我的WPF应用程序中存在奇怪的行为。如果在Image
和MenuItem
Button
中使用了ToolBar
,当我打开Menu
时,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"/>
<!-- ... -->
来自Window
的相关XAML:
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_New"
Command="{Binding NewCommand}"
Icon="{DynamicResource NewImage}" />
<!-- ... -->
<ToolBarTray>
<ToolBar>
<Button Command="{Binding NewCommand}"
Content="{DynamicResource NewImage}" />
我认为这是ResourceDictionary
中的资源警告,但我无法找到适当的解决方法。 StaticResource
和DynamicResource
都会出现行为。如果ResourceDictionary
独立或者与其他人合并,它似乎也不会受到影响。没有其他资源可以共享密钥。
修改:此外,向图片添加PresentationOptions:Freeze="True"
并未改变这种情况。
答案 0 :(得分:8)
Image类是可视化的,因此它只能在一个位置的可视树中出现。因此,您无法在多个MenuItems / Buttons / etc.之间共享它。
但是,您可以共享ImageSource(即Image.Source)值。
在WPF中,我相信您可以使用x:Shared =“False”来强制WPF为每个请求创建一个新实例。
答案 1 :(得分:2)
您不能在多个地方使用Image控件,它只能在一个地方出现在Visual Tree中,因此如果调用该资源,则会从前一个所有者中抢夺该图像。
编辑: x:Shared="False"
显然比下面的所有建议更好的解决方案,我想知道为什么这样一个重要的属性不会出现在Intellisense -_-
这种行为有点痛苦,我通常用来为图像的来源预定义IconStyle
和BitmapImages
,但为每个MenuItem
创建新图像需要它。
您还可以为Icon创建一个DataTemplate:
资源:
<Style x:Key="IconImageStyle" TargetType="{x:Type Image}">
<Setter Property="MaxWidth" Value="16"/>
<Setter Property="MaxHeight" Value="16"/>
</Style>
<DataTemplate x:Key="Icon_Close_Template">
<Image Style="{StaticResource IconImageStyle}"
Source="pack://application:,,,/Images/Close.ico"/>
</DataTemplate>
用法:
<Menu>
<MenuItem Header="File">
<MenuItem Header="Close">
<MenuItem.Icon>
<ContentPresenter ContentTemplate="{StaticResource Icon_Close_Template}"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Close">
<MenuItem.Icon>
<ContentPresenter ContentTemplate="{StaticResource Icon_Close_Template}"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
由于模板是通过工厂创建的,这将起作用,但仍然会显着膨胀XAML ......
为了解决这个问题,您可以编写一个标记扩展,这个非常简单,只复制Source
和Style
属性的值,您也可以使用反射或其他方法来创建一个完整的副本:
[MarkupExtensionReturnType(typeof(object))]
public class IconExtension : MarkupExtension
{
private Image icon;
public Image Icon
{
get { return icon; }
set { icon = value; }
}
public IconExtension() { }
public IconExtension(Image icon)
{
Icon = icon;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Icon == null) throw new ArgumentNullException("Icon");
return new Image() { Source = Icon.Source, Style = Icon.Style };
}
}
可以像这样使用:
<Style x:Key="IconImageStyle" TargetType="{x:Type Image}">
<Setter Property="MaxWidth" Value="16"/>
<Setter Property="MaxHeight" Value="16"/>
</Style>
<Image x:Key="Icon_Close" Style="{StaticResource IconImageStyle}" Source="pack://application:,,,/Images/Close.ico"/>
<!-- ... -->
<MenuItem Header="File">
<MenuItem Header="Close" Icon="{m:Icon {StaticResource Icon_Close}}"/>
<MenuItem Header="Close" Icon="{m:Icon {StaticResource Icon_Close}}"/>
</MenuItem>