Commanding with C1Toolbar (WPF Tutorial) > Part 3: Using Commands in MVVM |
Commanding is an essential part of the MVVM (Model-View-ViewModel) design pattern where the separation of UI from business logic is key. Toolbar for WPF supports the command framework and can be used with the popular MVVM pattern. In MVVM-designed applications, command targets are often implemented in the ViewModel, which are not part of the UI element tree. Therefore, the RoutedCommand is not a good implementation of ICommand to use in MVVM. You should use a special implementation such as DelegateCommand or RelayCommand, which enables your View to bind to objects that are not part of the UI element tree.
The following steps show how to create the same custom command implemented in Part 2 using the RelayCommand class and C1Toolbar.
C# |
Copy Code
|
---|---|
class MainViewModel : System.ComponentModel.INotifyPropertyChanged { private string textValue = ""; public string TextValue { get { return textValue; } set { textValue = value; OnPropertyChanged("TextValue"); } } private RelayCommand clearCommand; public ICommand ClearCommand { get { if (clearCommand == null) { clearCommand = new RelayCommand(param => this.Clear(), param => this.CanClear()); } return clearCommand; } } private bool CanClear() { return textValue.Length > 0; } private void Clear() { TextValue = ""; } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } |
This class uses the RelayCommand, which is a lightweight variation of the DelegateCommand. Both ICommand implementations allow you to delegate commanding logic to methods passed as parameters with command targets that are not part of the UI element tree. The RelayCommand and DelegateCommand classes are not part of the WPF framework and can be found online and with various MVVM toolkits.
C# |
Copy Code
|
---|---|
/// <summary> /// This class allows delegating the commanding logic to methods passed as parameters, /// and enables a View to bind commands to objects that are not part of the element tree. /// </summary> public class RelayCommand : ICommand { #region Fields readonly Action<object> _execute; readonly Predicate<object> _canExecute; #endregion // Fields #region Constructors public RelayCommand(Action<object> execute) : this(execute, null) { } public RelayCommand(Action<object> execute, Predicate<object> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion // Constructors #region ICommand Members [DebuggerStepThrough] public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(parameter); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void Execute(object parameter) { _execute(parameter); } #endregion // ICommand Members } |
XAML |
Copy Code
|
---|---|
<Window.Resources> <local:MainViewModel x:Key="viewModel" /> </Window.Resources> <Window.DataContext> <Binding Source="{StaticResource viewModel}"/> </Window.DataContext> |
This adds your ViewModel as a resource which is then bound to the DataContext of the Window or UserControl.
XAML |
Copy Code
|
---|---|
<c1:C1ToolbarGroup Header="Application"> <c1:C1ToolbarButton LabelTitle="Clear Text" Command="{Binding ClearCommand}" LargeImageSource="/Resources/delete.png"/> </c1:C1ToolbarGroup> |
This toolbar group contains one C1ToolbarButton with its Command property bound to the ClearCommand defined in the ViewModel.
XAML |
Copy Code
|
---|---|
<TextBox Grid.Row="1" Text="{Binding TextValue, UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left" Margin="12,17,0,0" Name="textBox1" VerticalAlignment="Top" Width="165" /> |
By setting the UpdateSourceTrigger to PropertyChanged, the TextValue property on the ViewModel will be updated any time there is a change in Text value, as opposed to only when the TextBox loses focus.
There are many benefits that you get by following the MVVM design pattern due to the loose coupling of UI from business logic.