Y a-t-il un moyen d'utiliser StaticResource dans une bibliothèque de contrôle WPF et d'être capable de la visualiser au moment de la conception?

j'ai une bibliothèque de contrôle WPF qui est ajoutée à une application Windows forms. Nous voulons que les commandes soient localisables, mais je ne suis pas sûr de savoir comment le faire complètement sans dupliquer le code. C'est ce que je fais maintenant .

fondamentalement, dans l'application Windows forms, avant que l'application principale ne démarre, j'instancie une application.xaml qui vivent dans les formes de l'app (contenant mes liens vers mes ressources qui vivent également dans les formulaires app). Cela fonctionne parfaitement pour l'exécution.

cependant, mon utilisateur contrôle tous ont Content="{StaticResource SomeVariableName}" , qui finissent par être blanc. Je peux arranger ça en ayant une application.XAML et les dictionnaires de ressources appropriés dans ma bibliothèque de contrôle qui correspondent à ceux de mon application windows forms. Cependant, c'est le code dupliqué.

Choses que j'ai déjà essayé en vain:

  • Instancier l'Application.xaml qui vit dans l'utilisateur contrôler la bibliothèque à partir de l'application mes formulaires. Cela ne fonctionne pas parce que L'URIs de mes ressources est à la recherche d'une ressource intégrée, pas mon dictionnaire de ressources locales (je pourrais alors simplement copier les fichiers de ressources du contrôle à un endroit approprié dans mon application de formulaires sur Construire). Puis-je utiliser Déferrablecontent ici? Il n'y a pas beaucoup en ligne aussi loin que je pourrais trouver sur cet attribut et comment il devrait être utilisé, cependant.
  • je voudrais utilisez les compilations post pour les applications et les dictionnaires, cependant, L'application est une référence statique à une application compilée.xaml pour autant que je peux dire. Alors, App.xaml doit vivre dans la forme au moins
    • j'ai essayé d'avoir une application dupliquée.xaml avec un post construire déplacer la débrouillardise.XAML. J'ai pensé que c'était une application dupliquée.xaml est ok puisque c'est la force motrice et vous pourriez ne pas vouloir compter sur un de la commande de toute façon (qui tourne en arrière et vous fait se demander si ensuite, vous devez avoir l'Application.xaml dans le contrôle? Sauf si vous voulez autoriser un défaut qui utilise des ressources intégrées....) Qui a également échoué en disant qu'il ne pouvait pas trouver la ressource, même si elle a été placée là où L'URI aurait dû pointer. Le code décomposé indique Uri resourceLocater = new Uri("/WindowsFormsApplication3;component/app.xaml", UriKind.Relative);

alors, y a-t-il un moyen de permettre à cela de fonctionner et d'avoir une vue du temps de conception du composant par défaut et d'éviter la duplication? Ou, est la duplication est OK dans ce cas? Si le sous-article de ma 2e balle semble correct (duplicated App.xaml avec build copied resourcedictionaries), Comment puis-je le faire ne pas chercher un élément de niveau component, mais plutôt un fichier de niveau un?

dernière question (et je peux la poster séparément si nécessaire) à laquelle je viens de prêter attention. Mon Application.xaml est construit dans le code, donc cela ne me permet pas de créer de nouvelles ressources médicales à la volée de toute façon. Est-il possible de faire cela?

option Finale...peut-être le meilleur? - je prévois d'utiliser le code D'Andre van Heerwaarde de toute façon , donc devrais-je juste vérifier l'existence d'un fichier et l'ajouter comme une ressource fusionnée à la volée? En gros, avoir une Application.xaml dans le contrôle de mon utilisateur qui est relié à une débrouillardise intégrée par défaut. Et puis, le code cherche les ressources localisées appropriées à la volée, qui peuvent être des trajectoires de fichier relatives? Le seul inconvénient que je vois ici, c'est que le défaut ne peut pas être changée à la volée...ce que je pourrais probablement même avoir ce regard dans un endroit précis (en utilisant une sorte de convention) et avoir préféré à l'un intégré?

Oh, et ma raison pour ne pas vouloir de ressources intégrées est que les utilisateurs finaux puissent ajouter / modifier de nouvelles ressources localisées après que la construction soit déployée.

je peux ajouter du code si cela peut vous aider à mieux visualiser cela, faites-le moi savoir.

mise à JOUR

j'ai maintenant un autre problème avec le style et pas seulement la localisation.

Voici un exemple de l'un des boutons internes sur l'un des contrôles:

<Button Style="{StaticResource GrayButton}"

quelques autres choses que j'ai essayé / pensé:

  • Je ne peux pas créer une application.xaml (qui ne serait jamais utilisé) avec la débrouillardise mis en place comme Applicationdéfinitions ne sont pas autorisés dans les projets de bibliothèque. Je pourrais intégrer ceci dans les ressources du contrôle, mais alors cela aurait toujours la priorité sur n'importe quelles ressources au niveau de l'application et je perds la personnalisabilité.

voici un cas de connexion qui ressemble en fait à ce que je cherche, mais il ne fournit pas de véritable solution à ce

