4

I am working ona WPF application that has a toolbar/menu that will have the use for several custom commands. Probably around 15-20. I have seen documentation on how to create custom commands, but none of them necessarily apply to what I am trying to do.

I am using a controller to handle the business logic in my application, and I am trying to keep my view from doing any logic at all.

What I would like to do is create a directory in my project that holds the custom command classes so that I can decouple them from the controller and the view, but I would still like them to be called from the view such as a normal commmand is.

I have also seen the use of a DelegateCommand class, but am not quite sure if that is the direction I want to head in.

I would like to be able to have an arbitrary custom command class such as the following

public CustomCommand: ICommandd
{
    public bool CanExecute(object parameter)
    {
        //arbitrary logic
    }

    public void Execute(object parameter)
    {

    }
}

The idea is that I would have 10-20 of these, and I want to keep them separate from everything else, and have them be called when needed.

I know that there is a way I can separate my custom commands, but am not quite sure.

I am new to using commands, so I still am trying to get a hold of the concept.

thanks,

1

2 Answers 2

4

The concept is you bind a command to a button and the command drives two properties of this button: "on click" and "enabled" resulting in the interface you posted.

The main reason you want to do commanding is to be able to bind button clicks to actions in your view model.

If you create one custom command which takes an action as constructor parameter you can wire methods from your view model directly to your command.

public class RelayCommand: ICommandd
{
    Action action;
    Func<bool> canExecute;

    public RelayCommand(Action action) : this(action, () => true) {}
    public RelayCommand(Action action, Func<bool> canExecute) 
    { 
        this.action = action; 
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return canExecute();
    }

    public void Execute(object parameter)
    {
        action();
    }
}

Usage in your view model would be

public RelayCommand SaveCommand { get; set; }

SaveCommand = new RelayCommand(OnSave);

public void Save()
{
    // save logic...
}

If you want to wire CanExecute, too you can use the second ctor and provide a CanSave Method.

public RelayCommand SaveCommand { get; set; }

SaveCommand = new RelayCommand(OnSave, CanSave);

public void Save()
{
    // save logic...
}

public bool CanSave()
{
    return // ... 
}

As you may noticed I dropped the command parameter in my implementation. This will be sufficient in most cases and saves you extra parameters in your handler methods. For the 10% left I implemented a RelayCommand<T> which takes an Action instead of Action and changes the Execute method to

    public void Execute(object parameter)
    {
        action((T)parameter);
    }

which requires a parameterized handler

SaveCommand = new RelayCommand<SomeType>(OnSave);

public void Save(SomeType toSave)
{
    // save logic using parameter
}

This saves you all casting issues you encounter when using object variables and keeps your view models type safe.

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

2 Comments

This is indeed a very helpful way of doing commands, especially for a M-V-VM architecture, but unfortunately this is not quite what I am looking for, if you read above, I am actually looking to separate all the logic out of my view, I have specific reasons for doing this, I actually found what I was looking for here codeproject.com/KB/WPF/… - Upvote for your great example though, thanks!
Even if you want to provide your commands through a static class I would recommend using RelayCommands. This way you won't need any code behind code for your xaml file and _DeleteContact = new RoutedUICommand("Delete an existing contact", "DeleteContact", typeof(MyAppCommands)); contains hardcoded strings which may change and hinder refactoring. I would be interested in your use case. Why do you want to put all commands into one static class?
1

Use RelayCommand, it doesn't require you to create a class for each command, you simply add both methods into the constructor as lambda expressions/delegates.

I use it all around my projects, it is a real time-saver.

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.