WPF using custom RoutedUICommands or simple event handlers?
Asked Answered
N

4

5

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.

Nucleoplasm answered 17/2, 2009 at 19:13 Comment(1)
"What factors in favour of commands outweigh the inconvience?" looks like a question to me. I thought the amount of background might make it easier for people to see I'm serious and understand the context.Nucleoplasm
D
7

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? ).

Doubling answered 18/2, 2009 at 9:4 Comment(0)
C
3

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}" />
Classmate answered 17/2, 2009 at 19:42 Comment(0)
T
2

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.

Tay answered 18/2, 2009 at 3:12 Comment(0)
N
1

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.

Nucleoplasm answered 20/2, 2009 at 8:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.