2011-04-08 36 views
9

我已经开始各种常见Image此举为ResourceDictionary,发现在我的WPF应用程序的异常行为。如果Image用于MenuItemButtonToolBar,当我打开Menu时,图像在Button上消失。从Window形象XAML ResourceDictionary中工具栏上消失的时候菜单打开

<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"/> 
    <!-- ... --> 

相关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"的图像没有变化的情况。

+2

这听起来与我在Silverlight 4中使用Path样式的经验非常类似!运行时只渲染应用资源的第一个实例,在那之后,形状(在我的情况下为矢量图标)应该是空的:(我还没有找到任何解决方法... – dain 2011-04-08 15:50:44

回答

7

Image类是一个可视化的,所以它只能出现在一个位置的可视化树中。因此,你不能在多个MenuItems/Buttons/etc之间共享它。

但是,您可以共享的ImageSource(即Image.Source)值。在WPF中,我相信你可以使用x:Shared =“False”来强制WPF为每个请求创建一个新的实例。

+0

现在你提到它的一个'Visual “这种行为似乎完全明显!”x:Shared“位完全不明显,很好,非常感谢。 – user7116 2011-04-08 17:46:34

2

不能使用在多个地方Image控件,它只能在一个地方出现在Visual树,所以如果在调用资源时,图像正在从以前的主人抢走。

编辑:x:Shared="False"明显比所有我下面的建议,更好的解决方案,我不知道为什么这样一个重要的属性不会在智能感知显示-_-


此行为是有点一个痛苦的,我通常使用预先定义一个IconStyleBitmapImages的图像的来源,但创造的每MenuItem在那里我可能需要它的新形象。

您也可以为你的图标来创建一个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虽然...

要解决这个问题你可以为电子商务xample写标记扩展,这一个是非常简单的,只复制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>