2008-08-12 9 views
34

J'ai effectué une programmation WPF et une chose que je n'ai jamais eue était le modèle de commande. Chaque exemple semble être intégré, éditer, couper, coller. Quelqu'un at-il un exemple ou une suggestion de meilleure pratique pour les commandes personnalisées?Exemple de modèle de commande WPF personnalisé

Répondre

38

Ah ah! Une question à laquelle je peux répondre! Tout d'abord, je dois mentionner que j'ai personnellement trouvé plus facile de définir et de connecter des commandes en code plutôt qu'en XAML. Cela me permet de brancher les gestionnaires pour les commandes un peu plus flexiblement qu'une approche XAML.

Vous devriez déterminer quelles commandes vous voulez avoir et à quoi elles se rapportent. Dans ma demande, j'ai actuellement une classe pour définir importantes commandes d'application comme ceci:

public static class CommandBank 
{ 
    /// Command definition for Closing a window 
    public static RoutedUICommand CloseWindow { get; private set; } 

    /// Static private constructor, sets up all application wide commands. 
    static CommandBank() 
    { 
    CloseWindow = new RoutedUICommand(); 
    CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt)); 
    // ... 
    } 

maintenant, parce que je voulais garder le code tous ensemble, en utilisant un code unique approche de commandes me permet de mettre les méthodes suivantes la classe ci-dessus:

/// Closes the window provided as a parameter 
public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e) 
{ 
    ((Window)e.Parameter).Close(); 
} 

/// Allows a Command to execute if the CommandParameter is not a null value 
public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e) 
{ 
    e.CanExecute = e.Parameter != null; 
    e.Handled = true; 
} 

la deuxième méthode, il peut même être partagé avec d'autres commandes sans avoir à me répéter dans tous les sens. Une fois que vous avez défini les commandes comme ceci, vous pouvez les ajouter à n'importe quelle partie de l'interface utilisateur. Dans la suite, une fois que la fenêtre est chargée, j'ajoute des liaisons de commandes à la fois à Window et MenuItem, puis j'ajoute une liaison d'entrée à la fenêtre en utilisant une boucle pour faire cela pour toutes les liaisons de commandes. Le paramètre qui est passé est la fenêtre elle-même, donc le code ci-dessus sait quelle fenêtre essayer et fermer.

public partial class SimpleWindow : Window 
{ 
    private void WindowLoaded(object sender, RoutedEventArgs e) 
    { 
    // ... 
    this.CommandBindings.Add(
     new CommandBinding(
     CommandBank.CloseWindow, 
     CommandBank.CloseWindowExecute, 
     CommandBank.CanExecuteIfParameterIsNotNull)); 

    foreach (CommandBinding binding in this.CommandBindings) 
    { 
     RoutedCommand command = (RoutedCommand)binding.Command; 
     if (command.InputGestures.Count > 0) 
     { 
     foreach (InputGesture gesture in command.InputGestures) 
     { 
      var iBind = new InputBinding(command, gesture); 
      iBind.CommandParameter = this; 
      this.InputBindings.Add(iBind); 
     } 
     } 
    } 

    // menuItemExit is defined in XAML 
    menuItemExit.Command = CommandBank.CloseWindow; 
    menuItemExit.CommandParameter = this; 
    // ... 
    } 

    // .... 
} 

Je puis aussi avoir plus tard des gestionnaires d'événements pour les événements WindowClosing et WindowClosed, je vous recommande de faire la mise en œuvre effective des commandes en tant que petits et génériques que possible. Comme dans ce cas, je n'ai pas essayé de mettre du code qui essaie d'arrêter la fermeture de la fenêtre s'il y a des données non enregistrées, j'ai gardé ce code fermement dans l'événement WindowClosing. Faites-moi savoir si vous avez des questions de suivi. :)

+2

Votre CanExecuteIfParameterIsNotNull contient un de mes contrariétés pour animaux de compagnie. Pourquoi pas seulement e.CanExecute = e.Parameter! = Null; – Ray

+0

@Ray Ce n'était pas quelque chose que je savais que je pouvais faire! Merci pour l'édition Drew. :) – Nidonocu

3

La chose à propos de XAML est qu'il est bien pour les programmes 'simples', mais malheureusement, il ne fonctionne pas bien lorsque vous voulez faire des choses comme des fonctions de partage. Supposons que vous ayez plusieurs classes et que l'interface utilisateur comporte des commandes qui n'ont jamais été désactivées, vous devez écrire une méthode 'CanAlwaysExecute' pour chaque fenêtre ou UserControl! Ce n'est pas vraiment DRY. Ayant lu plusieurs blogs et en essayant plusieurs choses, j'ai fait le choix de faire XAML purement sur les regards, les styles, l'animation et les déclencheurs. Tout mon accrochage des gestionnaires d'événements et de commande est maintenant dans le code-behind. :)

Un autre truc par la voie est la liaison d'entrée, afin de les attraper, le focus doit être sur l'objet qui contient les liaisons d'entrée. Par exemple, pour avoir un raccourci que vous pouvez utiliser à tout moment (par exemple, F1 pour ouvrir l'aide), cette liaison d'entrée doit être définie sur l'objet Fenêtre, car elle est toujours active lorsque votre application est active. L'utilisation de la méthode de code devrait vous faciliter la tâche, même lorsque vous commencerez à utiliser UserControls qui pourrait vouloir ajouter des liaisons d'entrée à la fenêtre parente.

7
+2

http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx ce lien est mort :( – Drahakar

Questions connexes