UI交互时,很多功能都是有不同的入口来实现,例如:复制、粘贴等。早期winform编程的时候一般都是通过抽取方法,然后事件调用方法来实现代码复用。WPF提供了命令这一模式来实现这一应用 - 一功能、多入口。
WPF的一个命令系统是被分为四个部分:
1. Command(命令):一个语义级别的输入,比如“复制”等;
2. CommandSource(命令源):引发某命令的元素,比如按钮,菜单项,键盘(Ctrl-C,F1等),鼠标等;
3. CommandTarget(命令目标):命令被作用的目标,比如文本框,播放器等;
4. CommandBinding(命令绑定):用于将命令和命令的处理逻辑链接起来,比如同样的"粘贴",但粘贴文本和粘贴图片的处理逻辑是不一样的,命令绑定负责将“粘贴”命令与合理的处理逻辑连接起来。
其中,命令源是由引发命令的元素实现的,在WPF现有的控件中,如:MenuItem、ButtonBase等。而命令目标是由接收命令的元素实现,使用时属于非必须项。
下面是个简单的例子:
1. 界面定义和绑定命令:
1. <!--窗口命令绑定定义-->
2. <Window.CommandBindings>
3. "Undo"
4. "CommandBinding_Undo_CanExecute"
5. "CommandBinding_Undo_Execute"/>
6. "Redo"
7. "CommandBinding_Redo_CanExecute"
8. "CommandBinding_Redo_Execute"/>
9. "Zoom"
10. "CommandBinding_Zoom_Execute"/>
11. </Window.CommandBindings>
12.
13. <!--窗口输入命令绑定定义-->
14. <Window.InputBindings>
15. "Undo" Key="Z" Modifiers="Control" />
16. "Redo" Key="Y" Modifiers="Control" />
17. </Window.InputBindings>
1. <Menu x:Name="TopMenu" DockPanel.Dock="Top" >
2. <MenuItem x:Name="MenuEditItem" Header="编 辑">
3. "MenuUndoItem" Header="撤 销" Command="Undo" />
4. "MenuRedoItem" Header="重 做" Command="Redo" />
5. </MenuItem>
6. </Menu>
7. <!--窗口底部菜单-->
8. "BottomMenu" DockPanel.Dock="Bottom">
9. <!--画板缩放菜单-->
10. "MenuZoomItem" Header="缩放比例:100%">
11. "50%" Command="Zoom" CommandParameter="50" />
12. "75%" Command="Zoom" CommandParameter="75" />
13. "100%" Command="Zoom" CommandParameter="100" />
14. "120%" Command="Zoom" CommandParameter="120" />
15. "150%" Command="Zoom" CommandParameter="150" />
16. "200%" Command="Zoom" CommandParameter="200" />
17. "300%" Command="Zoom" CommandParameter="300" />
18. "400%" Command="Zoom" CommandParameter="400" />
19. "500%" Command="Zoom" CommandParameter="500" />
20. </MenuItem>
21. </Menu>
2. 后台代码实现:
1. #region Window Command
2. /// <summary>
3. /// 可否执行撤销命令判断
4. /// </summary>
5. /// <param name="sender">Command</param>
6. /// <param name="e">event arg</param>
7. private void CommandBinding_Undo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
8. {
9. if (null == this.diagram.UndoManager.History.NextUndo)
10. {
11. false;
12. }
13. else
14. {
15. true;
16. }
17. }
18. /// <summary>
19. /// 执行撤销命令
20. /// </summary>
21. /// <param name="sender">Command</param>
22. /// <param name="e">event arg</param>
23. private void CommandBinding_Undo_Execute(object sender, ExecutedRoutedEventArgs e)
24. {
25. this.diagram.UndoManager.Undo();
26. }
27. /// <summary>
28. /// 可否执行重做命令判断
29. /// </summary>
30. /// <param name="sender">Command</param>
31. /// <param name="e">event arg</param>
32. private void CommandBinding_Redo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
33. {
34. if (null == this.diagram.UndoManager.History.NextRedo)
35. {
36. false;
37. }
38. else
39. {
40. true;
41. }
42. }
43. /// <summary>
44. /// 执行重做命令
45. /// </summary>
46. /// <param name="sender">Command</param>
47. /// <param name="e">event arg</param>
48. private void CommandBinding_Redo_Execute(object sender, ExecutedRoutedEventArgs e)
49. {
50. this.diagram.UndoManager.Redo();
51. }
52. /// <summary>
53. /// 执行缩放命令
54. /// </summary>
55. /// <param name="sender">Command</param>
56. /// <param name="e">event arg</param>
57. private void CommandBinding_Zoom_Execute(object sender, ExecutedRoutedEventArgs e)
58. {
59. float zoomValue = float.Parse(e.Parameter.ToString());
60. this.view.ZoomFactor = zoomValue;
61. this.MenuZoomItem.Header = "缩放比例:" + zoomValue + "%"; //Hard code in here
62. }
63. #endregion
有此,可以看到,使用命令大大简化了事件和方法的书写,简单明了。
而且,WPF为我们提供了大量内置命令,包括ApplicationCommands,NavigationCommands,,MediaCommands,EditingCommands与ComponentCommands,以及控件开发人员为它们的控件也提供了很多特有的命令(比如Slider.DecreaseLarge 与 Slider.DecreaseSmall),这些足以应付平时的大多数应用,如果还不够的话,你可以为自己的应用自定义更多的命令。
自定义命令需要在后台代码里定义好命令,代码如下:
1. #region Command
2.
3. /// <summary>
4. /// 新增流程模板分类命令
5. /// </summary>
6. public static readonly RoutedUICommand AddCatalog = new RoutedUICommand();
7.
8. /// <summary>
9. /// 编辑流程模板分类命令
10. /// </summary>
11. public static readonly RoutedUICommand EditCatalog = new RoutedUICommand();
12.
13. /// <summary>
14. /// 删除流程模板分类命令
15. /// </summary>
16. public static readonly RoutedUICommand DeleteCatalog = new RoutedUICommand();
17.
18. #endregion
页面代码也有所不同,代码如下:
1. <!--命令绑定-->
2. <Window.CommandBindings>
3. for context menu commands -->
4. "local:WorkflowManagementWindow.AddCatalog"
5. "EvaluateCanAddCatalog"
6. "ExcuteAddCatalog" />
7.
8. "local:WorkflowManagementWindow.EditCatalog"
9. "EvaluateCanEditCatalog"
10. "ExcuteEditCatalog" />
11.
12. "local:WorkflowManagementWindow.DeleteCatalog"
13. "EvaluateCanDeleteCatalog"
14. "ExcuteDeleteCatalog" />
15. </Window.CommandBindings>
当然,WPF的命令系统是非常庞大和复杂的,更多的应用还需根据实际情况不断摸索。有兴趣的可以一起讨论。