155 votes

Est-il possible de placer du code derrière un dictionnaire de ressources dans WPF pour le traitement des événements ?

Est-il possible de définir le code derrière un dictionnaire de ressources dans WPF. Par exemple, dans un usercontrol, vous déclarez un bouton en XAML. Le code de gestion des événements pour le clic du bouton est effectué dans le fichier de code derrière le contrôle. Si je devais créer un modèle de données avec un bouton, comment puis-je écrire le code de gestion d'événement pour le clic du bouton dans le dictionnaire de ressources ?

1 votes

La manière correcte de procéder est d'utiliser une commande, qui vous donne également la possibilité d'activer et de désactiver le bouton, bien que vous puissiez le faire de la manière suggérée dans certaines réponses, cela me semble être un piratage.

226voto

ageektrapped Points 7815

Je pense que ce que vous demandez est que vous voulez un fichier code-behind pour un ResourceDictionary. Vous pouvez tout à fait le faire ! En fait, vous le faites de la même manière que pour une fenêtre :

Disons que vous avez un ResourceDictionary appelé MyResourceDictionary. Dans votre fichier MyResourceDictionary.xaml, mettez l'attribut x:Class dans l'élément Root, comme suit :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

Ensuite, créez un fichier de code derrière appelé MyResourceDictionary.xaml.cs avec la déclaration suivante :

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

Et vous avez terminé. Vous pouvez mettre ce que vous voulez dans le code qui se trouve derrière : méthodes, propriétés et gestionnaires d'événements.

\== Mise à jour pour les applications Windows 10 ==

Et juste au cas où vous joueriez avec UWP il y a encore une chose dont il faut être conscient :

<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

8 votes

Comme un addendum à la réponse de ageektrapped : Assurez-vous que vous mettez le nom entièrement qualifié de votre classe codebehind dans l'attribut x:Class. x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictiona‌​ry" Sinon, si vous mettez simplement x:Class="MyResourceDictionary", l'analyseur xaml ne trouvera pas votre classe.

30 votes

Assurez-vous de fournir un constructeur par défaut dans le codebehind de la classe partielle, et assurez-vous qu'il appelle InitializeComponent(). (Dans mon cas, j'utilisais MEF pour exporter le dictionnaire de ressources).

4 votes

Mise à jour de l'extrait de code pour le commentaire approuvé. J'ai senti que c'était nécessaire pour compléter la réponse ; une erreur commune. Je viens de le faire :) Revert si vous n'aimez pas. Merci pour la réponse.

9voto

Phobis Points 3070

Je ne suis pas d'accord avec "ageektrapped"... utiliser la méthode d'une classe partielle n'est pas une bonne pratique. Quel serait alors l'intérêt de séparer le dictionnaire de la page ?

Depuis un code-behind, vous pouvez accéder à un élément x:Name en utilisant :

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

Vous pouvez faire este dans la méthode OnApplyTemplate si vous voulez vous connecter aux contrôles lorsque votre contrôle personnalisé se charge. Pour ce faire, la méthode OnApplyTemplate doit être surchargée. Il s'agit d'une pratique courante qui permet à votre style de rester déconnecté du contrôle. (Le style ne doit pas dépendre du contrôle, mais le contrôle doit dépendre de la présence d'un style).

8 votes

Phobis Je pense que le but de séparer le dictionnaire de la page est la réutilisabilité et la lisibilité de la page principale xaml. La solution ci-dessus a également fonctionné pour moi.

6voto

Pete Maher Points 111

Gishu - bien que cela puisse sembler être une "pratique généralement à ne pas encourager", voici une raison pour laquelle vous pourriez vouloir le faire :

Le comportement standard pour les boîtes de texte lorsqu'elles obtiennent le focus est que le signe d'insertion soit placé à la même position qu'il était lorsque le contrôle a perdu le focus. Si vous préférez que, dans l'ensemble de votre application, le contenu entier d'une zone de texte soit mis en évidence lorsque l'utilisateur appuie sur la touche de tabulation, l'ajout d'un simple gestionnaire dans le dictionnaire de ressources fera l'affaire.

Toute autre raison pour laquelle vous souhaitez que le comportement par défaut de l'interaction avec l'utilisateur soit différent du comportement par défaut semble être un bon candidat pour un code derrière dans un dictionnaire de ressources.

Je suis tout à fait d'accord pour dire que tout ce qui est spécifique à une fonctionnalité d'application ne devrait pas figurer dans un code derrière un dictionnaire de ressources.

0voto

Jason Barkley Points 85

Ajoutons que, de nos jours, avec l'avènement de {x:Bind ...}, si vous voulez placer votre DataTemplate dans un fichier ResourceDictionary partagé, vous êtes obligé de donner à ce fichier un code derrière.

-2voto

Gishu Points 59012

XAML sert à construire des graphes d'objets et ne contient pas de code.
Un modèle de données est utilisé pour indiquer comment un objet utilisateur personnalisé doit être rendu à l'écran... (par exemple, s'il s'agit d'un élément de boîte de liste) ; le comportement ne fait pas partie du domaine d'expertise d'un modèle de données. Redessinez la solution...

0 votes

Conclusion : Est-ce que vous recommanderiez d'utiliser le dic de ressources avec le code derrière ou pas ? Je ne l'ai jamais utilisé, j'ai des doutes.

1 votes

Je ne le ferais pas - pour moi, ce n'est pas normal. Un dictionnaire doit renvoyer des valeurs pour des clés spécifiques. Dans le cas de l'OP, le code d'empaquetage avec le modèle de données Je préfère essayer une approche différente utiliser le modèle de commande par exemple. J'ai besoin de plus de détails sur le problème de l'OP pour recommander une solution différente.

1 votes

Pas du tout d'accord. Avec MVVM, il existe un scénario où avoir du code derrière soi est extrêmement utile : le développement de propriétés attachées. Faites fonctionner le code derrière, puis transférez-le vers une propriété attachée. C'est beaucoup plus rapide que de développer simplement la propriété attachée à partir de zéro, à moins que vous ayez un cerveau de la taille de Manhattan.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X