Przegląd Polecenia

Polecenie to mechanizm wejściowy w programie Windows Presentation Foundation (WPF), który zapewnia obsługę danych wejściowych na bardziej semantycznym poziomie niż dane wejściowe urządzenia. Przykłady poleceń to operacje kopiowania, wycinania i wklejania znajdujące się w wielu aplikacjach.

To omówienie definiuje polecenia w WPF, które klasy są częścią modelu poleceń oraz jak używać i tworzyć polecenia w aplikacjach.

Ten temat zawiera następujące sekcje:

Co to są polecenia

Polecenia mają kilka celów. Pierwszym celem jest oddzielenie semantyki i obiektu, który wywołuje polecenie z logiki wykonującej polecenie. Dzięki temu wiele różnych źródeł może wywołać tę samą logikę poleceń i umożliwia dostosowanie logiki poleceń dla różnych obiektów docelowych. Na przykład operacje edycji Copy, Cut i Paste, które znajdują się w wielu aplikacjach, mogą być wywoływane przy użyciu różnych akcji użytkownika, jeśli są implementowane za pomocą poleceń. Aplikacja może zezwolić użytkownikowi na wycinanie zaznaczonych obiektów lub tekstu przez kliknięcie przycisku, wybranie elementu w menu lub użycie kombinacji klawiszy, takiej jak CTRL+X. Za pomocą poleceń można powiązać każdy typ akcji użytkownika z tą samą logiką.

Innym celem poleceń jest wskazanie, czy jest dostępna akcja. Aby kontynuować przykład cięcia obiektu lub tekstu, akcja ma sens tylko wtedy, gdy coś jest zaznaczone. Jeśli użytkownik spróbuje wyciąć obiekt lub tekst bez wybrania niczego, nic się nie stanie. Aby wskazać to użytkownikowi, wiele aplikacji wyłącza przyciski i elementy menu, aby użytkownik wiedział, czy można wykonać akcję. Polecenie może wskazywać, czy akcja jest możliwa przez zaimplementowanie CanExecute metody . Przycisk może subskrybować CanExecuteChanged zdarzenie i być wyłączony, jeśli CanExecute jest zwracany false lub włączony, jeśli CanExecute zwraca wartość true.

Semantyka polecenia może być spójna w aplikacjach i klasach, ale logika akcji jest specyficzna dla określonego obiektu, na który działał. Kombinacja klawiszy CTRL+X wywołuje polecenie Cut w klasach tekstowych, klasach obrazów i przeglądarkach sieci Web, ale rzeczywista logika wykonywania operacji wycinania jest definiowana przez aplikację wykonującą wycinanie. Element umożliwia RoutedCommand klientom implementowanie logiki. Obiekt tekstowy może wyciąć zaznaczony tekst do schowka, podczas gdy obiekt obrazu może wyciąć wybrany obraz. Gdy aplikacja obsługuje Executed zdarzenie, ma dostęp do obiektu docelowego polecenia i może podjąć odpowiednie działania w zależności od typu obiektu docelowego.

Prosty przykład polecenia w WPF

Najprostszym sposobem użycia polecenia w WPF jest użycie wstępnie zdefiniowanej RoutedCommand z jednej z klas bibliotek poleceń; użyj kontrolki, która ma natywną obsługę polecenia, i użyj kontrolki, która ma natywną obsługę polecenia, i użyj kontrolki, która ma natywną obsługę wywoływania polecenia. Polecenie Paste jest jednym ze wstępnie zdefiniowanych poleceń w ApplicationCommands klasie . Kontrolka TextBox ma wbudowaną logikę Paste do obsługi polecenia. Klasa ma natywną MenuItem obsługę wywoływania poleceń.

W poniższym przykładzie pokazano, jak skonfigurować MenuItem element tak, aby po kliknięciu wywołał Paste polecenie na TextBoxobiekcie , przy założeniu TextBox , że fokus klawiatury.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

Cztery główne pojęcia w poleceniach WPF

Model poleceń kierowanych w WPF można podzielić na cztery główne pojęcia: polecenie, źródło polecenia, element docelowy polecenia i powiązanie polecenia:

  • Polecenie to akcja do wykonania.

  • Źródłem polecenia jest obiekt, który wywołuje polecenie .

  • Obiektem docelowym polecenia jest obiekt, na który jest wykonywane polecenie.

  • Powiązanie polecenia to obiekt, który mapuje logikę poleceń na polecenie.

