Reputation: 9232
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,
Upvotes: 4
Views: 5196
Reputation: 8882
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.
Upvotes: 4
Reputation: 9232
I have ended up answering my own question through the following post, http://www.codeproject.com/KB/WPF/CentralizingWPFCommands.aspx?display=Print
Upvotes: 0
Reputation: 17272
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.
Upvotes: 1