我已经完成了一些WPF编程,而我从未得到的一件事就是命令模式。每个例子似乎都是内置的,编辑,剪切,粘贴。任何人都有自定义命令的最佳实践示例或建议吗?
答案 0 :(得分:38)
您应该确定要拥有的命令及其相关内容。在我的应用程序中,我目前有一个用于定义重要应用程序命令的类,如下所示:
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));
// ...
}
现在,因为我想将代码保持在一起,使用仅代码方法来命令,我可以在上面的类中使用以下方法:
/// 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;
}
第二种方法甚至可以与其他命令共享,而不必在整个地方重复它。
一旦定义了这样的命令,就可以将它们添加到任何UI中。在下面,一旦Window已加载,我将命令绑定添加到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事件提供了事件处理程序,我建议你尽可能地使命令的实际执行尽可能小。在这种情况下,如果有未保存的数据,我没有尝试将试图阻止Window关闭的代码,我将该代码牢牢地保存在WindowClosing事件中。
如果您有任何后续问题,请与我们联系。 :)
答案 1 :(得分:7)
去年我在http://blogs.vertigo.com/personal/alanl/Blog/archive/2007/05/31/commands-in-wpf.aspx
上写了一篇关于WPF命令的大量资源以及一个例子。在这里粘贴:
Adam Nathan’s sample chapter on Important New Concepts in WPF: Commands
MSDN article: The Command Pattern In WPF
Keyvan Nayyeri: How to Add Commands to Custom WPF Control
Ian Griffiths: Avalon Input, Commands, and Handlers
MSDN Library: Commanding Overview
MSDN Library: CommandBinding Class
MSDN Library: Input and Commands How-to Topics
MSDN Library: EditingCommands Class
MSDN Library: MediaCommands Class
MSDN Library: ApplicationCommands Class
MSDN Library: NavigationCommands Class
MSDN Library: ComponentCommands Class
同样埋藏在WPF SDK示例中,我已经扩展了RichTextBox编辑的一个很好的示例。您可以在此处找到它:RichTextEditor.zip
答案 2 :(得分:4)
在2008年9月的MSDN杂志中,Brian Noyes有一篇关于RoutedCommand / RoutedEvents的优秀文章!!!
这是链接: http://msdn.microsoft.com/en-us/magazine/cc785480.aspx
答案 3 :(得分:3)
关于XAML的事情是它对于“简单”程序来说很好,但遗憾的是,当你想做共享函数之类的事情时,它不能正常工作。假设您有几个类和UI,其中所有的命令都从未被禁用,您必须为每个Window或UserControl编写一个'CanAlwaysExecute'方法!那不是 DRY 。
阅读了几篇博客并尝试了几件事,我已经选择将XAML纯粹用于外观,样式,动画和触发器。所有我对事件处理程序和命令的挂钩现在都落后于代码隐藏。 :)
顺便说一下,另一个问题是输入绑定,为了捕获它们,焦点必须放在包含Input绑定的对象上。例如,要在任何时候使用快捷方式(例如,F1打开帮助),必须在Window对象上设置输入绑定,因为当您的应用处于活动状态时,它始终具有焦点。即使您开始使用可能希望将输入绑定添加到其父窗口的UserControls,使用代码方法也应该更容易。