wpf命令詳解
什麼是命令?
命令是Windows Presentation Foundation(WPF)中的一種輸入機制,它提供比裝置輸入更多的語義級別的輸入處理。
命令有幾個目的。第一個目的是將語義和呼叫命令的物件與執行命令的邏輯分開。這允許多個不同的源呼叫相同的命令邏輯,並且允許針對不同目標定製命令邏輯。例如,在許多應用程式中發現的編輯操作Copy,Cut和Paste可以通過使用不同的使用者操作(如果使用命令來實現)來呼叫。應用程式可能允許使用者通過單擊按鈕,選擇選單中的專案或使用組合鍵(例如CTRL + X)來剪下選定的物件或文字。通過使用命令,可以將每種型別的使用者操作繫結到相同的邏輯。
命令的另一個目的是指示操作是否可用。繼續以剪下物件或文字為例,該操作僅在選擇某些內容後才有意義。如果使用者嘗試在沒有選擇任何內容的情況下剪下物件或文字,則不會發生任何事情。為了向用戶表明這一點,許多應用程式禁用了按鈕和選單項,以便使用者知道是否可以執行某項操作。命令可以通過實現false
,或者如果啟用則CanExecute返回true
。
命令庫
WPF提供了一組預定義的命令。命令庫由以下類組成:ApplicationCommands,NavigationCommands,MediaCommands,EditingCommands和ComponentCommands。這些類提供諸如命令剪下,貼上,複製,browseback和browseforward,播放,停止,暫停。
其中許多命令都包含一組預設輸入繫結。例如,如果指定您的應用程式處理複製命令,則會自動獲得鍵盤繫結“ CTRL + C”。您還將獲得其他輸入裝置的繫結,例如Tablet PC筆手勢和語音資訊。
WPF指揮中的四個主要概念
WPF中的路由命令模型可以分為四個主要概念:命令,命令源,命令目標和命令繫結:
-
命令是要執行的動作。
-
命令源是呼叫該命令的物件。
-
命令的目標是命令正在被執行的物件。
-
命令繫結是該命令邏輯對映到該命令的物件。
下面的示例演示如何設定MenuItem,以使其在單擊時將呼叫TextBox上的Paste命令(假定TextBox具有鍵盤焦點)。
<StackPanel>
<Menu>
<MenuItem Command="ApplicationCommands.Paste" />
</Menu>
<TextBox />
</StackPanel>
“貼上”是命令,“ 選單項”是命令源,“文字框”是命令目標,命令繫結由“文字框”控制元件提供。
指令
WPF中的命令是通過實現ICommand介面建立的。 ICommand公開了兩個方法Execute和CanExecute以及一個事件CanExecuteChanged。Execute執行與命令關聯的動作。CanExecute確定命令是否可以在當前命令目標上執行。如果集中命令操作的命令管理器檢測到命令源中的更改可能會使已引發但尚未由命令繫結執行的命令無效,則會引發CanExecuteChanged。ICommand的WPF實現是RoutedCommand類。
WPF中的主要輸入源是滑鼠,鍵盤,路由命令。面向裝置的更多輸入使用RoutedEvent來通知應用程式頁面中的物件已發生輸入事件。RoutedCommand是沒有什麼不同。Execute和CanExecute的RoutedCommand不包含該命令的應用程式邏輯,而是它們提高該隧道和氣泡通過元素樹,直到它們遇到一個物件與路由事件的CommandBinding。CommandBinding包含這些事件的處理程式,它是執行該命令的處理程式。
RoutedCommand的Execute方法在命令目標上引發PreviewExecuted和Executed事件。在CanExecute上的方法的RoutedCommand引發CanExecute和PreviewCanExecute上命令目標的事件。這些事件在元素樹中經過隧道並冒泡,直到它們遇到一個具有針對該特定命令的CommandBinding的物件。
命令源
命令源是呼叫命令的物件。命令源的示例包括MenuItem,Button和KeyGesture(快捷鍵)。
WPF中的命令源通常實現ICommandSource介面。
ICommandSource公開了三個屬性:Command,CommandTarget和CommandParameter:
Command是呼叫命令源時要執行的命令。
CommandTarget是要在其上執行命令的物件。如果未設定CommandTarget,則具有鍵盤焦點的元素將成為命令目標。
CommandParameter是使用者定義的資料型別,用於將資訊傳遞給實現命令的處理程式。
實現ICommandSource的WPF類是ButtonBase,MenuItem,Hyperlink和InputBinding。 單擊它們時,ButtonBase,MenuItem和Hyperlink會呼叫命令,而執行與之關聯的InputGesture時,InputBinding會呼叫命令。
通常,命令源將偵聽CanExecuteChanged事件。此事件通知命令源該命令在當前命令目標上執行的能力可能已更改。命令源可以使用CanExecute方法查詢RoutedCommand的當前狀態。如果命令無法執行,則命令源可以禁用自身。例如,當無法執行命令時,MenuItem會自動變灰。
一個InputGesture可以用作命令源。WPF中的兩種輸入手勢是KeyGesture和MouseGesture。您可以將KeyGesture視為鍵盤快捷鍵,例如CTRL + C。
為了使InputGesture充當命令源,它必須與命令關聯。有幾種方法可以完成此操作。一種方法是使用InputBinding。
下面的示例演示如何在KeyGesture和RoutedCommand之間建立KeyBinding。即建立把快捷鍵當成命令源。
<Window.InputBindings>
<KeyBinding Key="B"
Modifiers="Control"
Command="ApplicationCommands.Open" />
</Window.InputBindings>
將InputGesture關聯到RoutedCommand的另一種方法是將InputGesture新增到RoutedCommand的InputGestureCollection上。
下面的示例演示如何將新增KeyGesture到InputGestureCollection一個的的RoutedCommand。
KeyGesture OpenCmdKeyGesture = new KeyGesture(
Key.B,
ModifierKeys.Control);
ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture);
命令繫結
CommandBinding關聯與執行命令的事件處理程式的命令。
CommandBinding類包含一個命令屬性,PreviewExecuted,Execute,PreviewCanExecute和CanExecute事件。
下面的示例演示如何在應用程式的根視窗上建立CommandBinding。
<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);
接下來,建立ExecutedRoutedEventHandler和CanExecuteRoutedEventHandler。該ExecutedRoutedEventHandler開啟一個訊息框,其中顯示的字串說命令已被執行。該CanExecuteRoutedEventHandler設定CanExecute屬性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);
}
void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
命令目標
命令目標是在其上執行命令的元素。關於RoutedCommand,命令目標是Executed和CanExecute路由開始的元素。如果在ICommandSource上設定了CommandTarget並且相應的命令不是RoutedCommand,則將忽略命令目標。
命令源可以顯式設定命令目標。如果未定義命令目標,則將具有鍵盤焦點的元素用作命令目標。將具有鍵盤焦點的元素用作命令目標的好處之一是,它使應用程式開發人員可以使用同一命令源在多個目標上呼叫命令,而不必跟蹤命令目標。例如,如果MenuItem在具有TextBox控制元件和PasswordBox控制元件的應用程式中呼叫“ 貼上”命令,則目標可以是TextBox或PasswordBox,具體取決於哪個控制元件具有鍵盤焦點。
下面的示例演示如何在標記和後面的程式碼中顯式設定命令目標。
<StackPanel>
<Menu>
<MenuItem Command="ApplicationCommands.Paste"
CommandTarget="{Binding ElementName=mainTextBox}" />
</Menu>
<TextBox Name="mainTextBox"/>
</StackPanel>
接下來,建立ExecutedRoutedEventHandler和CanExecuteRoutedEventHandler。該ExecutedRoutedEventHandler開啟一個訊息框,其中顯示的字串說命令已被執行。該CanExecuteRoutedEventHandler設定CanExecute屬性true
。