Learn Prism Commanding

12 minute read

Learn the Commanding section from the RRISM LIBRARY Documentation (https://prismlibrary.com/docs/commanding.html).

It’s a translation of that, but as a memo.
If you don’t speak Japanese, go back to English and understand it. .. ..

In addition to providing access to the data to be displayed or edited in the view, the ViewModel will likely define one or more actions or operations that can be performed by the user. Actions or operations that the user can perform through the UI are typically defined as commands. Commands provide a convenient way to represent actions or operations that can be easily bound to controls in the UI. They encapsulate the actual code that implements the action or operation and help to keep it decoupled from its actual visual representation in the view.
(Google Translate)
In addition to providing access to the data you view or edit in the view, the ViewModel may define one or more actions or operations that you can perform. Actions or operations that users can perform through the UI are usually defined as commands. Commands provide a convenient way to represent actions or operations that you can easily bind to controls in the UI. These help encapsulate the actual code that implements the action or operation and keep it separate from the actual visual representation in the view.

Commands can be visually represented and invoked in many different ways by the user as they interact with the view. In most cases, they are invoked as a result of a mouse click, but they can also be invoked as a result of shortcut key presses, touch gestures, or any other input events. Controls in the view are data bound to the ViewModels’s commands so that the user can invoke them using whatever input event or gesture the control defines. Interaction between the UI controls in the view and the command can be two-way. In this case, the command can be invoked as the user interacts with the UI, and the UI can be automatically enabled or disabled as the underlying command becomes enabled or disabled.
(Google Translate)
Commands can be visually represented and invoked in various ways when the user interacts with the view. Most often it is called as a result of a mouse click, but it is also called as a result of a shortcut key press, touch gesture, or other input event. Controls in a view are data bound to ViewModel commands that users can call using input events or gestures defined by the control. The interaction between the view’s UI controls and the commands is bidirectional. In this case, the command can be invoked when the user interacts with the UI, and the UI can be automatically enabled or disabled when the underlying command is enabled or disabled.

The ViewModel can implement commands as a Command Object (an object that implements the ICommand interface). The view’s interaction with the command can be defined declaratively without requiring complex event handling code in the view’s code-behind file. For example, certain controls inherently support commands and provide a Command property that can be data bound to an ICommand object provided by the ViewModel. In other cases, a command behavior can be used to associate a control with a command method or command object provided by the ViewModel.
(Google Translate)
ViewModels can implement commands as command objects (objects that implement the ICommand interface). View-command interactions can be declaratively defined without the need for complex event handling code in the view’s code-behind file. For example, certain controls essentially support commands and provide a Command property that can be data-bound to the ICommand object provided by the ViewModel. In other cases, you can use command behavior to associate a control with a command method or command object provided by the ViewModel.

Implementing the ICommand interface is straightforward. Prism provides the DelegateCommand implementation of this interface that you can readily use in your applications.
(Google Translate)
Implementing the ICommand interface is easy. Prism provides a DelegateCommand implementation of this interface that is ready to use in your application.

NOTE
DelegateCommand can be found in the Prism.Commands namespace which is located in the Prism.Core NuGet package.
(Google Translate)
Caution
DelegateCommand is located in the Prism.Commands namespace in the Prism.Core NuGet package.

Creating a DelegateCommand
image.png

The Prism DelegateCommand class encapsulates two delegates that each reference a method implemented within your ViewModel class. It implements the ICommand interface’s Execute and CanExecute methods by invoking these delegates. You specify the delegates to your ViewModel methods in the DelegateCommand class constructor. For example, the following code example shows how a DelegateCommand instance, which represents a Submit command, is constructed by specifying delegates to the OnSubmit and CanSubmit ViewModel methods. The command is then exposed to the view via a read-only property that returns a reference to the DelegateCommand.
(Google Translate)
The Prism DelegateCommand class encapsulates two delegates, each referencing a method implemented within the ViewModel class. By calling these delegates, you implement the Execute and CanExecute methods of the ICommand interface. Specify the delegate to the ViewModel method in the DelegateCommand class constructor. For example, the following code example shows how a DelegateCommand instance representing a Submit command is constructed by specifying a delegate in the OnSubmit and CanSubmit ViewModel methods. The command is then exposed to the view via a read-only property that returns a reference to the DelegateCommand.

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand<object>(Submit, CanSubmit);
    }

    void Submit(object parameter)
    {
        //implement logic
    }

    bool CanSubmit(object parameter)
    {
        return true;
    }
}

