2011-08-24 4 views
5

메뉴 명령 등의 일부 사용자 지정 16x16 아이콘을 사용하는 WPF 4.0 응용 프로그램이 있습니다. 나는 (현재로서는) 두 세트의 아이콘, 기본 Vista/7-ish 및 일부 XP-ish 아이콘을 갖고 싶습니다. 내가 원하는 것은 현재 OS가 어떤 아이콘을 사용할 지 결정하도록하는 것입니다.시스템 리소스 별 아이콘 리소스는 어떻게 정의합니까?

지금은 BitmapImage 리소스가 특정 PNG 리소스를 가리키는 테마 리소스 사전 (예 : Aero.NormalColor.xaml 등)에 정의되어 있습니다. 아이콘을 보여주고 싶어 내 응용 프로그램에서 어느 곳

<!-- 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 중 하나에 정적 리소스로 이미지/아이콘의 소스 속성을 설정합니다.

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

아이디어는 WPF가 자동으로 현재 OS 및 테마를 기반으로 테마 사전을로드하기 때문에, BitmapImage 자원의 한 세트를로드 할 것이며 아이콘이 마술 해당하는 사람이 될 것입니다.

그러나 이것은 작동하지 않으며 실행시에 "리소스를 찾을 수 없습니다"예외가 발생합니다. 내 직감은 테마 파일은 이미지가 아닌 사용자 지정 컨트롤 만 검색되기 때문입니다.

블렌드 4에는 아무런 문제가 없지만 에는에 Aero.NormalColor.xaml에 병합 된 특수 DesignTimeResources.xaml 파일이 정의되어 있습니다. VS2010은 초크지만 DesignData 파일 등도 사용하지 못해 놀랄 일이 아닙니다. 현재 별도의 리소스 사전 파일 (MainSkin.xaml)이 Application 리소스에 병합됩니다. 스타일 등을 참조하면 런타임에 잘 작동합니다.

나는 올바른 길을 가고 약간 잘못된 점이 있습니까? 원하는 효과를 얻으려면 완전히 다른 것을해야합니까? 그렇다면 무엇을해야합니까?

답변

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 다음과 같이 테마 내에서 리소스 사전은 자원을 정의합니다. 흥미롭게도 실제로는 사용자 정의만큼 중요하지 않으므로 이러한 리소스를로드해야합니다.

또한 ThemeInfo 당신이 좋아을 제어 무엇이든 XAML에서 이제 다음

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

(과 테마 리소스 사전의 소스 어셈블리에 보이는 있는지 확인 당신의 AssemblyInfo.cs를 업데이트해야합니다

, 아무튼 ' t 당신이 쓸 수 있습니다) CustomControl 수있는 당신은 또한 테마 변경 (아닌 정적 리소스가 AR을 필요로 할 때 응용 프로그램이 동적으로 업데이트 할 수 DynamicResource를 사용하여 자원

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

을 사용하려면 다음 estart).

TypeInTargetAssembly를 숨기려면 ComponentResourceKey의 클리너 구현을 작성하는 것이 좋겠지 만 (적어도 갈 것임)이 작업은 최소한 효과적 일 것입니다.업데이트하려면


, 나는 그냥 현재 실행중인 어셈블리를보고하고 TypeInTargetAssembly에 사용하는 것이 할 수있는 최초의 UIElement에를 찾을 수 ComponentResourceKey에 대한 개선을 구현했습니다. 많은 청소기를 증명해야

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

을 다음과 같이

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; 
     } 
    } 

는 이제 컨트롤이

<!-- 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 : \를보고 있습니다. –

관련 문제