WPF路由命令是解决问题还是使问题恶化?

时间:2009-01-21 19:45:43

标签: .net wpf routed-commands

据我所知,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 --------------|

我在这里缺少什么?它看起来像是一个额外的间接层。

4 个答案:

答案 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中执行命令,而无需使用任何代码,这对设计人员来说非常有用。