Commands
Youtube Tutorials: Commands Part I and Commands Part II
Commands enable a bound method from the ViewModel to be executed from a View element, like a button. You can add an execution validation if the UI element should be shown as disabled for preventing the execution (e.g. you have to enter data first to execute a save command).
A possible implementation of a application wide Command base class could be the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using System.Windows.Input;
namespace StandUpMate.Command
{
public class DelegateCommand : ICommand
{
public Action CommandAction { get; set; }
public Func<bool> CanExecuteFunc { get; set; }
public void Execute(object parameter)
{
CommandAction();
}
public bool CanExecute(object parameter)
{
return CanExecuteFunc == null || CanExecuteFunc();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
This can be then used linke in the following example, where I want to open a settings window, but only if it is not already opened yet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <summary>
/// Shows the settings window if not opened yet.
/// </summary>
public ICommand ShowSettingsWindowCommand
{
get
{
return new DelegateCommand
{
CanExecuteFunc = () => Application.Current.MainWindow == null
|| Application.Current.MainWindow.IsActive == false,
CommandAction = () =>
{
Application.Current.MainWindow = new MainWindow();
Application.Current.MainWindow.Show();
}
};
}
}
With CanExecuteFunc
I validate if the window is already open. The CommandAction
then executes the part to open the window.
This code is from my StandUpMate project.
Commands with multiple parameters
Besides simple binding methods to View elements, you can also process multiple parameters through the command call. To achieve this you have to build a MultiValueConverter to pack the parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// Converts multiple command parameters to pass as one.
/// </summary>
public class ArrayMultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.Clone();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
This has to be referenced in your XAML code (App.xaml):
1
2
3
<Application.Resources>
<u:ArrayMultiValueConverter x:Key="ArrayMultiValueConverter" />
</Application.Resources>
Now you can send multiple parameters from UI elements with the click of a button:
This is how you access the parameters in the ViewModel: