Frage

Ich habe ein wenig WPF-Programmierung gemacht und eine Sache, die ich nie verstanden habe, war das Befehlsmuster.Jedes Beispiel scheint für eingebaute Beispiele gedacht zu sein: Bearbeiten, Ausschneiden, Einfügen.Hat jemand ein Beispiel oder einen Vorschlag für Best Practices für benutzerdefinierte Befehle?

War es hilfreich?

Lösung

Ah ha!Eine Frage, die ich beantworten kann!Zunächst sollte ich erwähnen, dass es für mich persönlich einfacher ist, Befehle im Code zu definieren und einzubinden als in XAML.Dadurch kann ich die Handler für die Befehle etwas flexibler einbinden als bei einem reinen XAML-Ansatz.

Sie sollten herausfinden, welche Befehle Sie haben möchten und worauf sie sich beziehen.In meiner Anwendung habe ich derzeit eine Klasse zum Definieren wichtiger Anwendungsbefehle wie folgt:

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));
    // ...
  }

Da ich nun den gesamten Code zusammenhalten wollte, kann ich mit einem Nur-Code-Ansatz für Befehle die folgenden Methoden in die obige Klasse einfügen:

/// 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;
}

Die dortige zweite Methode kann sogar mit anderen Befehlen geteilt werden, ohne dass ich sie überall wiederholen muss.

Sobald Sie die Befehle auf diese Weise definiert haben, können Sie sie zu jedem Teil der Benutzeroberfläche hinzufügen.Im Folgenden füge ich nach dem Laden des Fensters Befehlsbindungen sowohl zum Fenster als auch zum MenuItem hinzu und füge dann mithilfe einer Schleife eine Eingabebindung zum Fenster hinzu, um dies für alle Befehlsbindungen zu tun.Der übergebene Parameter ist das Fenster selbst, sodass der obige Code weiß, welches Fenster er schließen soll.

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;
    // ...
  }

  // ....
}

Ich habe dann später auch Ereignishandler für die Ereignisse WindowClosing und WindowClosed. Ich empfehle Ihnen, die eigentliche Implementierung von Befehlen so klein und allgemein wie möglich zu gestalten.Da ich in diesem Fall nicht versucht habe, Code einzufügen, der versucht, das Schließen des Fensters zu stoppen, wenn nicht gespeicherte Daten vorhanden sind, habe ich diesen Code fest im WindowClosing-Ereignis belassen.

Lassen Sie mich wissen, wenn Sie weitere Fragen haben.:) :)

Andere Tipps

In der Septemberausgabe 2008 des MSDN-Magazins hat Brian Noyes einen hervorragenden Artikel über RoutedCommand/RoutedEvents!!!

Hier ist der Link:http://msdn.microsoft.com/en-us/magazine/cc785480.aspx

Das Besondere an XAML ist, dass es für „einfache“ Programme in Ordnung ist, aber leider nicht gut funktioniert, wenn Sie Dinge wie Freigabefunktionen ausführen möchten.Angenommen, Sie haben mehrere Klassen und Benutzeroberflächen, die alle Befehle hatten, die nie deaktiviert wurden, dann müssten Sie für jedes Fenster oder UserControl eine „CanAlwaysExecute“-Methode schreiben!Das ist einfach nicht sehr TROCKEN.

Nachdem ich mehrere Blogs gelesen und verschiedene Dinge ausprobiert habe, habe ich mich entschieden, XAML ausschließlich auf Aussehen, Stile, Animationen und Trigger zu konzentrieren.Die gesamte Verknüpfung von Event-Handlern und Befehlen erfolgt jetzt im Code-Behind.:) :)

Ein weiteres Problem ist übrigens die Eingabebindung. Damit sie abgefangen wird, muss der Fokus auf dem Objekt liegen, das die Eingabebindungen enthält.Um beispielsweise eine Verknüpfung zu haben, die Sie jederzeit verwenden können (z. B. F1 zum Öffnen der Hilfe), muss diese Eingabebindung für das Window-Objekt festgelegt werden, da dieses immer den Fokus hat, wenn Ihre App aktiv ist.Die Verwendung der Code-Methode sollte dies einfacher machen, selbst wenn Sie mit der Verwendung von UserControls beginnen, die möglicherweise Eingabebindungen zu ihrem übergeordneten Fenster hinzufügen möchten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top