介紹:
WPF Commands是一種非常好的的方式去復用應用程序中功能。在本文提供的 示例中,創建了一個使用WPF的Command模式來對Customer進行排序的示例。 WPFCommand模式非常適合用於在應用程序中的用不同控件調用相同的功能。WPF commands 也能適用於一些其他的情況,例如,如果輸入有誤,禁用控件。在文 章的CanExecute部分中,我們能進一步了解。
創建一個Command:
為了使用WPF commands,你必須聲明靜態的command。當你聲明這個command ,你也能確定"Input Gestures"也能調用這個命令。你能把 "input gestures" 想象成快捷方式。一些基本的鍵或者甚至組合鍵。例如,在示例項目中,我使用 F3這個鍵作為"input gesture"。
/// <summary>
/// Command to sort the Customers
/// As ou can see the command also hooks to the F3 key of the keyboard
/// </summary>
public static RoutedUICommand SortCustomers = new RoutedUICommand("SortCustomers",
"SortCustomers", typeof(CommandsDemo), new InputGestureCollection (
new InputGesture[] { new KeyGesture(Key.F3, ModifierKeys.None, "Sort Customer") }
));
在這個示例項目中,和用戶界面窗體在同一個類(CommandDemo.cs)中創建 command。在實際生活中中的項目,我建議將command聲明在更重要的地方,好讓 Windows/Components能使用相同的command聲明。例如,如果在項目中的另外一 個窗體也能使用customers的排序功能,我會創建一個裡面有command的類。這樣 ,這個command能被其他窗體輕易地訪問。你能把commands 想象成類似於事件的 東西。有人執行該命令,就有人處理命令。在我的腦海中想象這樣一幅畫 面...
有三個家伙Jon, Mark和在商店工作Patrick 。商店的經理決定讓Patrick去 洗地板。Jon說“洗地板”,Patrick 就去執行。Mark說“洗地板”,Patrick就 去執行。所以,基本上Patrick 是Command的處理者,Jon, Mark執行命令致使 Patrick(命令處理者)去做這個操作的。經理說Patrick去洗地板是命令的綁定 。
上面是關於這個模式如何工作的基本解釋。也許這個會更令人困惑。按照這 樣的方式,我們快忘記了...在WPF類中RoutedCommand類似於RoutedEvents。調 用者執行這個命令,由WPF Visual Tree指揮路線直到CommandBinding來處理這 個命令。在命令處理的時候,通過設置e.Handled = true,將它停止。
現在讓我們繼續,在定義這個command之後,你必須去做的是如何綁定這個命 令。基本上,這意味著你需要指定誰去執行操作。如下:
//Here we create handle the command binding for the whole window
//so which ever control invokes this command the same handler will handle the command
CommandBindings.Add(new CommandBinding (SortCustomers, SortCustomersHandler));
//command binding for the delet customer
CommandBindings.Add(new CommandBinding (DeleteCustomer, DeleteCustomerHandler, CanExecuteDeleteCustomer));
//handle the CanExecuteChange to set the text of the delete text block
DeleteCustomer.CanExecuteChanged += delegate
{
bool canExecute = AvalonCommandsHelper.CanExecuteCommandSource(deleteButton);
deleteText.Text = canExecute ?
"Delete selected customer" :
"Select customer to delete";
};
}
//handler for the Sort Customers command.
//this event handler will be invoked when some element will execute the SortCustomers Command
private void SortCustomersHandler(object sender, ExecutedRoutedEventArgs e)
{
//default the sort if no parameter is passed
string sortBy = e.Parameter == null ?
"Name" :
e.Parameter.ToString();
//get the view for the list
ICollectionView view = CollectionViewSource.GetDefaultView(customerList.ItemsSource);
view.SortDescriptions.Clear();
//add the new sort description
view.SortDescriptions.Add(
new SortDescription(sortBy, ListSortDirection.Ascending));
view.Refresh();
}
那麼,留給我們要做的是創建 Mark 和Jon,他們才是實際執行這個命令的。 一些控件像button,當這個被點擊的時候,有一個command屬性讓你確定什麼命 令會被使用(你甚至通過使用CommandParameter屬性傳遞一個參數給這個命令) 。
>Command=”local:CommandsDemo.SortCustomers”
使用以下的C#代碼,你甚至可以手動地執行命令 :
ICommand command = SortCustomers;
command.Execute(”Name”);
第二部分 CanExecute :
WPF的command有另外的一個很酷的功能:CanExecute。基本上這是讓您可以 檢查該命令可以執行與不能執行的一個方法。如果你有一個只能在一定條件下執 行的命令,這是一個非常方便的功能。例如,你在一個ListBox的列表中有一用 戶列表。您希望能夠刪除用戶,你定義需要user id作為參數的命令。您通過獲 得ListBox中選擇項來確定要刪除用戶。傳遞id作為命令的參數。只有當用戶選 擇,您能執行的命令。
在CanExecuteChanged事件處理中,你必須調用ICommand接口的CanExecute方 法,為了檢查command的當前狀態是什麼。
代碼
//handler for the Can execute chack of the delete customer
private void CanExecuteDeleteCustomer(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null && e.Parameter is Customer; ;
e.Handled = true;
}
如果CanExecute為false, 通過禁用控件,所有的控件都支持命令模式(例 如:button)出處理CanExecute的結果。如果執行命令的控件不支持命令模式, 不用擔心,因為只有當CanExecute= TRUE的時候才能執行。當然也有(例如,改 變控件的visibility或者改變控件的text屬性)。 你也能執行這個。
bool canExecute = command.CanExecute(paramterForCommand);
我創建了一個幫助方法,它接受一個ICommandSource ,返回command的 CanExecute 狀態。
代碼
/// <summary>
/// Gets the Can Execute of a specific command
/// </summary>
/// <param name="commandSource">The command to verify</param>
/// <returns></returns>
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);
}
就像Demo中展示的一樣,你能使用這個方法來核實command 的狀態,我希望 這篇文章能讓你更好的理解command是如何運作的,如何使用好它來讓你的應用 程序代碼編寫的更好。為了你能更好的使用wpf的Command 模式,你可以下載這 篇文章的示例。
參考原文: http://www.codeproject.com/KB/WPF/wpfcommands.aspx
出處:http://zhuqil.cnblogs.com
代碼: http://files.cnblogs.com/zhuqil/WpfCommands.zip