WPF Commands 是在應用程式中重複使用功能的絕佳方式。本文範例展示使用 Command 模式對 Customer 進行排序。Command 模式適合不同控制項呼叫相同功能,也可根據條件啟用/停用控制項(如輸入驗證失敗時停用按鈕)。
需宣告靜態 Command,並可指定「輸入手勢」觸發(如快捷鍵)。範例使用 F3 鍵:
public static RoutedUICommand SortCustomers = new RoutedUICommand(
"SortCustomers", "SortCustomers", typeof(CommandsDemo),
new InputGestureCollection(new InputGesture[] {
new KeyGesture(Key.F3, ModifierKeys.None, "Sort Customer")
}));
建議將 Command 宣告於共用類別,供多視窗/元件存取。Command 運作類似事件:執行者發起命令,處理者執行,綁定機制連結兩者。WPF RoutedCommand 透過 Visual Tree 路由至 CommandBinding 處理。
// 視窗層級綁定,所有控制項觸發同一處理器
CommandBindings.Add(new CommandBinding(SortCustomers, SortCustomersHandler));
// 刪除命令含 CanExecute
CommandBindings.Add(new CommandBinding(DeleteCustomer, DeleteCustomerHandler, CanExecuteDeleteCustomer));
// 監聽 CanExecuteChanged 更新 UI 文字
DeleteCustomer.CanExecuteChanged += delegate {
bool canExecute = AvalonCommandsHelper.CanExecuteCommandSource(deleteButton);
deleteText.Text = canExecute ? "刪除選取客戶" : "請選取要刪除的客戶";
};
private void SortCustomersHandler(object sender, ExecutedRoutedEventArgs e)
{
string sortBy = e.Parameter == null ? "Name" : e.Parameter.ToString();
ICollectionView view = CollectionViewSource.GetDefaultView(customerList.ItemsSource);
view.SortDescriptions.Clear();
view.SortDescriptions.Add(new SortDescription(sortBy, ListSortDirection.Ascending));
view.Refresh();
}
XAML 中按鈕綁定:
<Button Command="{x:Static local:CommandsDemo.SortCustomers}" />
C# 手動執行:
ICommand command = SortCustomers;
command.Execute("Name");
檢查命令是否可執行。範例:ListBox 選取項目時才允許刪除。
private void CanExecuteDeleteCustomer(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null && e.Parameter is Customer;
e.Handled = true;
}
CanExecute=false 時,支援命令的控制項(如 Button)自動停用。非支援命令控制項需手動檢查:
bool canExecute = command.CanExecute(parameter);
public static bool CanExecuteCommandSource(ICommandSource commandSource)
{
ICommand baseCommand = commandSource.Command;
if (baseCommand == null) return false;
object commandParameter = commandSource.CommandParameter;
IInputElement commandTarget = commandSource.CommandTarget;
RoutedCommand command = baseCommand as RoutedCommand;
if (command == null) return baseCommand.CanExecute(commandParameter);
if (commandTarget == null) commandTarget = commandSource as IInputElement;
return command.CanExecute(commandParameter, commandTarget);
}
範例程式碼下載:WpfCommands.zip
參考原文:CodeProject