2009-01-21 5 views
5

Das von mir verstandene Ziel des Befehlsmusters besteht darin, die Benutzeroberflächeninteraktion von der Anwendungslogik zu trennen. Mit richtig implementierten Befehle, ein Klick auf einen „Print“ Menüpunkt könnte in einer Kette von Interaktion wie folgt ergeben:Führt WPF Routed Commands ein Problem oder verschlimmert es?

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

Dies fordert Sie dazu auf die Benutzeroberfläche von der Anwendungslogik zu trennen.

Ich habe WPF-Befehle untersucht, und zum größten Teil sehe ich, wie sie dieses Muster implementiert haben. Allerdings habe ich das Gefühl, bis zu einem gewissen Grad haben sie komplizierte das Command-Muster und verwaltet, um es so zu implementieren, dass Sie von der Trennung der Benutzeroberfläche von Anwendungslogik entmutigen.

Betrachten wir zum Beispiel diese einfache WPF-Fenster, das eine Schaltfläche Text in das Textfeld einzufügen hat:

<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> 

Hier ist der 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); 
     } 
    } 
} 

Was habe ich von der gewinnen Befehl? Es scheint mir, dass ich genauso einfach den Code vom Kommandoverhandlungs-Event-Handler in das Click Ereignis der Schaltfläche gesetzt haben könnte. Sicher, jetzt kann ich mehrere UI-Elemente mit dem Befehl Einfügen verbinden und ich muss nur den einen Event-Handler verwenden, aber was, wenn ich in mehrere verschiedene Textfelder einfügen möchte? Ich müsste die Event-Handler-Logik komplizierter machen oder mehr Event-Handler schreiben. So, jetzt fühle ich mich wie ich habe:

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

Was fehlt mir hier? Es sieht für mich wie eine zusätzliche Ebene der Indirektion aus.

Antwort

2

Zusätzlich zu den bereits erwähnten Dingen haben Sie in Ihrem speziellen Beispiel für das Einfügen die CommandTarget- und CommandParameter-Eigenschaften vergessen. Zum Einfügen können Sie eine TextBox angeben, indem Sie sie als CommandTarget festlegen.

Diese Eigenschaften sind unbedingt erforderlich, wenn Sie denselben RoutedCommand von verschiedenen Steuerelementen verwenden möchten. Sie ermöglichen es Ihnen, dem Executed-Handler Informationen über den Kontext zu geben, in dem der Befehl aufgerufen wird.

+0

Ich las ein Buch Kapitel auf Befehle letzte Nacht und fand diese Informationen, dann fühlte mich prompt wie ein Dope. – OwenP

0

Sie können für einige Dinge Overkill sein, aber Sie haben einige nette Vorteile wie CanExecute, die Schaltflächen/Menüelemente automatisch aktivieren/deaktivieren können, wenn der Befehl nicht verfügbar ist (z. B. kein Text ausgewählt usw.). Sie können auch Befehlssachen in Blend erstellen, ohne Code zu verwenden, was sich hervorragend für Designer eignet.

3

Sie können Konzepte verwirren.

Die Schnittstelle ICommand unterstützt das Befehlsmuster. Damit können Sie Benutzeraktionen in eine wiederverwendbare Klasse abstrahieren.

Geroutete Befehle sind eine spezielle Implementierung von ICommand, die den visuellen Baum nach Handlern durchsucht. Sie sind besonders nützlich für Befehle, die von vielen verschiedenen Steuerelementen implementiert werden können, und Sie möchten, dass das aktuelle Steuerelement sie verarbeitet. Denken Sie, kopieren/einfügen. Es könnte eine ganze Reihe von Steuerelementen geben, die damit umgehen könnten, aber mit Hilfe des gerouteten Befehls findet das geroutete Befehlssystem automatisch das richtige Steuerelement, um den Befehl basierend auf dem Fokus zu verarbeiten.

2

Ich würde die RoutedCommands und RoutedUICommands beim Erstellen von Steuerelementen bevorzugen.Zum Beispiel implementiert TextBox den UndoCommand für Sie und das Eingabefeld ist bereits an Ctrl + Z gebunden. Beim Erstellen von Ansichtsmodellen wird jedoch ein benutzerdefinierter ICommand mit internen Implementierungen von Execute und CanExecute bevorzugt. Der DelegateCommand stellt dies in Prism bereit. Dies ermöglicht dem view/xaml-Designer, sich nur um den Befehl und nicht die richtigen Execute/CanExecute-Handler zu kümmern. Dies würde ein expressiveres Ansichtsmodell ermöglichen.

ps. Delegate Commands funktionieren noch nicht (elegant) mit InputBindings. Kann jemand bei Microsoft das bitte reparieren?