W poprzednim przykładzie Paste polecenie to polecenie, MenuItem czyli źródło polecenia, TextBox jest elementem docelowym polecenia, a powiązanie polecenia jest dostarczane przez kontrolkę TextBox . Warto zauważyć, że nie zawsze jest to przypadek, że CommandBinding element jest dostarczany przez kontrolkę, która jest klasą docelową polecenia. Zupełnie często CommandBinding element musi zostać utworzony przez dewelopera aplikacji lub CommandBinding element może być dołączony do przodka obiektu docelowego polecenia.

Polecenia

Polecenia w WPF są tworzone przez zaimplementowanie interfejsu ICommand . ICommandUwidacznia dwie metody, Executei , i CanExecutezdarzenie . CanExecuteChanged Execute wykonuje akcje skojarzone z poleceniem . CanExecute Określa, czy polecenie może zostać wykonane na bieżącym obiekcie docelowym polecenia. CanExecuteChanged Jest zgłaszany, jeśli menedżer poleceń, który centralizuje operacje poleceń wykrywa zmianę w źródle poleceń, które może unieważnić polecenie, które zostało zgłoszone, ale nie zostało jeszcze wykonane przez powiązanie polecenia. Implementacja ICommand WPF klasy jest klasą RoutedCommand i koncentruje się na tym omówieniu.

Głównymi źródłami danych wejściowych w WPF są mysz, klawiatura, atrament i kierowane polecenia. Bardziej zorientowane na urządzenia dane wejściowe używają elementu do RoutedEvent powiadamiania obiektów na stronie aplikacji o wystąpieniu zdarzenia wejściowego. Wartość A RoutedCommand nie różni się. Metody ExecuteRoutedCommand i CanExecute nie zawierają logiki aplikacji dla polecenia, ale raczej zgłaszają zdarzenia kierowane przez tunel i bąbelek przez drzewo elementów, dopóki nie napotkają obiektu z obiektem CommandBinding. Zawiera CommandBinding programy obsługi dla tych zdarzeń i są to programy obsługi wykonujące polecenie. Aby uzyskać więcej informacji na temat routingu zdarzeń w WPF, zobacz Routed Events Overview (Przegląd zdarzeń trasowanych).

Metoda Execute w obiekcie RoutedCommand wywołuje PreviewExecuted zdarzenia i Executed w obiekcie docelowym polecenia. Metoda CanExecute w obiekcie RoutedCommand wywołuje CanExecute zdarzenia i PreviewCanExecute w obiekcie docelowym polecenia. Te zdarzenia tunelują i bąbelkują przez drzewo elementów, dopóki nie napotkają obiektu, który ma CommandBinding dla tego konkretnego polecenia.

WPF udostępnia zestaw typowych poleceń trasowanych rozmieszczonych w kilku klasach: MediaCommands, , NavigationCommandsApplicationCommands, ComponentCommandsi EditingCommands. Te klasy składają się tylko z RoutedCommand obiektów, a nie logiki implementacji polecenia. Logika implementacji to odpowiedzialność za obiekt, na którym jest wykonywane polecenie.

Źródła poleceń

Źródłem polecenia jest obiekt, który wywołuje polecenie. Przykłady źródeł poleceń to MenuItem, Buttoni KeyGesture.

Źródła poleceń w WPF zwykle implementują ICommandSource interfejs.

ICommandSource Uwidacznia trzy właściwości: Command, CommandTargeti CommandParameter:

  • Command to polecenie do wykonania po wywołaniu źródła polecenia.

  • CommandTarget to obiekt, na którym należy wykonać polecenie. Warto zauważyć, że w WPF CommandTarget właściwość on ICommandSource ma zastosowanie tylko wtedy, gdy ICommand jest RoutedCommand. CommandTarget Jeśli właściwość jest ustawiona na , ICommandSource a odpowiednie polecenie nie jest wartością RoutedCommand, obiekt docelowy polecenia jest ignorowany. CommandTarget Jeśli parametr nie jest ustawiony, element z fokusem klawiatury będzie obiektem docelowym polecenia.

  • CommandParameter to typ danych zdefiniowany przez użytkownika służący do przekazywania informacji do procedur obsługi implementujących polecenie .

