代码:
介绍:
WPF Commands是一种非常好的的方式去复用应用程序中功能。在本文提供的示例中,创建了一个使用WPF的Command模式来对Customer进行排序的示例。WPFCommand模式非常适合用于在应用程序中的用不同控件调用相同的功能。 WPF command
s 也能适用于一些其他的情况,例如,如果输入有误,禁用控件。在文章的CanExecute部分中,我们能进一步了解。
创建一个Command:
为了使用WPF command
s,你必须声明静态的command。当你声明这个command,你也能确定"Input Gestures"也能调用这个命令。你能把 "input gestures" 想象成快捷方式。一些基本的键或者甚至组合键。例如,在示例项目中,我使用F3这个键作为"input gesture"。
/// 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 想象成类似于事件的东西。有人执行该命令,就有人处理命令。在我的脑海中想象这样一幅画面...
上面是关于这个模式如何工作的基本解释。也许这个会更令人困惑。按照这样的方式,我们快忘记了...在WPF类中RoutedCommand类似于RoutedEvents。调用者执行这个命令,由WPF Visual Tree指挥路线直到CommandBinding来处理这个命令。在命令处理的时候,通过设置e.Handled = true,将它停止。
现在让我们继续,在定义这个command之后,你必须去做的是如何绑定这个命令。基本上,这意味着你需要指定谁去执行操作。如下:
//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属性传递一个参数给这个命令)。
使用以下的C#代码,你甚至可以手动地执行命令 :
第二部分 CanExecute :
WPF的command有另外的一个很酷的功能:CanExecute。基本上这是让您可以检查该命令可以执行与不能执行的一个方法。如果你有一个只能在一定条件下执行的命令,这是一个非常方便的功能。例如,你在一个ListBox的列表中有一用户列表。您希望能够删除用户,你定义需要user id作为参数的命令。您通过获得ListBox中选择项来确定要删除用户。 传递id作为命令的参数。只有当用户选择,您能执行的命令。
在CanExecuteChanged事件处理中,你必须调用ICommand接口的CanExecute方法,为了检查command的当前状态是什么。
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属性)。 你也能执行这个。
我创建了一个帮助方法,它接受一个ICommandSource ,返回command的CanExecute 状态。
/// 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 模式,你可以下载这篇文章的示例。
参考原文: