据我所知,Command模式的目标是帮助将UI交互与应用程序逻辑分开。使用正确实现的命令,单击“打印”菜单项可能会产生如下链接:
(button) ---click executes command----> (command) ---calls Print() in app logic ---> (logic)
这鼓励您将UI与应用程序逻辑分开。
我一直在研究WPF命令,在大多数情况下,我看到他们是如何实现这种模式的。但是,我觉得他们在某种程度上已经复杂 Command模式,并设法以不鼓励将UI与应用程序逻辑分离的方式实现它。
例如,考虑这个简单的WPF窗口,它有一个按钮将文本粘贴到文本框中:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Paste"
Executed="CommandBinding_Executed"/>
</Window.CommandBindings>
<StackPanel>
<TextBox x:Name="txtData" />
<Button Command="Paste" Content="Paste" />
</StackPanel>
</Window>
以下是代码隐藏:
namespace WpfApplication1
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
ApplicationCommands.Paste.Execute(null, txtData);
}
}
}
我从命令中获得了什么?在我看来,我可以轻松地将命令绑定事件处理程序中的代码放入按钮的Click
事件中。当然,现在我可以将多个UI元素与粘贴命令相关联,我只需要使用一个事件处理程序,但是如果我想粘贴到几个不同的文本框呢?我必须使事件处理程序逻辑更复杂或编写更多的事件处理程序。所以现在,我觉得我有这个:
(button) ---executes Routed Command---> (Window) ---executes command binding----(command binding)
(logic) <---calls application logic--- (event handler) <-----raises event --------------|
我在这里缺少什么?它看起来像是一个额外的间接层。
答案 0 :(得分:3)
你可能会混淆概念。
ICommand
接口支持命令模式。这允许您将用户操作抽象为可重用的类。
路由命令是ICommand
的特定实现,它在可视化树中搜索处理程序。它们对于可以由许多不同控件实现的命令特别有用,并且您希望当前控件处理它。想想复制/粘贴。可能有一大堆控件可以处理它,但是通过使用routed命令,路由命令系统将自动找到正确的控件来处理基于焦点的命令。
答案 1 :(得分:2)
除了已经提到的内容之外,您在特定的Paste示例中忘记的是CommandTarget和CommandParameter属性。对于粘贴,您可以通过设置为CommandTarget来指定TextBox。
当想要使用来自不同控件的相同RoutedCommand时,这些属性是绝对必要的。它们允许您向Executed处理程序提供有关调用该命令的上下文的一些信息。
答案 2 :(得分:2)
我建议在构建控件时使用RoutedCommands和RoutedUICommands。例如,TextBox为您实现UndoCommand,并且Input guseture已经绑定到 Ctrl + Z 。 但是,在构建View Models时,我首选的是具有Execute和CanExecute内部实现的自定义ICommand。 DelegateCommand在Prism中提供了这个功能。这允许view / xaml设计器只担心命令而不是正确的Execute / CanExecute处理程序。这将允许更具表现力的视图模型。
PS。委托命令尚未使用InputBindings(优雅地)工作。微软的某个人可以解决这个问题!
答案 3 :(得分:0)
对于某些事情来说,它们可能有点过分,但是你确实得到了一些很好的好处,比如CanExecute,它可以在命令不可用时自动启用/禁用按钮/菜单项(例如没有选择文本等)。您也可以在Blend中执行命令,而无需使用任何代码,这对设计人员来说非常有用。