Klasy WPF, które implementują ICommandSource , to ButtonBase, MenuItem, Hyperlinki InputBinding. ButtonBase, MenuItemi Hyperlink wywołaj polecenie po kliknięciu i InputBinding wywołuje polecenie po jego wykonaniu InputGesture .

W poniższym przykładzie pokazano, jak używać elementu MenuItem w ContextMenu źródle poleceń jako polecenia Properties .

<StackPanel>
  <StackPanel.ContextMenu>
    <ContextMenu>
      <MenuItem Command="ApplicationCommands.Properties" />
    </ContextMenu>
  </StackPanel.ContextMenu>
</StackPanel>
StackPanel cmdSourcePanel = new StackPanel();
ContextMenu cmdSourceContextMenu = new ContextMenu();
MenuItem cmdSourceMenuItem = new MenuItem();

// Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu;
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem);

// Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties;
Dim cmdSourcePanel As New StackPanel()
Dim cmdSourceContextMenu As New ContextMenu()
Dim cmdSourceMenuItem As New MenuItem()

' Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem)

' Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties

Zazwyczaj źródło polecenia nasłuchuje CanExecuteChanged zdarzenia. To zdarzenie informuje źródło polecenia, że możliwość wykonywania polecenia w bieżącym obiekcie docelowym polecenia mogła ulec zmianie. Źródło polecenia może wykonywać zapytania dotyczące bieżącego RoutedCommand stanu obiektu przy użyciu CanExecute metody . Źródło polecenia może następnie wyłączyć się, jeśli polecenie nie może zostać wykonane. Przykładem jest MenuItem szarość, gdy polecenie nie może zostać wykonane.

Element InputGesture może służyć jako źródło polecenia. Dwa typy gestów wejściowych w WPF to i KeyGestureMouseGesture. Możesz traktować KeyGesture jako skrót klawiaturowy, taki jak CTRL+C. Element A KeyGesture składa się z zestawu Key i ModifierKeys. Obiekt MouseGesture składa się z MouseAction elementu i opcjonalnego ModifierKeyszestawu .

Aby element InputGesture działał jako źródło polecenia, musi być skojarzony z poleceniem. Istnieje kilka sposobów, aby to osiągnąć. Jednym ze sposobów jest użycie elementu InputBinding.

W poniższym przykładzie pokazano, jak utworzyć element KeyBinding między a i KeyGesture .RoutedCommand

<Window.InputBindings>
  <KeyBinding Key="B"
              Modifiers="Control" 
              Command="ApplicationCommands.Open" />
</Window.InputBindings>
KeyGesture OpenKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

KeyBinding OpenCmdKeybinding = new KeyBinding(
    ApplicationCommands.Open,
    OpenKeyGesture);

this.InputBindings.Add(OpenCmdKeybinding);
Dim OpenKeyGesture As New KeyGesture(Key.B, ModifierKeys.Control)

Dim OpenCmdKeybinding As New KeyBinding(ApplicationCommands.Open, OpenKeyGesture)

Me.InputBindings.Add(OpenCmdKeybinding)

Innym sposobem skojarzenia elementu z elementem jest dodanie elementu InputGesture do InputGestureCollection elementu w obiekcie RoutedCommand.InputGestureRoutedCommand

W poniższym przykładzie pokazano, jak dodać element KeyGesture do InputGestureCollection obiektu RoutedCommand.

KeyGesture OpenCmdKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture);
Dim OpenCmdKeyGesture As New KeyGesture(Key.B, ModifierKeys.Control)

ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture)

CommandBinding

Element CommandBinding kojarzy polecenie z procedurami obsługi zdarzeń, które implementują polecenie.

Klasa CommandBinding zawiera Command właściwość , i PreviewExecuted, ExecutedPreviewCanExecutei CanExecute zdarzenia.

Command to polecenie, CommandBinding z którymi jest skojarzone. Programy obsługi zdarzeń dołączone do PreviewExecuted zdarzeń i Executed implementują logikę poleceń. Programy obsługi zdarzeń dołączone do zdarzeń PreviewCanExecute i CanExecute określają, czy polecenie może zostać wykonane w bieżącym obiekcie docelowym polecenia.

