【WPF】命令 Command
在使用 MVVM 結構的 WPF 程序中,ViewModel 對 View 的響應是通過 Command (命令)來完成的。比如用戶點了某個按鍵,使得與該按鍵相綁定的命令被觸發,而該命令又是在 ViewModel 中被定義的,于是就完成了一次 View 對 ViewModel 的調用。
WPF 和 C# 語言的高級用法,比如委托、反射、事件等等,是緊密聯系的,所以學習 WPF 時需要有一定的 C# 基礎。
雖然官方提供了一些常用命令,但本文還是著重于自定義命令的用法。
?? 方法一 從頭開始創建自定義命令
第一步:創建命令
命令有兩大要素:做什么、能做嗎。自定義命令首先要繼承自 ICommand:
class CustomCommand : ICommand
{
//當能不能做發生變化時會觸發的事件(必須要實現)
public event EventHandler CanExecuteChanged;
public void Execute(object param) //做什么(必須要實現)
{
if (ExecuteAction != null)
ExecuteAction(param);
}
public bool CanExecute(object param) //能做嗎(必須要實現)
{
if (CanExecuteAction != null)
return CanExecuteAction(param);
return false;
}
public Action<object> ExecuteAction { get; set; }
public Func<object, bool> CanExecuteAction { get; set; }
}
如上所示,ICommand 的后代有三個東西必須要實現,而最后兩個 ExecuteAction 和 CanExecuteAction 是比較推薦的寫法。
在本例中,Execute() 方法是 ICommand 認定的用來執行命令的方法,ExecuteAction 是對該方法的一項委托,于是外部使用者(ViewModel)只需設置這份委托,而不需染指 Execute() 方法。
第二步:完成ViewModel
接下來把這個命令類放在 ViewModel 中使用:
//先實例化這個命令(這是屬于ViewModel的命令,等下要被送到View中去)
public CustomCommand MyCommand { get; set; }
public void DoSomething(object param){
//這個命令真正要做的事情
}
public bool CanDoSomething(object param){
return true; //判斷能否做這個事情,大部分時候返回true就行了
}
public MyViewModel(){
//在ViewModel的構造函數中,完成對命令的設置
MyCommand = new CustomCommand();
MyCommand.ExecuteAction = new Action<object>(this.DoSomething);
MyCommand.CanExecuteAction = new Func<object, bool>(this.CanDoSomething);
}
ViewModel 中定義了兩個函數,分別對應命令的“做什么”、“能做嗎”,并通過委托的方式告訴命令。
第三步:完成View
剩下的就是 View 中的內容了:
先要加入命名空間,才能獲得我們的 ViewModel。這里把命名空間設為vm
<Window xmlns:vm="clr-namespace:MyApp.ViewModel" ... />
<Grid>
<Grid.DataContext>
<vm:MyViewModel> <!--把第二步中的ViewModel當作DataContext-->
</Grid.DataContext>
<Button Content="Click here" Command="{Binding MyCommand}" />
</Grid>
</Window>
在 View 的 xaml 文件中,首先把 ViewModel 當作它的 DataContext (畢竟 ViewModel 其實就是 View 的 Model)。然后直接在按鈕上用 Binding 的方式綁定命令。于是當用戶點擊按鈕時,這個命令就會被觸發。
命令被觸發時,它會先調用自己的 CanExecute() 方法,這個方法在第一步中調用 CanExecuteAction 這個委托,這份委托又在第二步中綁定了 CanDoSomething() 方法……經過一番長途跋涉之后終于調用了 DoSomething() 方法 ??。
感受:如果按照老辦法,按鈕響應只需設一個 OnClick 的方法就成了,簡單清爽,完全不必大費周章搞這么多事。可當程序到了一定規模,舊的思路就使維護變得難以維系。做界面還是應該養成良好的習慣
?? 方法二 使用自帶的 RoutedUICommand
先創建一個命令:
public static class CustomCommands
{
public static readonly RoutedUICommand ExitCommand = new RoutedUICommand(
"quit app",
"ExitCommand",
typeof(CustomCommands),
new InputGestureCollection() {
new KeyGesture(Key.W, ModifierKeys.Control) //可以為它綁定快捷鍵
});
}
然后為“做什么”和“能做嗎”定義兩個方法:
public void ExitCommand_Execute(object sender, ExecutedRoutedEventArgs e)
{
//在這里寫執行命令的具體內容(要做什么事)
e.Handled = true;
}
public void ExitCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true; //在這里判斷該命令能否執行
e.Handled = true;
}
最后在 xaml 里面:
<Window.CommandBindings>
<CommandBinding Command="local:CustomCommands.ExitCommand"
CanExecute="ExitCommand_CanExecute"
Executed="ExitCommand_Execute"/>
</Window.CommandBindings>
<Button Content="Exit" Command="local:CustomCommands.ExitCommand"/>
要說 WPF 還真是有點復雜啊。

浙公網安備 33010602011771號