5 votes

Les commandes routées WPF résolvent-elles un problème ou l'aggravent-elles ?

D'après ce que j'ai compris, l'objectif du modèle Command est d'aider à séparer l'interaction avec l'interface utilisateur de la logique de l'application. Avec des commandes correctement implémentées, un clic sur l'élément de menu "Imprimer" pourrait entraîner une chaîne d'interaction comme celle-ci :

(button) ---click executes command----> (command) ---calls Print() in app logic ---> (logic)

Cela vous encourage à séparer l'interface utilisateur de la logique de l'application.

J'ai regardé les commandes WPF, et pour la plupart, je vois comment ils ont implémenté ce modèle. Cependant, j'ai l'impression que dans une certaine mesure, ils ont compliqué le modèle Command et a réussi à l'implémenter de telle sorte que vous êtes découragé de séparer l'interface utilisateur de la logique de l'application.

Prenons par exemple cette simple fenêtre WPF qui comporte un bouton permettant de coller du texte dans la zone de texte :

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Paste"
                        Executed="CommandBinding_Executed"/>
    </Window.CommandBindings>
    <StackPanel>
        <TextBox x:Name="txtData" />
        <Button Command="Paste" Content="Paste" />
    </StackPanel>
</Window>

Voici le code-behind :

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ApplicationCommands.Paste.Execute(null, txtData);
        }
    }
} 

Qu'ai-je retiré de cette commande ? Il me semble que j'aurais pu tout aussi bien intégrer le code du gestionnaire d'événements de liaison de la commande dans le gestionnaire d'événements du bouton Click événement. Bien sûr, je peux maintenant associer plusieurs éléments d'interface utilisateur à la commande Coller et je ne dois utiliser qu'un seul gestionnaire d'événement, mais que se passe-t-il si je veux coller dans plusieurs zones de texte différentes ? Je devrais rendre la logique du gestionnaire d'événements plus compliquée ou écrire plus de gestionnaires d'événements. Donc maintenant, j'ai l'impression d'avoir ceci :

(button) ---executes Routed Command---> (Window) ---executes command binding----(command binding)
(logic) <---calls application logic--- (event handler) <-----raises event --------------|

Qu'est-ce que je rate ici ? Ça ressemble à une couche supplémentaire d'indirection pour moi.

3voto

Kent Boogaart Points 97432

Vous confondez peut-être les concepts.

El ICommand L'interface prend en charge le modèle de commande. Cela vous permet d'abstraire les actions de l'utilisateur dans une classe réutilisable.

Les commandes routées sont une mise en œuvre particulière de ICommand qui recherchent des gestionnaires dans l'arbre visuel. Ils sont particulièrement utiles pour les commandes qui peuvent être mises en œuvre par de nombreux contrôles différents, et vous voulez que le contrôle actuel les gère. Pensez au copier/coller. Il pourrait y avoir tout un tas de contrôles qui pourraient la gérer, mais en utilisant la commande routée, le système de commande routée trouvera automatiquement le contrôle correct pour gérer la commande en fonction du focus.

2voto

Bubblewrap Points 3880

En plus des éléments déjà mentionnés, ce que vous avez oublié dans votre exemple spécifique de collage, ce sont les propriétés CommandTarget et CommandParameter. Pour Coller, vous pouvez spécifier une TextBox en la définissant comme CommandTarget.

Ces propriétés sont absolument essentielles lorsque l'on veut utiliser la même RoutedCommand à partir de différents contrôles. Elles vous permettent de donner au gestionnaire Executed certaines informations sur le contexte dans lequel la commande est invoquée.

2voto

Je préférerais utiliser les RoutedCommands et les RoutedUICommands lors de la création de contrôles. Par exemple, TextBox implémente la UndoCommand pour vous et la structure Input est déjà liée à Ctrl + Z . Cependant, lorsque je crée des modèles de vue, je préfère utiliser une ICommand personnalisée avec des implémentations internes de Execute et CanExecute. C'est ce que fournit la DelegateCommand dans Prism. Cela permet au concepteur de vues/xaml de se préoccuper uniquement de la commande et non des gestionnaires Execute/CanExecute à utiliser. Cela permettrait d'obtenir un modèle de vue plus expressif.

ps. Les commandes déléguées ne fonctionnent pas encore (de manière élégante) avec les InputBindings. Est-ce que quelqu'un chez Microsoft peut corriger cela, s'il vous plaît !

0voto

Steven Robbins Points 18791

Elles peuvent être excessives pour certaines choses, mais vous bénéficiez de quelques avantages intéressants comme CanExecute qui peut automatiquement activer/désactiver des boutons/éléments de menu lorsque la commande n'est pas disponible (par exemple, si aucun texte n'est sélectionné, etc.). Vous pouvez également effectuer des commandes dans Blend, sans utiliser de code, ce qui est idéal pour les concepteurs.

0voto

Brent Lamborn Points 481

La seule chose que je n'aime pas dans les RoutedCommands est la façon dont elles sont affectées par le Focus. Si le focus est placé sur un élément particulier de l'arbre visuel, la commande peut ne pas arriver jusqu'à l'endroit où se trouve la liaison de commande.

Quelqu'un a-t-il des conseils/meilleures pratiques pour traiter les problèmes de RoutedCommand/Focus ?

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