自定义WPF命令模式示例
我已经做了一些WPF编程,而我从来没有得到的是命令模式。 每个例子似乎是内置的,编辑,剪切,粘贴。 任何人都有自定义命令的最佳实践的例子或build议?
啊哈! 一个问题,我可以回答! 首先,我应该提到,我个人发现在代码中而不是在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; }
第二种方法甚至可以与其他命令共享,而不必在整个地方重复。
一旦你定义了这样的命令,你可以将它们添加到任何一个用户界面。 在下面的例子中,一旦窗口已经加载,我将命令绑定添加到Window和MenuItem,然后使用循环将input绑定添加到Window,以便为所有命令绑定执行此操作。 传递的参数是Window自身,所以上面的代码知道要尝试closures哪个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事件的事件处理程序,我build议您尽可能小和通用的命令的实际执行。 正如在这种情况下,我没有试图把代码,如果有未保存的数据,试图停止窗口closures,我把这个代码坚持在WindowClosing事件。
如果您有任何后续问题,请告诉我。 🙂
粘贴在这里:
Adam Nathan关于WPF中重要新概念的示例章节:命令
MSDN文章:WPF中的命令模式
Keyvan Nayyeri:如何将命令添加到自定义的WPF控件
Ian Griffiths:Avaloninput,命令和处理程序
维基百科:命令模式
MSDN库:指挥概述
MSDN库:CommandBinding类
MSDN Library:input和命令帮助主题
MSDN库:EditingCommands类
MSDN库:MediaCommands类
MSDN库:ApplicationCommands类
MSDN Library:NavigationCommands类
MSDN库:ComponentCommands类
也埋在WPF SDK示例中,我已经扩展了RichTextBox编辑的一个很好的示例。 你可以在这里find它: RichTextEditor.zip
在2008年9月的MSDN杂志上,Brian Noyes有一篇关于RoutedCommand / RoutedEvents的精彩文章!
这里是链接: http : //msdn.microsoft.com/en-us/magazine/cc785480.aspx
关于XAML的一点是,对于“简单”的程序来说是好的,但遗憾的是,当你想要做共享function的时候,它并不是很好。 假设你有几个类和UI的所有这些都没有被禁用的命令,你必须为每个窗口或用户控件编写一个“CanAlwaysExecute”方法! 这不是很干 。
阅读了几个博客,并尝试了几件事情之后,我select了让XAML纯粹的外观,风格,animation和触发器。 我所有的事件处理和命令挂钩现在在代码隐藏。 🙂
另一个问题是input绑定,为了让它们被捕获,焦点必须放在包含input绑定的对象上。 例如,你可以随时使用捷径(比如说F1来打开帮助),因此必须在Window对象上设置input绑定,因为当你的应用程序处于活动状态时,它始终具有焦点。 即使在开始使用UserControls时,使用代码方法也应该更容易,可能需要将input绑定添加到其父窗口。