When the Execute method is called on the DelegateCommand object, it simply forwards the call to the method in your ViewModel class via the delegate that you specified in the constructor. Similarly, when the CanExecute method is called, the corresponding method in your ViewModel class is called. The delegate to the CanExecute method in the constructor is optional. If a delegate is not specified, DelegateCommand will always return true for CanExecute.

The DelegateCommand class is a generic type. The type argument specifies the type of the command parameter passed to the Execute and CanExecute methods. In the preceding example, the command parameter is of type object. A non-generic version of the DelegateCommand class is also provided by Prism for use when a command parameter is not required, and is defined as follows:
(Google Translate)
When the Execute method is called on the DelegateCommand object, the call to the method of the ViewModel class is forwarded through the delegate specified in the constructor. Similarly, when the CanExecute method is called, the corresponding method of the ViewModel class is called. Delegate to the CanExecute method of the constructor is optional. If no delegate is specified, DelegateCommand always returns true for CanExecute.

The DelegateCommand class is a generic type. The type argument specifies the type of command parameter passed to the Execute and CanExecute methods. In the above example, the command parameter type is object. A non-generic version of the DelegateCommand class is also provided by Prism for use when command parameters are not needed and is defined as follows:

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit);
    }

    void Submit()
    {
        //implement logic
    }

    bool CanSubmit()
    {
        return true;
    }
}

NOTE
The DelegateCommand deliberately prevents the use of value types (int, double, bool, etc). Because ICommand takes an object, having a value type for T would cause unexpected behavior when CanExecute(null) is called during XAML initialization for command bindings. Using default(T) was considered and rejected as a solution because the implementor would not be able to distinguish between a valid and defaulted values. If you wish to use a value type as a parameter, you must make it nullable by using DelegateCommand<Nullable> or the shorthand ? syntax (DelegateCommand<int?>). (Google Translate) Caution DelegateCommand intentionally prohibits the use of value types (int, double, bool, etc.). Because ICommand gets an object, having a value type of T causes unexpected behavior when CanExecute (null) is called during XAML initialization of the command binding. The use of default (T) was considered as a solution and rejected because the implementer cannot distinguish between valid and default values. If you use a value type as a parameter, you must use DelegateCommand <Nullable > or an abbreviation to make the value type nullable. Syntax (DelegateCommand <int?>).

Invoking DelegateCommands from the View
There are a number of ways in which a control in the view can be associated with a command object provided by the ViewModel. Certain WPF, Xamarin.Forms, and UWP controls can be easily data bound to a command object through the Command property.
(Google Translate)
There are several ways to associate a view control with the command object provided by the ViewModel. Certain WPF, Xamarin.Forms, and UWP controls can be easily data-bound to a command object using the Command property.

<Button Command="{Binding SubmitCommand}" CommandParameter="OrderId"/>

A command parameter can also be optionally defined using the CommandParameter property. The type of the expected argument is specified in the DelegateCommand generic declaration. The control will automatically invoke the target command when the user interacts with that control, and the command parameter, if provided, will be passed as the argument to the command's Execute method. In the preceding example, the button will automatically invoke the SubmitCommand when it is clicked. Additionally, if a CanExecute delegate is specified, the button will be automatically disabled if CanExecute returns false, and it will be enabled if it returns true. (Google Translate) Command parameters can also be optionally defined using the CommandParameter property. The expected argument type is specified in the DelegateCommand generic declaration. When the user interacts with the control, the control automatically calls the target command and, if command parameters are specified, is passed as an argument to the command's Execute method. In the previous example, when you click the button, SubmitCommand is called automatically. In addition, if the CanExecute delegate is specified, the button will be automatically disabled if CanExecute returns false, and the button will be enabled if it returns true.

