4

Ok, so I'm trying to grasp the concept of WPF Commands. They seem pretty straightforward, until you try to forward the command to something that's not the XAML's code behind. I've seen several ways to do this with custom commands, but no straightforward explanation of how to do this with the built in WPF commands. Things like "Open", "save", "cut", etc.

Is there a simple way, using the RelayCommand class or something else, to forward the Open command to my ViewModel?

4 Answers 4

6

WPF's built-in ApplicationCommands and the like were not originally designed with MVVM in mind, so they don't really match up when you try to put them in the ViewModel.

In WPF 4 it is now possible to bind InputCommands to your ViewModel:

https://www.thomaslevesque.com/2009/10/26/vs2010-binding-support-in-inputbindings/

An alternative is to use a DelegateCommands, which you can implement on your own or get from a library like Prism. You can define the DelegateCommand as an object in your viewmodel and bind to it from your view.

Once you have the binding working you define what the command does in your viewmodel code.

Sign up to request clarification or add additional context in comments.

3 Comments

I'm guessing that using either of these doesn't give me the keybindings for free.
I believe you can bind a KeyBinding to a command in your viewmodel, but to be honest I've only ever used DelegateCommand, so I can't give you a more complete example.
3

If you're doing MVVM with WPF, I would strongly recommend looking at a framework to help you out, such as:

  1. Prism (provides its own DelegateCommand)
  2. MVVM Light Toolkit (provides its own RelayCommand)
  3. Caliburn.Micro (my favourite, provides Actions)

Comments

1

One way is to use an attached property to allow your ViewModel to define CommandBindings on the view. Check my blog post for details:

CommandBindings with MVVM

Comments

0

Suppose your ViewModel exposes a New command. You can re-route Application.New command binding to the VM with code like this. In XAML:

<Window.CommandBindings>
    <CommandBinding Command="New" />
    ...
</Window.CommandBindings>

Then in code you can do something like this. (I like to keep code out of the code behind, so I house this in a utility class.)

foreach (CommandBinding cb in CommandBindings)
{
    switch (((RoutedUICommand)cb.Command).Name)
    {
        case "New":
            cb.Executed += (sender, e) => ViewModel.New.Execute(e);
            cb.CanExecute += (sender, e) => e.CanExecute = ViewModel.New.CanExecute(e);
            break;
    }
}

The anonymous methods provide a thunk between RoutedUICommand and ICommand.

EDIT: Alternatively, it's considered a best practice to set the command binding explicitly with the CommandManager rather than adding handlers.

CommandManager.RegisterClassCommandBinding(typeof(MainWindow),
    new CommandBinding(ApplicationCommands.New,
        (sender, e) => ViewModel.NewScore.Execute(e),
        (sender, e) => e.CanExecute = ViewModel.NewScore.CanExecute(e)));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.