5

今天我正在和某人谈论如何选择一种设计模式来处理他们的 WPF 程序中的逻辑,并希望 SO 社区可以提供进一步的建议以使决策更容易。哪些因素有利于命令胜过不便?

我准备了一个完整的示例以及三种方法中前两种的一些UML 图:

  1. 在按钮和菜单上使用 Click 事件处理程序。
  2. 使用 XAML 中绑定的命令。
  3. 使用代码中绑定的命令,并为纯 GUI 布局和样式保留 XAML。

他参加的入门课程和许多书籍都将简单的 Click 事件处理程序作为将逻辑连接到 UI 对象的自然方式。

他对使用命令所需的开销量感到有些震惊,而命令是在代码隐藏文件中创建的:

public static readonly ICommand cmdShow2 = new RoutedUICommand(
  "Show Window2", "cmdShow2", 
  typeof(TestDespatchWindow));

然后是 XAML 中的更多代码,必须以冗长的方式识别和绑定命令:

<Window x:Class="WPFDispatchDemo.TestDespatchWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:w="clr-namespace:WPFDispatchDemo"..>

    <Window.CommandBindings>
      <CommandBinding Command="{x:Static w:TestDespatchWindow.cmdShow2}"
        Executed="OnShow2" />
    </Window.CommandBindings>
      <DockPanel>
        <StackPanel Margin="0,8,0,0">
          <Button x:Name="Show2EventBased" 
                  Margin="10,2,10,2" 
                  Click="OnShow2" 
                  Content="Show2 via WPF Event"/>
          <Button x:Name="Show2Command" 
                  Command="{x:Static w:TestDespatchWindow.cmdShow2}"
                  Margin="10,2,10,2" 
                  Content="Show2 via WPF"/>
        </StackPanel>
    </DockPanel>
  </Window>

我(还)不能声称自己是 WPF 专家,所以我可能把事情画得比实际更复杂,但我怀疑你不能比上面更简单地简化事情。

编辑:

我在 DelegateCommand、RoutedCommand 和 Event 之间发现了一个有趣的3 路比较。

4

4 回答 4

6

掌握它们的优缺点,你要根据自己的情况来选择,我强烈建议你根据具体情况做出选择,不要为整个项目选择“一成不变的方式”。

在某些情况下,发送者和接收者之间的分离以及仅使用 XAML 发送命令的能力是一个很大的优势(作为一个很好的示例,请查看 ScrollBar 控件模板如何与http://msdn.microsoft.com/en上的控制逻辑进行通信-us/library/ms742173.aspx)。

在其他情况下,命令可以将原本是 2 行的事件处理程序变成一些不可能遵循的怪物,涉及更改应用程序中的 4 个不同位置(ViewModel 应该如何关闭表单?)。

于 2009-02-18T09:04:25.863 回答
3

唯一的原因是要熟悉命令注册表。意味着事件可能是私有方法,我觉得它们与窗口的代码紧密结合。同时,Commands 提供了将实现(事件)和定义(命令)分开的能力,你甚至可以使用另一个类(看看 ApplicationCommands)。

此外,当我做我的 WPF 工作时,我使用 ICommand(命令模式) 的实现。该命令的所有逻辑都转到 Execute 方法。这有助于我以更结构化的方式保持逻辑分离,而不会过度复杂化窗口代码。使用此选项,您可以在模型上创建命令,从而在没有噪音的情况下绑定它们。看一看。

创建模型。

public class Model
{
  ICommand CloseMessagePopupCommand {get; set;}
}

然后分配数据上下文

public MainWindow()
{

  this.DataContext = new Model();
}

并使用以下 XAML 代码。

<Button 
    Command="{Binding CloseMessagePopupCommand}"
    Content="{StaticResource Misc.Ok}" />
于 2009-02-17T19:42:10.190 回答
2

在开发 WPF 应用程序时,我尝试忠实于 Mike 在开发 WPF 应用程序时提到的命令模式,并结合使用了 Andy 的 #2 和 #3 方法。

在我看来,我只能想到命令的一个缺点:只有某些 UI 元素的某些操作会调用命令。解决此问题的一种方法是让您的事件处理程序在命令上调用 Execute 方法。我认为命令提供了一种非常好的封装执行逻辑的方法。如果您维护一大块 UI 并使用 MVC/MVC/MVVM 模式实现它,这将变得非常明显。

我鼓励您查看 Dan Crevier 关于DataModel-View-ViewModel模式的系列,特别是关于命令和封装命令的部分。即使这种模式不能满足您的需求,它也很好地概述了如何将逻辑封装在一个单独的类中。

于 2009-02-18T03:12:24.057 回答
1

ICommand 的其他变体似乎是实现复杂命令结构的流行方式。

Brian Noyes 在他关于 PRISM 的文章中

WPF 中的路由命令非常强大和有用,但是在应用于复合应用程序时它们存在一些缺点。首先是它们与可视树完全耦合——调用者必须是可视树的一部分,并且命令绑定必须通过可视树绑定。...第二个缺点是它们与UI的焦点树紧密相关,并继续谈论CAL(Prism)包含的DelegateCommand和CompositeCommand。

于 2009-02-20T08:01:01.583 回答