2009-04-07 8 views
5

WinForms 컨테이너에서 WPF UserControl을 호스팅하고 있습니다. 이제는 테마/스킨에 UserControl을 사용하고 싶습니다. 이를 위해 "스킨"을 정의하는 몇 가지 리소스 사전이 있습니다. 내 응용 프로그램이 시작되면 Application.Current가 존재하도록 "새로운 System.Windows.Application()"을 만듭니다. 테마를 변경하기 위해 오래된 스킨이 제거되고 새로운 스킨이 런타임에 응용 프로그램 수준 리소스 사전에 병합됩니다. 그러나이 UserControl 다이내믹하게 참조 된 리소스를 변경하지 마십시오. 나는 이것을 곧바로 WPF 응용 프로그램에서 시도해 보았지만 제대로 작동했다. 나는 뭔가를 놓치고 있는가, 아니면 이것을 전혀 할 수 없는가? 그건 그렇고, UserControl 초기화되기 전에 응용 프로그램 리소스에 스킨을 추가하면 작동하지만 그 후에 스킨을 변경할 수는 없습니다. ElementHost에서 호스팅 할 때 동적 인 응용 프로그램 수준 리소스가 동적이 아닙니다.

가장 기본적인 방법이 REPO하려면

새로운 윈폼 응용 프로그램을 만듭니다. WPF UserControl을 앱에 추가하십시오. 이것은 간단하다 :

<UserControl ...> 
    <Grid> 
     <Button 
     Background="{DynamicResource ButtonBG}"/> 
    </Grid> 
</UserControl> 

는 각각의 색으로 키 ButtonBG와 SolidColorBrush를 두 ResourceDictionaries, White.xaml 및 Black.xaml (또는 무엇이든)를 만듭니다. Form1.cs에 Button과 ElementHost 두 개를 추가합니다. ElementHost의 자식을 방금 만든 UserControl의 인스턴스로 설정합니다. 화이트 버튼을 클릭하면 이제

[STAThread] 
static void Main() 
{ 
    new System.Windows.Application(); 

    Application.Current.Resources.MergedDictionaries[0] = 
     (ResourceDictionary)Application.LoadComponent(
     new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative))); 

    ... 
} 

: 와이어 최대 피부 교환 이벤트 버튼 : Program.cs에서

private void White_Click(object sender, EventArgs e) 
{ 
    Application.Current.Resources.MergedDictionaries[0] = 
     (ResourceDictionary)Application.LoadComponent(
     new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative))); 
} 

private void Black_Click(object sender, EventArgs e) 
{ 
    Application.Current.Resources.MergedDictionaries[0] = 
     (ResourceDictionary)Application.LoadComponent(
     new Uri(@"\WpfThemes;component\Black.xaml", UriKind.Relative))); 
} 

을 초기 피부를 Application.Current가 있는지 확인 및 설정 UserControl의 버튼이 흰색으로 바뀌고 Black 버튼을 클릭하면 버튼이 검은 색이 될 것으로 예상됩니다. 그러나 이것은 발생하지 않습니다.

이유를 아는 사람이 있습니까? 해결책이 있습니까?

아이디어 : 아이디어 : 아마도 테마가 변경 될 때 DynamicResources를 다시 평가할 수있는 방법이 있다면 작동 할 수 있습니다.

덕분에, 먼지

답변

6

나는 이것이 WPF 프레임 워크에서 간과 문제가 될 수있다 생각합니다.

Reflector를 통해 알 수있는 바로는 Application 리소스 사전이 대대적으로 변경되면 (스킨 추가, 제거 또는 대체와 같은 다양한 영향을 줄 수있는 변경), 반복되는 코드가 있음을 알 수 있습니다 응용 프로그램에있는 Windows 모두를 검사하여 다시 DynamicResources을 평가하도록합니다. 그러나 최상위 수준 인을 WPF에서 ElementHost과 같은 것으로 간주하는 다른 요소는 동일한 처리를 얻지 못합니다. 이것은 내가 겪고있는 행동으로 이어집니다.

이 문제의 임시 해결책은 수동으로 모든 ElementHost을 수동으로 검사하고 ResourceDictionary 스킨을 추가, 제거 또는 바꾸는 것입니다. 완벽하지는 않지만 일을 끝내게됩니다.

+0

안녕하세요 dustyburwell, 샘플 코드를 제공해 주시겠습니까? – user1912383

-1

또 다른 해결 방법은 더미 창을 만들고 요소 호스트의 내용을 내용으로 지정하는 것입니다. 응용 프로그램을 살펴보고 자원 기반의 변경 사항을 처리하는 방법을 확인한 경우 Windows에만 알립니다.

당신이 기억해야 할 것은 응용 프로그램을 제대로 종료 할 수 있도록 요소 호스트를 폐기 할 때 창 (-> 예외)을 표시하지 않고 닫는 것입니다.