Styles au niveau de l'assembly / de niveau racine dans la bibliothèque de classes WPF

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

  •  03-07-2019
  •  | 
  •  

Question

J'ai un assemblage de bibliothèque de classe C # (2008 / .NET 3.5) prenant en charge WPF (basé sur cet article ).
J'ai créé plusieurs fenêtres et tente maintenant de créer un ensemble de style commun pour eux. Toutefois, comme il s'agit d'une bibliothèque de classes (au lieu d'une application WPF), je ne dispose pas d'un fichier app.xaml (et de son application contenue, Application.Resources correspondante) dans lequel stocker ces styles pour un accès global.

Donc: comment créer un ensemble de définitions de style de premier niveau qui seront visibles par tous les fichiers xaml de l'assemblage, étant donné que je n'ai pas app.xaml ( voir ci-dessus) ? Et / ou est-il possible d'ajouter un app.xaml fonctionnel dans une bibliothèque de classes?

Pour info, j’ai essayé de créer un ResourceDictionary dans un fichier ResourceDictionary.xaml et de l’inclure dans chaque fenêtre de "& Window; Ressource". bloc. Cela s'est avéré résoudre le style des boutons, etc ... mais pas pour la fenêtre englobante. Je peux mettre Style = "{StaticResource MyWindowStyle}" dans le bloc d'ouverture de la fenêtre. Il se compile et s'affiche dans la fenêtre de conception de VS, mais lors de l'exécution, j'obtiens une exception d'analyse syntaxique (MyWindowStyle Je ne pense pas que Visual Studio voit que le dictionnaire est inclus après la ligne en question, mais la liste de révocation de certificats fait les choses de manière plus séquentielle et n'a donc pas encore chargé le ResourceDictionary).

Merci pour les idées, mais toujours pas de solution ... apparemment, une bibliothèque de classes NE prend PAS en charge l’utilisation de generic.xaml de manière implicite. J'ai ajouté generic.xaml à mon projet de bibliothèque de classes et ai défini son action de construction sur "Ressource". Il contient:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type Window}" x:Key="MyWindow">
        <Setter Property="Background" Value="Black"/>
    </Style>
</ResourceDictionary>

La fenêtre xaml que je souhaite utiliser avec le thème se présente comme suit:

<Window x:Class="MyAssembly.ConfigureGenericButtons"
    x:ClassModifier="internal"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Style="{StaticResource MyWindow}"
    Title="ConfigureGenericButtons">
...Buttons, etc...
</Window>

Bien que la fenêtre VS Design n’affiche pas la fenêtre dans le style MyWindow (c’est-à-dire un fond noir), elle est bien compilée et démarre. Cependant, lorsque l'application contenant cette bibliothèque de classes effectue un appel provoquant l'affichage de cette fenêtre, je reçois une XamlParseException:

  

Impossible de trouver la ressource nommée '{MyWindow}'.

J'ai aussi essayé de laisser le paramètre Style de côté, pour voir si la fenêtre utiliserait le style par défaut (et j'ai essayé cela tous les deux avec le x: Key de generic.xaml inclus et sans). Aucune erreur, mais tout ce qui est défini dans le fichier generic.xaml ne s'affiche pas non plus.

Est-ce que je fais quelque chose de mal ici, ou toute autre idée sur la manière de permettre l'utilisation de styles personnalisés courants sur une fenêtre (c.-à-d. qu'il n'est pas nécessaire de définir les styles dans le xaml de chaque fenêtre) - avec la mise en garde que cela n'est PAS une application?

Était-ce utile?

La solution

Essayez d'ajouter

Style={DynamicResource MyStyle}

Vous ne pouvez pas utiliser un StaticResource dans ce cas.

Autres conseils

Cela ressemble à un travail de thématisation.

  1. Ajoutez un /themes/generic.xaml ResourceDictionary à votre projet.
  2. Ajoutez les éléments suivants à AssemblyInfo.cs: [assembly: ThemeInfo (ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
  3. ?
  4. Bénéfice!

Toutes les ressources que vous ajoutez à generic seront utilisées par tous les contrôles. Vous pouvez également créer des thèmes spécifiques au profil (Luna, Aero, etc.) en incluant un fichier ResourceDictionary avec le nom de thème correct dans le répertoire themes .

Voici un lien vers plus d’informations: Créer et appliquer des thèmes personnalisés

Si vous n'avez pas d'app.xaml, vous pouvez toujours le charger dans les ressources au niveau de l'application, mais vous devez écrire du code (pas xaml) pour le faire, semblable à ceci ...

void LoadIt()
{
     ResourceDictionary MyResourceDictionary = new ResourceDictionary();
     MyResourceDictionary.Source = new Uri("MyResources.xaml", UriKind.Relative);
     App.Current.Resources.MergedDictionaries.Add(  MyResourceDictionary )
}

consultez ce site pour un exemple: http: // ascendedguard .com / 2007/08 / une-des-fonctionnalités-intéressantes-sur-wpf-est-comment.html

Dr. WPF (ou la personne précédemment connue sous le nom de Dr. WPF) a un grand poster sur le sujet.

Voici un extrait de l'article où ils créent l'objet Application et ajoutent des ressources:

if (Application.Current == null)
{
    // create the Application object
    new Application();

    // merge in your application resources
    Application.Current.Resources.MergedDictionaries.Add(
        Application.LoadComponent(
            new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
            UriKind.Relative)) as ResourceDictionary);
}

Étant donné que mon assemblée est hébergée via interop, je devais ajouter les paramètres suivants: ShutdownMode, puis arrêter à la fin:

new Application() { ShutdownMode = ShutdownMode.OnExplicitShutdown };

Cela a fonctionné comme un charme.

si vous le chargez dans Window.Resource, le dictionnaire n’est disponible que pour les enfants de cette fenêtre. Vous devez l'avoir disponible pour la fenêtre et ses enfants.

Essayez de le charger dans votre fichier app.xaml. Cela devrait en faire une ressource de niveau application, pas une ressource de niveau fenêtre.

Donc, après avoir passé beaucoup de temps, j'ai finalement compris cela. Voici comment:

  1. Dans la bibliothèque de contrôles WPF, ajoutez un nouveau dossier nommé themes .
  2. Dans le dossier themes , ajoutez un dictionnaire de ressources nommé generic.xaml .
  3. Dans generic.xaml , ajoutez votre ressource en utilisant la syntaxe suivante:

    <SolidColorBrush x:Key="{ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}" Color="Blue" />
    
  4. Dans votre contrôle, utilisez la syntaxe suivante pour accéder à cette ressource:

    Background="{StaticResource {ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}}"
    

Choses à noter:

  1. Les étapes 1 et 2 sont normalement effectuées automatiquement par Visual Studio lorsque vous créez une nouvelle bibliothèque de contrôles WPF.
  2. Je ne comprends pas tout à fait l'objectif du premier paramètre de ComponentResourceKey , mais c'est obligatoire. Utilisez le nom du contrôle qui consommera cette ressource.
  3. Le concepteur de Visual Studio n'a pas été en mesure de localiser la ressource dans mon cas. Ce pourrait être un problème de cache, je ne suis pas sûr. Au moment de l'exécution, toutefois, cela fonctionne parfaitement.
  4. Vous pouvez lire plus de détails sur cette syntaxe dans cet article MSDN .

J'espère que cela vous facilitera la vie.

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