web-dev-qa-db-fra.com

Problème de référencement d'un dictionnaire de ressources qui contient un dictionnaire fusionné

J'ai une bibliothèque, CommonLibraryWpfThemes, contenant plusieurs fichiers XAML du dictionnaire de ressources. Le fichier My Themes/Generic.xml contient une déclaration ResourceDictionary.MergedDictionaries qui fusionne tous les autres fichiers ensemble.

Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Dans mon projet d'application, j'ai une référence à CommonLibraryWpfThemes et je fais explicitement référence à Generic.xml dans mon fichier App.xaml.

App.xaml - FAILS

<Application
    x:Class="MyApp.App"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary
            Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
    </Application.Resources>
</Application>

Ça ne marche pas. J'obtiens l'erreur suivante lorsque j'exécute mon application:

System.Windows.Markup.XamlParseException occurred
  Message="Cannot find resource named '{_fadedOrangeBrush}'. Resource names are case sensitive.  Error at object 'System.Windows.Setter' in markup file 'CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml' Line 18 Position 13."
  Source="PresentationFramework"
  LineNumber=18
  LinePosition=13

Si je place le contenu de Generic.xaml directement dans App.xaml, tout fonctionne bien:

App.xaml - RÉUSSIS

<Application
    x:Class="MyApp.App"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Peut-être que je m'y trompe. Mon objectif est de faciliter la référence à toutes mes ressources de thème à partir de plusieurs applications sans avoir à répertorier tous les fichiers individuels. Existe-t-il un moyen recommandé de procéder? (Remarque: je n'essaie pas de basculer entre plusieurs thèmes - je n'ai qu'un seul thème.)

En prime, ce serait bien si quelqu'un pouvait me dire comment référencer des ressources dans une bibliothèque externe sans casser le concepteur dans Visual Studio.

Merci.

MODIFIER:

J'ai essayé d'encapsuler le ResourceDictionary dans un élément ResourceDictionary.MergedDictionary, mais cela n'a pas fonctionné non plus (j'obtiens la même erreur):

<Application
    x:Class="MyApp.App"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary
                    Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
44
devuxer

Répondu à une question similaire ici plus tôt, voir Ajout d'un dictionnaire fusionné à un dictionnaire fusionné question.

Il s'agit d'un bogue d'optimisation, voir style Microsoft Connect/DefaultStyleKey introuvable dans les MergedDictionaries internes :

Lors de la création de chaque objet en XAML, si un style par défaut est présent (c'est-à-dire un style avec une clé de type), ce style doit être appliqué. Comme vous pouvez l'imaginer, il existe plusieurs optimisations de performances pour rendre cette recherche (implicite) aussi légère que possible. L'un d'eux est que nous ne regardons pas dans les dictionnaires de ressources à moins qu'ils ne soient marqués comme "contenant des styles par défaut". Il y a un bogue: si tous vos styles par défaut sont imbriqués dans des dictionnaires fusionnés à trois niveaux de profondeur (ou plus), le dictionnaire supérieur n'est pas signalé, la recherche l'ignore. Le travail consiste à mettre un style par défaut à quelque chose, n'importe quoi, dans le dictionnaire racine.

L'ajout d'un style factice au dictionnaire racine résout ce problème. Exemple

<Application x:Class="MyApp.App"  
             xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"  
             xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml">  
    <Application.Resources> 
        <ResourceDictionary> 
            <ResourceDictionary.MergedDictionaries> 
                <ResourceDictionary 
                    Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" /> 
                </ResourceDictionary.MergedDictionaries> 
            <!-- Dummy Style, anything you won't use goes --> 
            <Style TargetType="{x:Type Rectangle}" /> 
        </ResourceDictionary> 
    </Application.Resources> 
</Application>   
67
Fredrik Hedblad

Vérifiez votre constructeur dans App.xaml.cs appelle InitializeComponent () - c'est ce qui fusionne les dictionnaires de ressources ...

12
Chris

Vous ne devriez pas avoir à faire référence à generic.xaml du tout, il a un support intégré. Cela signifie cependant qu'il fournit un style par défaut, que vous ne définissez pas explicitement. Les styles/modèles définis explicitement doivent être accessibles à partir de dictionnaires de référence référencés explicitement.

(MODIFIER pour plus de clarté)

Une exception à cela est le App.xaml, où les ressources définies deviennent accessibles par l'ensemble de l'application, sans avoir besoin de référencer un dictionnaire de ressources spécifique. La ressource elle-même devrait être accessible par son nom.

La raison pour laquelle cela échoue

<Application.Resources>
    <ResourceDictionary
        Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</Application.Resources>

est, je pense, parce que vous ne l'avez pas enveloppé dans un wrapper MergedDictionary, en l'ajoutant aux dictionnaires fusionnés. L'ajout direct aux ressources ne fonctionne que pour les ressources que vous déclarez localement, par exemple les styles, etc. eux-mêmes.

Cependant, comme je l'ai déjà dit, vous ne devriez pas avoir à fusionner generic.xaml n'importe où, vous devriez peut-être simplement refactoriser les pinceaux et autres ressources utilisées en dehors des styles, et fusionner uniquement ces ressources dans app.xaml.

Notez également que les styles ne doivent pas nécessairement être dans generic.xaml pour avoir le comportement "style par défaut" - si un style avec une clé égale au type de l'élément lui est accessible (globalement ou dans les ressources locales), alors il utilisera le style comme style par défaut. Le generic.xaml n'est qu'une commodité.

Vérifiez cette réponse.

Pour les autres pinceaux personnalisés, etc., vous devez référencer ces ressources de manière explicite.

Vous devez également vérifier le contenu du WindowDictionary.xaml, cette erreur a une certaine odeur.

4
Kenan E. K.

J'obtenais cette erreur dans mes tests unitaires et la réponse de Chris d'en haut m'a donné l'indice dont j'avais besoin. Fondamentalement sur ma première méthode testée, j'ai mis:

        MyApplication.App app = new MyApplication.App();
        app.InitializeComponent();

Et soudain, il pourrait trouver mon modèle pour mes pages. Remarque: cela signifie que vous devez vérifier si une instance de votre application existe déjà si vous testez également votre App.cs.

0
ouflak