W poniższym przykładzie pokazano, jak utworzyć obiekt CommandBinding w katalogu głównym Window aplikacji. Polecenie CommandBinding powoduje skojarzenie Open polecenia z procedurami Executed obsługi i .CanExecute

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Open"
                  Executed="OpenCmdExecuted"
                  CanExecute="OpenCmdCanExecute"/>
</Window.CommandBindings>
// Creating CommandBinding and attaching an Executed and CanExecute handler
CommandBinding OpenCmdBinding = new CommandBinding(
    ApplicationCommands.Open,
    OpenCmdExecuted,
    OpenCmdCanExecute);

this.CommandBindings.Add(OpenCmdBinding);
' Creating CommandBinding and attaching an Executed and CanExecute handler
Dim OpenCmdBinding As New CommandBinding(ApplicationCommands.Open, AddressOf OpenCmdExecuted, AddressOf OpenCmdCanExecute)

Me.CommandBindings.Add(OpenCmdBinding)

Następnie zostaną utworzone wartości ExecutedRoutedEventHandler i CanExecuteRoutedEventHandler . Otwiera ExecutedRoutedEventHandler element MessageBox , który wyświetla ciąg z informacją, że polecenie zostało wykonane. Właściwość CanExecuteRoutedEventHandler ustawia CanExecute wartość true.

void OpenCmdExecuted(object target, ExecutedRoutedEventArgs e)
{
    String command, targetobj;
    command = ((RoutedCommand)e.Command).Name;
    targetobj = ((FrameworkElement)target).Name;
    MessageBox.Show("The " + command +  " command has been invoked on target object " + targetobj);
}
Private Sub OpenCmdExecuted(ByVal sender As Object, ByVal e As ExecutedRoutedEventArgs)
    Dim command, targetobj As String
    command = CType(e.Command, RoutedCommand).Name
    targetobj = CType(sender, FrameworkElement).Name
    MessageBox.Show("The " + command + " command has been invoked on target object " + targetobj)
End Sub
void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}
Private Sub OpenCmdCanExecute(ByVal sender As Object, ByVal e As CanExecuteRoutedEventArgs)
    e.CanExecute = True
End Sub

Element jest CommandBinding dołączony do określonego obiektu, takiego jak katalog główny Window aplikacji lub kontrolki. Obiekt CommandBinding dołączony do definiuje zakres powiązania. Na przykład CommandBinding obiekt docelowy polecenia dołączony do obiektu docelowego polecenia może zostać osiągnięty przez Executed zdarzenie, ale CommandBinding nie można uzyskać dostępu do elementu podrzędnego obiektu docelowego polecenia. Jest to bezpośrednia konsekwencja sposobu, w jaki RoutedEvent tunele i bąbelki z obiektu, który wywołuje zdarzenie.

W niektórych sytuacjach element CommandBinding jest dołączony do samego obiektu docelowego polecenia, na przykład z klasą TextBox i Cutpoleceniami , Copyi Paste . Dość często jednak jest to wygodniejsze dołączanie CommandBinding elementu do przodka obiektu docelowego polecenia, takiego jak główny Window lub obiekt aplikacji, zwłaszcza jeśli ten sam CommandBinding może być używany dla wielu obiektów docelowych poleceń. Są to decyzje projektowe, które należy wziąć pod uwagę podczas tworzenia infrastruktury poleceń.

Element docelowy polecenia

Elementem docelowym polecenia jest element, na którym jest wykonywane polecenie. W odniesieniu do RoutedCommandelementu , element docelowy polecenia jest elementem, w którym uruchamia się routing Executed i CanExecute . Jak wspomniano wcześniej, w WPF CommandTarget właściwość on ICommandSource ma zastosowanie tylko wtedy, gdy ICommand jest RoutedCommand. CommandTarget Jeśli właściwość jest ustawiona na , ICommandSource a odpowiednie polecenie nie jest wartością RoutedCommand, obiekt docelowy polecenia jest ignorowany.