la solution (au-delà du sommet..ce qui ne fonctionne pas) que je pense, c'est peut-être (et encore try) semble également beaucoup de travail pour quelque chose que je pense devrait être simple. Mais, je pourrais être capable de créer des propriétés de dépendance dans le contrôle que je peux lier et ensuite permettre à ceux-ci d'être supplantés par le projet qui utilisera le contrôle. Comme je l'ai dit, cela semble être beaucoup de travail pour une demande assez simple :). Serait-ce le même travail? Et, plus important encore, est-il une meilleure solution, plus simple, que je suis absent?

22
demandé sur Community 2012-04-06 08:26:24

3 réponses

j'ai rencontré ce problème une fois, et je l'ai résolu en laissant tomber le tout" les ressources sont des objets indexés par clé dans les dictionnaires canoniques " chose.

je veux dire, le simple fait de définir une ressource dans un projet et de la référencer dans un autre par sa" clé " devrait donner la chair de poule à toute personne saine d'esprit. Je voulais fort références.

ma solution à ce problème a été de créer un outil personnalisé qui convertit mes fichiers XAML de ressource en classes statiques avec une propriété pour chaque ressource:

Donc Mes Ressources.xaml:

<ResourceDictionary>
  <SolidColorBrush x:Key="LightBrush" ... />
  <SolidColorBrush x:Key="DarkBrush" ... />
</ResourceDictionary>

Devient MyResources.XAML.cs

public static class MyResources {

  static MyResources() {
    // load the xaml file and assign values to static properties
  }

  public static SolidColorBrush LightBrush { get; set; }
  public static SolidColorBrush DarkBrush { get; set; }

}

pour référencer une ressource, vous pouvez utiliser le x:Static au lieu de StaticResource :

<Border 
   Fill="{x:Static MyResources.LightBrush}"
   BorderBrush="{x:Static MyResources.DarkBrush}"
   ... />

Maintenant vous avez des références solides, autocompletion et compile vérification de temps des ressources.

12
répondu Nicolas Repiquet 2012-04-26 13:16:57

moi aussi j'ai eu un problème avec les thèmes de style et les ressources statiques disponibles. Donc, j'ai créé une bibliothèque autonome qui n'avait essentiellement rien d'autre que les thèmes à utiliser tout imbriqué comme vos ressources fusionnées de votre question liée précédente.

ensuite, sous la forme Windows (.xaml), je viens de mettre une référence à cette bibliothèque, quelque chose comme

<Window x:Class="MyAppNamespace.MyView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ... />

  <Window.Resources>
    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <!-- Common base theme -->
        <ResourceDictionary   Source="pack://application:,,,/MyLibrary;component/Themes/MyMainThemeWrapper.xaml" />
        </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
  </Window.Resources>

  <Rest of XAML for the WPF window>

</Window>

la "composante" semble renvoyer à la racine du projet "MyLibrary" donné. Dans le réel projet, j'ai créé un sous-dossier appelé "Thèmes", d'où la source comprend... composante/Themes/...

Le " MyMainThemeWrapper.xaml " ressemble beaucoup à vos dictionnaires de ressources fusionnés imbriqués, et il voit tout parfaitement d'autres bibliothèques.

0
répondu DRapp 2012-04-20 15:58:59

voici ma partielle solution à votre problème. Je n'ai pas essayé de gérer les ressources libres, mais j'ai du succès avec le partage des ressources entre WinForms et WPF.

  • créez une bibliothèque de classe pour contenir vos ressources .Fichiers ResX (Ex: Resources.resx, ressources.fr.resx, etc)
  • Créez vos contrôles WPF dans une bibliothèque de contrôle utilisateur WPF
  • créer votre hôte WinForms
  • référez les ressources de votre bibliothèque de ressources de WPF en utilisant l'Infrastructure .Localisation.Wpf extension de balisage et chef de la culture, par exemple,

    <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
    
  • mettez le contenu de vos contrôles d'utilisateur WPF dans un ou plusieurs dictionnaires de ressources en tant que Modèles de contrôle, e, g

    <ControlTemplate x:Key="TestTemplate">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
    
            <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>
        </Grid>
    </ControlTemplate>
    
  • utilisez le modèle de ressource dans vos contrôles d'utilisateur

    <UserControl x:Class="WpfControls.UserControl1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300" >
        <UserControl.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="ResourceDictionary.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </UserControl.Resources>
        <ContentControl Template="{StaticResource TestTemplate}" />
    </UserControl>
    
  • ajouter quelques lignes de code pour faire fonctionner les choses

    public partial class UserControl1 : UserControl
    {
        // we require a reference to the resource library to ensure it's loaded into memory
        private Class1 _class1 = new Class1();
    
        public UserControl1()
        {
            // Use the CultureManager to switch to the current culture
            CultureManager.UICulture = Thread.CurrentThread.CurrentCulture;
    
            InitializeComponent();
        }
    }
    

Voici une simple demo app appelé WindowsFormsHost.7z

0
répondu Phil 2012-04-25 20:11:49