Command in own class

Topics: Actions & Coroutines, Conventions
Jul 31, 2013 at 9:49 PM
On my first project trying out Caliburn.Micro, I like a lot of the things :-)

One thing I miss (or havn't discovered yet) is how to separate the viewmodel and a command.
CM doesn't support ICommand, as it's way of doing things is superior. I'm sure it's true, so I would love a small push in the right direction to achieve this or perhaps discover a better way.

As I understand you have to put the "Execute" method and "CanExecute" property directly in the viewmodel, named to match the control in the view, to get the magic to work.

I would like to put the "Execute" and "CanExecute" in a different object that is property on the viewmodel and then CM would automatically bind to that object, using the control name and property names as usually.
Sep 13, 2013 at 8:07 AM
This is actually what I am interested of as well.

Would it be correct solution to modify CM BindActions implementation in order to achieve this? Maybe have viewmodel implement an interface like IHaveActions and access those action objects from there and bind triggers to methods within those objects. Or is some other other approach better?
Sep 13, 2013 at 8:39 AM
Edited Sep 13, 2013 at 8:41 AM
I suppose you need to re-use a command in multiple places, and you don't want to repeat code, or maybe you want to keep a collection of 'commands' (like in VS) to manage them. Or you are simply happy with the ICommand implementation! :)
It all comes down to defining a class that 'replaces' ICommand, and deals with CM requirements.

Let's say this is your view-model setup:
public class MyViewModel : Screen
    public CMCommand MyCommand { get; private set; }

    //Initialization and more stuff...

public class CMCommand : PropertyChangedBase, ICommand
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public CMCommand(Action<object> execute, Predicate<object> canExecute = null)
          if (execute == null)
                throw new ArgumentNullException("execute");

          _execute = execute;
          _canExecute = canExecute;

    public bool CanExecute(object parameter)
           return _canExecute == null || _canExecute(parameter);

    public void Execute(object parameter)
         return _execute(parameter);
Now, consider a view associated to MyViewModel view-model like the one below:
<UserControl ... xmlns:cm="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro">
    <ContentControl cm:View.Model="{Binding Path=MyCommand}"/>
and a view associated to the CMCommand like this one:
    <Button x:Name="Execute"/>
The only issue with this is that CM does not provide a way to force action guard re-evaluation, in case they are defined as functions. You can use this approach to make it possible.
Note that it would be possible to define multiple views for commands, depending on the context (default, toolbar, contextmenu...).