在上一篇中,我们学习了WPF的路由事件,而在本节将学习一个更为抽象且松耦合的事件版本,即命令。最明显的区别是,事件是与用户动作相关联的,而命令是那些与用户界面想分离的动作,例如我们最熟悉的剪切(Cut)、复制(Copy)和粘贴(Paste)命令。这带来的好处是:命令可以实现复用,减少了代码量,从而可以在不破坏后台逻辑的条件下,更加灵活地控制你的用户界面。然而,命令并不是WPF特有的,早在MFC中已经有了类似的机制,然而,在WPF之前使用命令是一件很烦琐的事情,因为需要考虑状态间的同步问题。WPF为了解决这个问题,增加了两个重要特性:一是将事件委托到适当的命令;而是将控件的启用状态与相应命令的状态保持一致。在Caliburn.Micro中完全用Command来代替事件。本篇将从WPF命令模型、自定义命令和WPF内置命令来学习。
WPF命令模型主要包含以下几个基本元素:
命令(Command):指的是实现了ICommand接口的类,例如RoutedCommand类及其子类RoutedUICommand类,一般不包含具体逻辑。
命令源(Command Source):即命令的发送者,指的是实现了ICommandSource接口的类。像Button、MenuItem等界面元素都实现了这个接口,单击它们都会执行绑定的命令。
命令目标(Command Target):即命令的接受者,指的是实现了IInputElement接口的类。
命令关联(Command Binding):即将一些外围逻辑和命令关联起来。
下面通过一个关系图来看下:
由上图,不难发现,命令目标需要通过命令关联来影响命令源。
1.1命令
WPF的命令模型的核心是System.Window.Input.ICommand接口,包含两个方法和一个事件。
public interface ICommand { // 摘要: // 当出现影响是否应执行该命令的更改时发生。 event EventHandler CanExecuteChanged; // 摘要: // 定义用于确定此命令是否可以在其当前状态下执行的方法。 // // 参数: // parameter: // 此命令使用的数据。如果此命令不需要传递数据,则该对象可以设置为 null。 // // 返回结果: // 如果可以执行此命令,则为 true;否则为 false。 bool CanExecute(object parameter); // // 摘要: // 定义在调用此命令时调用的方法。 // // 参数: // parameter: // 此命令使用的数据。如果此命令不需要传递数据,则该对象可以设置为 null。 void Execute(object parameter); }