当菜单打开时,XAML 资源字典中的图像在工具栏上消失



我已经开始将各种常见的Image移动到ResourceDictionary中,并注意到我的WPF应用程序中存在一种奇怪的行为。如果Image用于MenuItemToolBar上的Button,当我打开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中的资源警告,但我无法找到适当的解决方案。行为同时发生StaticResourceDynamicResource。它似乎也不会受到ResourceDictionary是否独立存在或是否与其他合并的影响。也没有其他资源共享该密钥。

编辑:此外,向图像添加PresentationOptions:Freeze="True"并没有改变情况。

Image 类是一个视觉对象,因此它只能出现在可视化树中的一个位置。因此,您不能在多个菜单项/按钮/等之间共享它。

但是,您可以共享 ImageSource(即 Image.Source(值。

在 WPF 中,我相信您可以使用 x:Shared="False" 来强制 WPF 为每个请求创建一个新实例。

不能在多个位置使用 Image 控件,它只能出现在可视化树中的一个位置,因此,如果调用资源,则会从以前的所有者那里抢夺图像。

编辑:x:Shared="False"显然是比我下面的所有建议更好的解决方案,我想知道为什么如此重要的属性没有出现在智能感知中 -_-


这种行为有点痛苦,我通常用于预定义图像源的IconStyleBitmapImages,但为可能需要的每个MenuItem创建新图像。

您还可以为图标创建数据模板:

资源:

    <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......

为了解决这个问题,你可以写一个标记扩展,这个非常简单,只复制SourceStyle属性的值,你也可以使用反射或其他方式创建一个完整的副本:

[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>

相关内容

  • 没有找到相关文章

最新更新