7

I bet this has been answered many times over, but...

For a simple situation where a button on a UserControl has its command property set to something like Find (ApplicationCommands.Find) how would the ViewModel handle that command? I usually see command handlers wired up with a CommandBinding that gets added to a CommandBindings collection on a UIElement, but my ViewModel doesn't derive from UIElement (should it?). The commands themselves don't expose events to notify when they've been executed, so where should I wire up to get that information?

EDIT: I'd like to use stock WPF to solve the problem if possible. I know there are many available frameworks for this sort of thing but would like to keep the code simple.

EDIT2: Including some sample code.

<UserControl>
  <UserControl.DataContext>
    <local:MyViewModel/>
  </UserControl.DataContext>

  <Button Command="Find"/>
</UserControl>

Where:

class MyViewModel
{
  // Handle commands from the view here.
}

I could add a CommandBinding to the UserControl which would handle Executed, then call a hypothetical Find method in MyViewModel which does the actual work, but that's extra and unnecessary code. I'd prefer if the ViewModel itself handled the Find command. One possible solution would be to have MyViewModel derive from UIElement however that seems counter intuitive.

James Cadd
  • 12,136
  • 30
  • 85
  • 134

1 Answers1

4

The purpose of commands is to decouple the code which generates the order from the code which executes it. Therefore: if you want tight coupling, you should better do it through events:

<UserControl ... x:Class="myclass">
    ...
    <Button Click="myclass_find" .../>
    ...
</UserControl>

For loose coupling you need to add a CommandBinding to your UserControl:

<UserControl ... >
    <UserControl.DataContext>
        <local:MyViewModel/>
    </UserControl.DataContext>

    <UserControl.CommandBindings>
        <Binding Path="myFindCommandBindingInMyViewModel"/>
    </UserControl.CommandBindings>
    ...
    <Button Command="ApplicationComamnd.Find" .../>
    ...
</UserControl>

(not sure about the syntax)

Or you can add a CommandBinding to your UserControl's CommandBindings in the constructor, taking the value from the ViewNodel:

partial class MyUserControl : UserControl
{
    public MyUSerControl()
    {
        InitializeComponent();
        CommandBinding findCommandBinding = 
                  ((MyViewModel)this.DataContext).myFindCommandBindingInMyViewModel;
        this.CommandBindings.Add(findCommandBinding);
    }
}
Vlad
  • 35,022
  • 6
  • 77
  • 199
  • I'd prefer loose coupling so I'm looking for an answer that shows how to handle the command in a class separate from the UserControl. – James Cadd Feb 24 '10 at 18:43
  • do you want to process `ApplicationCommands.Find` the same way for all sources? – Vlad Feb 24 '10 at 19:11
  • Added some code to clarify where I want to handle the command execution - I'd like to handle the commands in the ViewModel, not in the UserControl itself in keeping with the general MVVM philosophy. – James Cadd Feb 24 '10 at 19:44
  • My purpose is to get advantage of all the InputGestures in the ApplicationCommands. Is there a cleaner way to port the ApplicationCommands to the VM commands? – Shimmy Weitzhandler Jun 29 '11 at 08:55
  • @Shimmy: why do you need to port them? There shouldn't be any big difference between the predefined `ApplicationCommands` and the commands which you implement yourself. – Vlad Jun 29 '11 at 11:03
  • I know, but I want to get advantage of both RoutedCommand and DelegateCommand, whatever. I decided to use DelegateCommand and set my gestures on it. – Shimmy Weitzhandler Jun 29 '11 at 11:09