自定义WPF命令模式示例
我已经完成了一些WPF编程,而我从未获得的一件事就是命令模式。每个示例似乎都是针对内置示例,编辑,剪切,粘贴的。是否有人对自定义命令有最佳实践的示例或者建议?
解决方案
回答
啊哈!我可以回答的问题!首先,我要提到的是,我个人发现用代码而不是XAML定义和连接命令更加容易。与所有XAML方法相比,它使我能够更加灵活地连接命令的处理程序。
我们应该计算出想要拥有的命令以及与之相关的命令。在我的应用程序中,我目前有一个用于定义重要应用程序命令的类,如下所示:
public static class CommandBank { /// Command definition for Closing a window public static RoutedUICommand CloseWindow { get; private set; } /// Static private constructor, sets up all application wide commands. static CommandBank() { CloseWindow = new RoutedUICommand(); CloseWindow.InputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt)); // ... }
现在,由于我想将所有代码保持在一起,因此对Commands使用仅代码方法使我可以将以下方法放在上面的类中:
/// Closes the window provided as a parameter public static void CloseWindowExecute(object sender, ExecutedRoutedEventArgs e) { ((Window)e.Parameter).Close(); } /// Allows a Command to execute if the CommandParameter is not a null value public static void CanExecuteIfParameterIsNotNull(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = e.Parameter != null; e.Handled = true; }
那里的第二种方法甚至可以与其他Command共享,而无需我在各处重复进行。
一旦定义了这样的命令,就可以将它们添加到任何用户界面中。在下文中,一旦窗口已加载,我将命令绑定添加到Window和MenuItem,然后使用循环将输入绑定添加到Window,以对所有命令绑定执行此操作。传递的参数是Window本身,因此上面的代码知道要尝试关闭的Window。
public partial class SimpleWindow : Window { private void WindowLoaded(object sender, RoutedEventArgs e) { // ... this.CommandBindings.Add( new CommandBinding( CommandBank.CloseWindow, CommandBank.CloseWindowExecute, CommandBank.CanExecuteIfParameterIsNotNull)); foreach (CommandBinding binding in this.CommandBindings) { RoutedCommand command = (RoutedCommand)binding.Command; if (command.InputGestures.Count > 0) { foreach (InputGesture gesture in command.InputGestures) { var iBind = new InputBinding(command, gesture); iBind.CommandParameter = this; this.InputBindings.Add(iBind); } } } // menuItemExit is defined in XAML menuItemExit.Command = CommandBank.CloseWindow; menuItemExit.CommandParameter = this; // ... } // .... }
然后,我以后还会有WindowClosing和WindowClosed事件的事件处理程序,我建议我们使命令的实际实现尽可能地小而通用。在这种情况下,我没有尝试放置试图在没有保存的数据的情况下关闭窗口的代码,而是将该代码牢牢地保留在WindowClosing事件内。
如果我们有任何后续问题,请告诉我。 :)
回答
关于XAML的事情是,它对于"简单"程序来说很好,但是可悲的是,当我们要执行诸如共享功能之类的事情时,它并不能很好地工作。假设我们有多个类,并且UI的所有类都从未禁用过命令,则必须为每个Window或者UserControl编写一个" CanAlwaysExecute"方法!那不是很干。
在阅读了几篇博客并尝试了几件事之后,我选择了纯粹使XAML涉及外观,样式,动画和触发器的选择。我所有与事件处理程序和命令的联系现在都在后面的代码中。 :)
顺便提一下,另一个陷阱是Input绑定,为了使其能够被捕获,焦点必须集中在包含Input绑定的对象上。例如,要获得快捷方式,我们可以随时使用它(例如,F1打开帮助),则必须在Window对象上设置输入绑定,因为在应用程序处于活动状态时,该输入绑定始终具有焦点。即使我们开始使用可能要向其父窗口添加输入绑定的UserControl时,使用代码方法也应该使此操作更容易。
回答
去年,我在http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx上发布了有关WPF命令的大量资源以及示例。
粘贴到这里:
亚当·纳特汉斯(Adam Nathans)样本章节介绍了WPF中的重要新概念:命令
MSDN文章:WPF中的命令模式
Keyvan Nayyeri:如何将命令添加到自定义WPF控件
伊恩·格里菲思(Ian Griffiths):Avalon输入,命令和处理程序
维基百科:命令模式
MSDN库:命令概述
MSDN库:CommandBinding类
MSDN库:输入和命令方法主题
MSDN库:EditingCommands类
MSDN库:MediaCommands类
MSDN库:ApplicationCommands类
MSDN库:NavigationCommands类
MSDN库:ComponentCommands类
WPF SDK示例中也包含该示例,我扩展了RichTextBox编辑中的一个很好的示例。我们可以在这里找到它:RichTextEditor.zip
回答
在MSDN杂志的2008年9月版中,Brian Noyes撰写了一篇有关RoutedCommand / RoutedEvents的精彩文章!
链接在这里:
http://msdn.microsoft.com/zh-CN/magazine/cc785480.aspx