Raising Change Notifications
The ViewModel often needs to indicate a change in the command’s CanExecute status so that any controls in the UI that are bound to the command will update their enabled status to reflect the availability of the bound command. The DelegateCommand provides several ways to send these notifications to the UI.
(Google Translate)
In many cases, the ViewModel should indicate a change in the command’s CanExecute status. This causes the UI controls bound to the command to update the valid status to reflect the availability of the bound command. DelegateCommand provides several ways to send these notifications to the UI.

RaiseCanExecuteChanged
Use the RaiseCanExecuteChanged method whenever you need to manually update the state of the bound UI elements. For example, when the IsEnabled property values changes, we are calling RaiseCanExecuteChanged in the setter of the property to notify the UI of state changes.
(Google Translate)
Whenever you need to manually update the state of a bound UI element, use the RaiseCanExecuteChanged method. For example, when the value of the IsEnabled property changes, the property setter calls RaiseCanExecuteChanged to notify the UI of the state change.

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                SetProperty(ref _isEnabled, value);
                SubmitCommand.RaiseCanExecuteChanged();
            }
        }

ObservesProperty
In cases where the command should send notifications when a property value changes, you can use the ObservesProperty method. When using the ObservesProperty method, whenever the value of the supplied property changes, the DelegateCommand will automatically call RaiseCanExecuteChanged to notify the UI of state changes.
(Google Translate)
If the command needs to send a notification when the property value changes, you can use the ObservesProperty method. When using the ObservesProperty method, the DelegateCommand automatically calls RaiseCanExecuteChanged to notify the UI of the state change when the value of the provided property changes.

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit, CanSubmit).ObservesProperty(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }

    bool CanSubmit()
    {
        return IsEnabled;
    }
}

NOTE
You can chain-register multiple properties for observation when using the ObservesProperty method. Example: ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave).
(Google Translate)
Caution
You can use the ObservesProperty method to chain and monitor multiple properties. Example: ObservesProperty (() => IsEnabled) .ObservesProperty (() => CanSave).

ObservesCanExecute
If your CanExecute is the result of a simple Boolean property, you can eliminate the need to declare a CanExecute delegate, and use the ObservesCanExecute method instead. ObservesCanExecute will not only send notifications to the UI when the registered property value changes but it will also use that same property as the actual CanExecute delegate.
(Google Translate)
If CanExecute is the result of a simple Boolean property, you can eliminate the need to declare a CanExecute delegate and use the ObservesCanExecute method instead. ObservesCanExecute not only sends a notification to the UI when the registered property value changes, but also uses the same properties as the actual CanExecute delegate.

public class ArticleViewModel : BindableBase
{
    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set { SetProperty(ref _isEnabled, value); }
    }

    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit).ObservesCanExecute(() => IsEnabled);
    }

    void Submit()
    {
        //implement logic
    }
}

WARNING
Do not attempt to chain-register ObservesCanExecute methods. Only one property can be observed for the CanExcute delegate.
(Google Translate)
warning
Do not chain the ObservesCanExecute method. The CanExcute delegate can only monitor one property.

Implementing a Task-Based DelegateCommand
In today’s world of async/await, calling asynchronous methods inside of the Execute delegate is a very common requirement. Everyone’s first instinct is that they need an AsyncCommand, but that assumption is wrong. ICommand by nature is synchronous, and the Execute and CanExecute delegates should be considered events. This means that async void is a perfectly valid syntax to use for commands. There are two approaches to using async methods with DelegateCommand.
(Google Translate)
In today’s asynchronous / wait world, calling asynchronous methods within an execution delegate is a very common requirement. Everyone’s first instinct is that they need an AsyncCommand, but that assumption is wrong. ICommand is essentially synchronous, and the Execute and CanExecute delegates are considered events. In other words, async void is a perfectly valid syntax to use for commands. There are two ways to use asynchronous methods with DelegateCommand.

Option 1:

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(Submit);
    }

    async void Submit()
    {
        await SomeAsyncMethod();
    }
}

Option 2:

public class ArticleViewModel
{
    public DelegateCommand SubmitCommand { get; private set; }

    public ArticleViewModel()
    {
        SubmitCommand = new DelegateCommand(async ()=> await Submit());
    }

    Task Submit()
    {
        return SomeAsyncMethod();
    }
}