Question

J'ai une BaseSkin et plusieurs UserSkins dans une dll distincte de mon application WPF.

En fonction de qui utilise l'application, l'enveloppe de base et l'une des enveloppes utilisateur seront fusionnées dans un dictionnaire de ressources et chargées pour l'application.

Ce que je souhaite, c’est la possibilité de spécifier un style dans un fichier BaseSkin, puis d’être capable de le remplacer par un fichier UserSkin spécifique, en modifiant les propriétés dont je dois disposer.

Je sais que je peux accomplir cela en utilisant l'attribut BasedOn comme ceci:

Base:

<Style x:Key="ButtonBg" TargetType="{x:Type Button}">
    <Setter Property="Background" Value="Green"/>
</Style>

utilisateur:

<Style x:Key="CustomButtonBg" TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonBg}">
    <Setter Property="Background" Value="Blue"/>
</Style>

Le problème est que les éléments doivent maintenant avoir un style CustomButtonBg qui peut ne pas être réellement implémenté. Existe-t-il un moyen de faire en sorte que les deux styles utilisent la même clé (ButtonBg) et qu’ils soient fusionnés, l’application recherche d’abord un style nommé ButtonBg dans Utilisateur, et s’il n’en existe pas, utilisez celui de base?

Je pensais que si je pouvais donner le nom de l'assembly dans l'attribut BasedOn pour qu'il pointe vers le fichier BaseSkin, je pourrais éviter les erreurs de nommage lorsque je leur donne la même clé, mais je ne trouve aucun moyen de le faire. Les autres options consistent simplement à forcer une implémentation de chaque style même si rien ne change, ou à vérifier par programme les skins, mais ce sont là les derniers recours.

Était-ce utile?

La solution

Vous pouvez essayer de tirer parti de la logique de recherche de ressources. Lorsque WPF essaie de trouver une ressource à l'aide de la clé, il commence par rechercher le ResourceDictionary de l'élément en cours, puis son parent, puis son parent, etc.

.

Donc, puisque vous avez dit que c'était conditionnel pour l'utilisateur, cela pouvait être fusionné dans le ResourceDictionary au niveau Fenêtre tant que votre base d'origine était à l'application niveau.

Modifier: mes informations sont meilleures. De MSDN sur les dictionnaires fusionnés :

  

Comportement des dictionnaires fusionnés

     

Les ressources d'un dictionnaire fusionné occupent un emplacement dans l'étendue de recherche de ressource située juste après l'étendue du dictionnaire de ressources principal dans lequel elles sont fusionnées. Bien qu'une clé de ressource soit unique dans chaque dictionnaire individuel, une clé peut exister plusieurs fois dans un ensemble de dictionnaires fusionnés. Dans ce cas, la ressource renvoyée proviendra du dernier dictionnaire trouvé de manière séquentielle dans la collection MergedDictionaries. Si la collection MergedDictionaries a été définie dans XAML, l'ordre des dictionnaires fusionnés dans la collection correspond à l'ordre des éléments, comme indiqué dans le balisage. Si une clé est définie dans le dictionnaire principal et également dans un dictionnaire fusionné, la ressource renvoyée proviendra du dictionnaire principal. Ces règles de portée s'appliquent également aux références de ressources statiques et aux références de ressources dynamiques.

Cela signifie que vous pouvez définir votre skin de base dans un ResourceDictionary différent et le fusionner dans un autre ResourceDictionary . L'utilisateur doit avoir l'apparence de ce dernier et il le trouvera en premier, sinon il continuera à explorer le dictionnaire fusionné contenant Base. Chacun de vos dictionnaires utilisateur peut fusionner le dictionnaire de base et vous ne chargez que le dictionnaire utilisateur dans l'application au lieu des deux séparément.

Autres conseils

Vous pouvez simplement nommer votre base BaseButtonBg et, lorsque vous ne fusionnez pas un ResourceDictionary basé sur l'utilisateur, fusionnez-en un générique contenant:

<Style x:Key="ButtonBg" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButtonBg}"/>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top