Aplicativo de nível dinâmico recursos não são dinâmicos quando hospedado em ElementHost

StackOverflow https://stackoverflow.com/questions/727141

Pergunta

Eu estou hospedando um UserControl WPF em um recipiente WinForms. Agora, eu quero ser capaz de tema / pele do UserControl. Para fazer isso, eu tenho vários dicionários de recursos que definem as "peles". Quando meu aplicativo inicia-se criar uma "nova System.Windows.Application ()" para que Application.Current existe. Para alterar o tema a pele velha é removida e uma nova pele é incorporado ao dicionário de recursos nível de aplicativo em tempo de execução. No entanto, isso não muda qualquer um dos recursos dyanamically referenciados no UserControl. Tentei fazer isso em um aplicativo WPF em linha reta e funcionou muito bem. Estou faltando alguma coisa, ou não é possível fazer isso em tudo? By the way, se eu adicionar uma pele para os recursos do aplicativo antes do UserControl é inicializado ele vai trabalhar, mas eu não posso mudar a pele depois disso.

Para repo isso da maneira mais básica:

Crie um novo aplicativo WinForms. Adicionar um UserControl WPF para o aplicativo. Este é o suficiente simples:

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

Crie duas ResourceDictionaries, White.xaml e Black.xaml (ou qualquer outro) que têm um SolidColorBrush com a chave ButtonBG com a respectiva cor. No Form1.cs, adicione dois botões e um ElementHost. Defina o filho do ElementHost a uma instância do UserControl que acabamos de criar. Fio até os botões para eventos que trocar a pele:

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

Em Program.cs, garantir que Application.Current existe e definir a pele inicial:

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

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

   ...
}

Agora, quando o botão é clicado Branco Eu esperaria o botão no UserControl para virar branco e quando o botão preto é clicado eu esperaria o botão para ligar preto. Isso não acontece, no entanto.

Alguém sabe por quê? Existe uma solução?

Editar: Idea:. Talvez, se há uma maneira de forçar uma reavaliação da DynamicResources quando o tema muda, que iria trabalhar

Obrigado, Dusty

Foi útil?

Solução

Eu acho que isso pode ser um problema negligenciado no quadro WPF.

De que eu posso dizer a via refletor, parece que quando o dicionário de recursos Application é catastroficamente alterado (uma mudança que provavelmente terá efeitos amplos, como adicionar, remover ou substituir uma pele), não é o código que faz um loop sobre todos do Windows na aplicação e obriga-os a re-avaliar o seu DynamicResources. No entanto, outros elementos que eu consideraria de nível superior em WPF como ElementHosts não recebem o mesmo tratamento. Isso leva ao comportamento que eu estou experimentando.

A minha solução para este problema é ir manualmente através de todos os meus ElementHosts individualmente e adicionar, remover ou substituir o arquivo ResourceDictionary pele. Não é perfeito, mas ele começa o trabalho feito.

Outras dicas

Outra solução seria a criação de uma janela manequim e especificar o conteúdo do ElementHost como conteúdo. Se você olhar para a Aplicação e verificação de como ele lida com mudanças de ResourceDictionaries, você vê que ele só notifica janelas ..

A única coisa que você deve lembrar é nunca mostrar a janela. (-> exceção), e para fechá-la ao descartar o ElementHost, de modo que o desligamento do aplicativo pode corretamente

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top