Commands are used to separate the semantics and the object that invokes a command from the logic that executes the command i.e. it separates UI component from the logic that needs to be executed on command invocation. So, that you can test business logic separately using test cases and also your UI code is loosely coupled to business logic.
Now, that being said let's pick your questions one by one:
What job does it do?
I have added the details above. Hope it clears the usage of commands.
Is it usable for all commands in my form?
Some controls exposed Command DependencyProperty like Button, MenuItem etc. which have some default event registered to it. For Button it's Click
event. So, if you bind ICommand
declared in ViewModel with Button's Command DP, it will be invoked whenever button is clicked on.
For other events, you can bind using Interactivity triggers
. Refer to the sample here how to use them to bind to ICommand
in ViewModel.
How do I make the button disable when (a) certain text box(es) are not
filled in?
The link you posted doesn't provide complete implementation of RelayCommand
. It lacks the overloaded constructor to set CanExecute
predicate which plays a key role in enabling/disabling the UI control to which your command is bound to.
Bound TextBox
es with some properties in ViewModel
and in CanExecute
delegate returns false
if any of the bound properties are null
or empty which automatically disabled the control to which command is bound to.
Full implementation of RelayCommand
:
public class RelayCommand<T> : ICommand
{
#region Fields
readonly Action<T> _execute = null;
readonly Predicate<T> _canExecute = null;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
/// </summary>
/// <param name="execute">Delegate to execute when Execute is called on the command. This can be null to just hook up a CanExecute delegate.</param>
/// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
/// <summary>
/// Creates a new command.
/// </summary>
/// <param name="execute">The execution logic.</param>
/// <param name="canExecute">The execution status logic.</param>
public RelayCommand(Action<T> execute, Predicate<T> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion
#region ICommand Members
///<summary>
///Defines the method that determines whether the command can execute in its current state.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
///<returns>
///true if this command can be executed; otherwise, false.
///</returns>
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute((T)parameter);
}
///<summary>
///Occurs when changes occur that affect whether or not the command should execute.
///</summary>
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
///<summary>
///Defines the method to be called when the command is invoked.
///</summary>
///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
public void Execute(object parameter)
{
_execute((T)parameter);
}
#endregion
}
Is it useable for all commands in my form?
- What commands you are referring to here? – McinnisClick
andTextChanged
– TaunyataupeClick
you can directly bindCommand
DP of button to someICommand
in your ViewModel. But to bindTextChanged
you need to use interactivity triggers to bindICommand
in your ViewModel. – Mcinnis