2011-08-24 6 views
5

私は、メニューコマンドなどのようなものでいくつかのカスタム16x16アイコンを利用するWPF 4.0アプリケーションを持っています。私は(今のところ)2セットのアイコン、デフォルトのVista/7-ishのものといくつかのXP-ishのものを持っていたいと思います。私が望むのは、現在のOSにどのアイコンを使うかを決めることです。システムリソース単位でアイコンリソースを定義するにはどうすればよいですか?

今、特定のPNGリソースを指し示すテーマリソース辞書(Aero.NormalColor.xamlなど)でBitmapImageリソースを定義しています。アイコンを表示したい私のアプリでどこでも

<!-- Aero.NormalColor.xaml --> 
<BitmapImage x:Key="IconSave" UriSource="/MyWPFApp;component/Resources/Icons16/Aero/disk.png"/> 

<!-- Luna.NormalColor.xaml --> 
<BitmapImage x:Key="IconSave" UriSource="/MyWPFApp;component/Resources/Icons16/Luna/disk.png"/> 

は、これらのBitmapImagesのいずれかにStaticResourceとして画像/アイコンのソースプロパティを設定します。

<Image Source="{StaticResource IconSave}"/> 

アイデアは、WPFは自動的に現在のOSやテーマに基づいたテーマの辞書をロードするので、BitmapImageのリソースの一組だけがロードされるだろうと、アイコンが魔法のように適切なものになるということです。

これは動作しません。実行時に「リソースが見つかりません」という恐れがあります。私の勘には、テーマファイルだけがカスタムコントロールの検索を受けるからです。Imageはそうではありません。

ブレンド4は問題ありませんが、にはがあり、Aero.NormalColor.xamlにマージされた特別なDesignTimeResources.xamlファイルが定義されています。 VS2010のチョークがありますが、DesignDataファイルなども使用できないため、私は驚くことではありません。私は現在、アプリケーションリソースにマージされた別のリソース辞書ファイル(MainSkin.xaml)も持っています。スタイルなどを参照することは、実行時にうまく動作します。

私は適切なトラックにありますが、ちょっとした問題がありますか?望みの効果を得るためには全く別のことをする必要がありますか?あれば何ですか?

答えて

5

私は、これがComponentResourceKeyを使用して動作することがわかりました。メインウィンドウまたはあなたのアセンブリ内のカスタムコントロールのいずれかとすることができる。ここ

<!-- themes\aero.normalcolor.xaml --> 
<BitmapImage x:Key="{ComponentResourceKey ResourceId=IconSave, TypeInTargetAssembly={x:Type local:CustomControl}}" UriSource="/MyWPFApp;component/Resources/Icons16/Aero/disk.png"/> 

<!-- themes\luna.normalcolor.xaml --> 
<BitmapImage x:Key="{ComponentResourceKey ResourceId=IconSave, TypeInTargetAssembly={x:Type local:CustomControl}}" UriSource="/MyWPFApp;component/Resources/Icons16/Luna/disk.png"/> 

local:CustomControl次のようにあなたのテーマの中でリソースディクショナリはリソースを定義します。興味深いことに、カスタムである限り、実際には問題にならないので、これらのリソースをロードするように強制します。

ます。また、「doesnの、(あなたが好きな制御ThemeInfoがあなたのXAMLの中に今次

[assembly:ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)] 

をテーマリソースディクショナリのためのソースアセンブリを見ていることを確認するためにあなたのAssemblyInfo.csを更新する必要がありますトンあなたが書くことができます)CustomControlする必要がありますが、テーマの変更(というよりStaticResourceは、ARが必要になるときにアプリケーションが動的に更新することができますDynamicResourceを使用することにより、リソース

<Image Source="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type local:CustomControl}, ResourceId=IconSave}}"/> 

を利用するには、次のエスタート)。

TypeInTargetAssemblyを隠すために、私はComponentResourceKeyのよりクリーンな実装を書くことができますが、少なくともこれはあなたを動かすはずです。更新するには


は、私は、現在実行中のアセンブリを見て、TypeInTargetAssemblyに使用することができる最初のUIElementを見つけるでしょうComponentResourceKeyの改善を実装しました。

public class ThemeResourceKey : ComponentResourceKey 
    { 
     public ThemeResourceKey(String resourceId) 
     { 
      ResourceId = resourceId; 
      var assembly = Assembly.GetExecutingAssembly(); 

      var types = assembly.GetTypes().Where(t => typeof (UIElement).IsAssignableFrom(t)); 
      var uiElementType = types.FirstOrDefault(); 
      if(uiElementType == default(Type)) 
       throw new ArgumentException("No custom UIElements defined within this XAML"); 

      TypeInTargetAssembly = uiElementType; 
     } 
    } 

ロットクリーナーを証明する必要があります

<Image Source="{DynamicResource {local:ThemeResourceKey IconSave}}"/> 

を次のように今、あなたのコントロールでこの

<!-- themes\aero.normalcolor.xaml --> 
<BitmapImage x:Key="{local:ThemeResourceKey IconSave}" UriSource="/MyWPFApp;component/Resources/Icons16/Aero/disk.png"/> 

と参照これでリソースディクショナリを定義することができます。あなたがそれに問題がある場合、それが助けて私に知らせてくれることを願っています。

+0

'pack:// application:,,,/Resources/Icons16/Aero/disk.png'それ以外の場合、私は' DirectoryNotFoundException'をそのまま使用しました何らかの理由でC:\で探しています。 –

関連する問題