2011-04-08 29 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>