Źródło polecenia może jawnie ustawić element docelowy polecenia. Jeśli element docelowy polecenia nie jest zdefiniowany, element z fokusem klawiatury będzie używany jako element docelowy polecenia. Jedną z zalet używania elementu z fokusem klawiatury jako obiektu docelowego polecenia jest to, że umożliwia deweloperowi aplikacji używanie tego samego źródła poleceń do wywoływania polecenia na wielu miejscach docelowych bez konieczności śledzenia celu polecenia. Na przykład jeśli obiekt MenuItem wywołuje polecenie Wklej w aplikacji, która ma kontrolkę TextBox i kontrolkęPasswordBox, element docelowy może być TextBox obiektem docelowym lub PasswordBox w zależności od tego, która kontrolka ma fokus klawiatury.

W poniższym przykładzie pokazano, jak jawnie ustawić element docelowy polecenia w znaczników i w kodzie.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste"
              CommandTarget="{Binding ElementName=mainTextBox}" />
  </Menu>
  <TextBox Name="mainTextBox"/>
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;
' Creating the UI objects
Dim mainStackPanel As New StackPanel()
Dim pasteTextBox As New TextBox()
Dim stackPanelMenu As New Menu()
Dim pasteMenuItem As New MenuItem()

' Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem)
mainStackPanel.Children.Add(stackPanelMenu)
mainStackPanel.Children.Add(pasteTextBox)

' Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste

The CommandManager

Funkcja CommandManager obsługuje wiele funkcji związanych z poleceniami. Udostępnia zestaw metod statycznych do dodawania i usuwania PreviewExecutedprogramów obsługi zdarzeń , Executed, PreviewCanExecutei CanExecute do i z określonego elementu. Zapewnia metodę rejestrowania CommandBinding i InputBinding obiektów w określonej klasie. Zapewnia CommandManager również środki, za pośrednictwem RequerySuggested zdarzenia, aby powiadomić polecenie, kiedy powinno zgłosić CanExecuteChanged zdarzenie.

Metoda InvalidateRequerySuggested wymusza CommandManager wywołanie RequerySuggested zdarzenia. Jest to przydatne w przypadku warunków, które powinny wyłączyć/włączyć polecenie, ale nie są warunkami, o których CommandManager jest świadomy.

Biblioteka poleceń

WPF udostępnia zestaw wstępnie zdefiniowanych poleceń. Biblioteka poleceń składa się z następujących klas: ApplicationCommands, , NavigationCommandsMediaCommands, EditingCommandsi ComponentCommands. Te klasy udostępniają polecenia, takie jak Cut, BrowseBack i BrowseForward, StopPlayi Pause.

Wiele z tych poleceń obejmuje zestaw domyślnych powiązań wejściowych. Jeśli na przykład określisz, że aplikacja obsługuje polecenie kopiowania, automatycznie uzyskasz powiązanie klawiatury "CTRL+C" Również otrzymasz powiązania dla innych urządzeń wejściowych, takich jak gesty pióra komputera tabletu i informacje o mowie.

Gdy odwołujesz się do poleceń w różnych bibliotekach poleceń przy użyciu języka XAML, zazwyczaj można pominąć nazwę klasy klasy, która uwidacznia statyczną właściwość polecenia. Ogólnie rzecz biorąc, nazwy poleceń są jednoznaczne jako ciągi, a typy właścicieli istnieją w celu zapewnienia logicznego grupowania poleceń, ale nie są niezbędne do uściślania. Można na przykład określić Command="Cut" , a nie bardziej pełne Command="ApplicationCommands.Cut". Jest to mechanizm wygody, który jest wbudowany w procesor XAML WPF dla poleceń (dokładniej jest to zachowanie konwertera ICommandtypów , które procesor WPF XAML odwołuje się w czasie ładowania).

Tworzenie poleceń niestandardowych

Jeśli polecenia w klasach bibliotek poleceń nie spełniają Twoich potrzeb, możesz utworzyć własne polecenia. Istnieją dwa sposoby tworzenia polecenia niestandardowego. Pierwszym z nich jest rozpoczęcie od podstaw i zaimplementowanie interfejsu ICommand . Innym sposobem i bardziej typowym podejściem jest utworzenie elementu RoutedCommand lub .RoutedUICommand

Przykład tworzenia niestandardowego obiektu można znaleźć w temacie Create a Custom RoutedCommand Sample (Tworzenie niestandardowego RoutedCommandroutedCommand Sample).

Zobacz też