WPF 使用自定义 RoutedUICommands 或简单的事件处理程序?

发布于 2024-07-13 23:16:32 字数 1987 浏览 12 评论 0 原文

我今天正在和某人谈论如何选择一种设计模式来处理 WPF 程序中的逻辑,并希望 SO 社区可以提供进一步的建议来帮助做出决定。 哪些因素有利于命令而不是不便?

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

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

他参加的入门课程和许多书籍都展示了简单的 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 专家,因此我可能将事情描述得比实际情况更复杂,但我怀疑您无法将事情简化得比上面的更复杂。

编辑:

我发现了一个有趣的3 DelegateCommand、RoatedCommand 和 Event 之间的方式比较

I was talking to someone today about picking a design pattern for how to handle logic in their WPF program and hoping that the SO community can help with further advice to make the decision easier. What factors in favour of commands outweigh the inconvenience?

I prepared a full sample along with some UML diagrams of the first two of three approaches:

  1. Use Click event handlers on buttons and menus.
  2. Use commands bound in XAML.
  3. Use commands bound in code, with the XAML kept for pure GUI layout and styling.

The introductory course he'd been on and many of the books show simple Click event handlers as the natural way to connect logic to UI objects.

He was a bit stunned by the amount of overhead required to use commands with both the command being created in the code behind file:

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

and then even more code in the XAML with the wordy way the command has to be identified and bound:

<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>

I can't (yet) claim to be a WPF expert so I may have painted things as more complex than they really are but my suspicion is that you can't simplify things much more than the above.

Edit:

I found an interesting 3-way comparison between DelegateCommand, RoutedCommand and Event.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

我们只是彼此的过ke 2024-07-20 23:16:32

命令各有优缺点,你要根据自己的情况来选择,
我强烈建议您根据具体情况做出选择,不要为整个项目选择“唯一正确的方法”。

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

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

Commands their advantages and disadvantages, you have to choose based on your situation,
I highly recommend you make that choice on a case basis, don't choose "the one true way" for the entire project.

For some cases the separation between sender and receiver and the ability to send commands using only XAML is a big advantage (for a good example look how the ScrollBar control template communicates with the control logic at http://msdn.microsoft.com/en-us/library/ms742173.aspx ).

In other cases commands can turn what would have been a 2 lines event handler into some impossible to follow monstrosity involving changing 4 separate places in the application (How should the ViewModel close the form? ).

ぽ尐不点ル 2024-07-20 23:16:32

唯一的原因是要熟悉命令注册表。 意味着事件很可能是私有方法,我觉得它们与窗口代码紧密结合。 同时 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}" />

The only reason is to have well know registry of commands. Means that events are likely to be private methods and I feel that they are tightly bonded to code of the window. At the same time Commands gives ability to keep implementation (event) and definition (Command) separately, you can even use another class (take a look on ApplicationCommands).

In addition, when I am doing my WPF work I use implementation of the ICommand(Command Pattern). All logic of the command goes to the Execute method. This helps me to keep separation of logic in more structured way witout overcomplication of the window code. With this option you can create commands on your model and therefore bind them witout noise. Take a look.

Create model.

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

Then assign Data Context

public MainWindow()
{

  this.DataContext = new Model();
}

And use follwing XAML code.

<Button 
    Command="{Binding CloseMessagePopupCommand}"
    Content="{StaticResource Misc.Ok}" />
轮廓§ 2024-07-20 23:16:32

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

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

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

I try to stay true to the command pattern that Mike refers to when developing WPF applications, using a combination of Andy's #2 and #3 approaches.

I can think of only one downside of commands in my view: only certain actions of certain UI elements invoke commands. One way to get around this is to have your event handler call the Execute method on a command. I think that commands provide a very good way to encapsulate execution logic. If you maintain a large piece of UI and implement it using a MVC/MVC/MVVM pattern, this becomes very apparent.

I encourage you to take a look at Dan Crevier's series on the DataModel-View-ViewModel pattern, in particular the section on Commands and Encapsulating Commands. Even if this pattern doesn't meet your needs, it gives a great overview of how you can encapsulate logic inside a separate class.

锦爱 2024-07-20 23:16:32

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

Brian Noyes 在他的有关 PRISM 的文章中说道

路由命令WPF 非常强大且有用,但是当应用于组合应用程序时它们有一些缺点。 第一个是它们完全耦合到可视化树 - 调用程序必须是可视化树的一部分,并且命令绑定必须通过可视化树绑定。 ...第二个缺点是它们与 UI 的焦点树紧密相连,接下来讨论 CAL (Prism) 包含的 DelegateCommand 和 CompositeCommand。

Other variations on ICommand seem to be a popular way to implement complex command structures.

Brian Noyes in his article on PRISM says

Routed commands in WPF are very powerful and useful, but they have some shortcomings when applied to a composite application. The first is that they are entirely coupled to the visual tree-the invoker has to be part of the visual tree, and the command binding has to be tied in through the visual tree. ... The second shortcoming is that they are tightly tied in with the focus tree of the UI and goes on to talk about the DelegateCommand and CompositeCommand which CAL (Prism) includes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文