Dynamique des ressources au niveau de l'application ne sont pas dynamiques lorsque hébergé dans ElementHost

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

Question

Je l'hébergement d'un UserControl WPF dans un récipient WinForms. Maintenant, je veux être en mesure de thème / peau UserControl. Pour ce faire, j'ai plusieurs dictionnaires de ressources qui définissent les « peaux ». Quand mon application démarre je crée une « nouvelle System.Windows.Application () » de sorte que existe Application.Current. Pour changer le thème de la vieille peau est enlevée et une nouvelle peau est fusionné dans le dictionnaire de niveau d'application des ressources lors de l'exécution. Cependant, cela ne change pas les ressources référencées dyanamically dans le UserControl. J'ai essayé dans une application WPF droit et cela a fonctionné très bien. Est-ce que je manque quelque chose, ou est-il pas possible de le faire du tout? Soit dit en passant, si j'ajoute une peau dans les ressources d'application avant l'UserControl est initialisé il fonctionne, mais je ne peux pas changer la peau après.

Repo cela de la manière la plus fondamentale:

Créer une nouvelle application WinForms. Ajouter un WPF UserControl à l'application. Ceci est assez simple:

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

Créer deux ResourceDictionaries, White.xaml et Black.xaml (ou autre) qui ont un SolidColorBrush avec la ButtonBG clé avec la couleur respective. Dans Form1.cs, ajoutez deux boutons et un ElementHost. Réglez l'enfant du ElementHost à une instance du UserControl que nous venons de créer. Câbler les boutons pour les événements qui échangent la peau:

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

Dans Program.cs, assurez-vous que Application.Current existe et définir la peau initiale:

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

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

   ...
}

, lorsque le bouton blanc est cliqué j'attendre le bouton dans le UserControl à blanchir et lorsque le bouton noir est cliqué j'attendre sur le bouton pour noircissent. Cela ne se produit pas, cependant.

Quelqu'un sait pourquoi? Y at-il une solution?

Modifier Idée:. Peut-être, s'il y a un moyen de forcer la réévaluation des DynamicResources lorsque les changements de thème, qui fonctionnerait

Merci, Dusty

Était-ce utile?

La solution

Je pense que cela peut être un problème négligé dans le cadre WPF.

D'après ce que je peux dire par l'intermédiaire de réflecteur, il semble que lorsque le dictionnaire des ressources Application est modifiée catastrophiquement (un changement qui probablement large allant des effets tels que l'ajout, la suppression ou le remplacement d'une peau), il y a un code qui passe en boucle sur toutes les du Windows dans l'application et les oblige à réévaluer leur DynamicResources. Cependant, d'autres éléments que je considère haut niveau dans WPF comme ElementHosts ne reçoivent pas le même traitement. Cela conduit au comportement que je fais l'expérience.

Ma solution à ce problème est d'aller manuellement à travers toutes mes ElementHosts individuellement et ajouter, supprimer ou remplacer le fichier ResourceDictionary de la peau. Ce n'est pas parfait, mais il fait le travail.

Autres conseils

Une autre solution serait de créer une fenêtre factice et préciser le contenu du ElementHost comme contenu. Si vous regardez dans l'application et de vérifier la façon dont il gère les changements de resourcedictionaries, vous voyez qu'il informe que les fenêtres ..

La seule chose que vous devez rappeler est de ne jamais afficher la fenêtre (-> exception), et il fermer lors de l'élimination du ElementHost, de sorte que l'arrêt de l'application peut correctement

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top