2008-08-12 7 views
34

Zrobiłem programowanie WPF i jedną rzeczą, której nigdy nie otrzymałem, był wzorzec poleceń. Każdy przykład wydaje się być wbudowany, edytować, wyciąć, wkleić. Czy ktoś ma przykład lub sugestię najlepszej praktyki dla niestandardowych poleceń?Niestandardowy przykład wzoru polecenia WPF

Odpowiedz

38

Ah ha! Pytanie, na które mogę odpowiedzieć! Po pierwsze, powinienem wspomnieć, że osobiście łatwiej mi było zdefiniować i podłączyć polecenia w kodzie niż w XAML. Pozwala mi to nieco bardziej elastycznie podpinać procedury obsługi poleceń niż wszystkie metody XAML.

Powinieneś dowiedzieć się, jakie polecenia chcesz mieć i do czego się odnoszą. W mojej aplikacji, obecnie mam klasę definiowania ważnych poleceń aplikacji tak:

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

Teraz, ponieważ chciałem zachować kod wszyscy razem, przy użyciu kodu tylko podejście do poleceń pozwala mi umieścić następujące metody w Klasa powyżej:

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

Druga metoda może być nawet udostępniona innym poleceniom bez konieczności powtarzania go w każdym miejscu.

Po zdefiniowaniu takich poleceń można je dodać do dowolnego elementu interfejsu użytkownika. Poniżej, po załadowaniu okna, dodaję powiązania poleceń zarówno do Window i MenuItem, a następnie dodam powiązanie wejściowe do okna za pomocą pętli, aby zrobić to dla wszystkich powiązań poleceń. Parametrem, który jest przekazywany, jest Window self, więc powyższy kod wie, jakie okno spróbować zamknąć.

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

    // .... 
} 

Wtedy też później mieć obsługi zdarzeń dla zdarzeń WindowClosing i WindowClosed, ja polecam Ci dokonać faktycznej realizacji poleceń małych i generycznych, jak to możliwe. Podobnie jak w tym przypadku, nie próbowałem umieszczać kodu, który próbuje zatrzymać zamykanie okna, jeśli są niezapisane dane, zachowałem ten kod mocno wewnątrz zdarzenia WindowClosing.

Daj mi znać, jeśli masz dodatkowe pytania. :)

+2

Twój CanExecuteIfParameterIsNotNull zawiera jeden z moich przykrości domowych. Dlaczego nie tylko e.CanExecute = e.Parameter! = Null; – Ray

+0

@Ray To nie było coś, o czym wiedziałem, że mogę zrobić! Dzięki za edycję Drew. :) – Nidonocu

3

Rzeczą o XAML jest to, że jest ona dobra dla "prostych" programów, ale niestety nie działa dobrze, gdy chcesz robić takie rzeczy, jak funkcje udostępniania. Załóżmy, że masz kilka klas i interfejsów, z których wszystkie miały polecenia, które nigdy nie były wyłączone, musisz napisać metodę "CanAlwaysExecute" dla każdego Window lub UserControl! To po prostu niezbyt dobrze DRY.

Po przeczytaniu kilku blogów i kilku próbach dokonałem wyboru, aby zrobić XAML wyłącznie o wyglądzie, stylach, animacji i wyzwalaczach. Całe moje podpinanie programów obsługi zdarzeń i komendy jest teraz w tyle za kodem. :)

Innym sposobem przyzwyczajenia jest powiązanie wejścia, w celu ich przechwycenia, fokus musi znajdować się na obiekcie zawierającym wiązania wejściowe. Na przykład, aby uzyskać skrót, którego możesz użyć w dowolnym momencie (powiedz F1, aby otworzyć pomoc), to powiązanie wejścia musi być ustawione na obiekcie Window, ponieważ zawsze ma ono fokus, gdy twoja aplikacja jest Aktywna. Użycie metody kodu powinno ułatwić to zadanie, nawet po rozpoczęciu korzystania z kontrolek UserControl, które mogą chcieć dodać powiązania wejściowe do ich okna nadrzędnego.

7
+2

http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx Ten link jest martwy :( – Drahakar