ICommand is often used in the MVVM design pattern to allow the View to trigger business logic defined in the ViewModel. This allows for easier maintenance, unit testing, and the ability to reuse ViewModels across different UI frameworks. Examples of where a View might invoke a command include clicking a Save menu item, tapping a phone icon, or stretching an image. In these cases, the ViewModel will then invoke the business logic of saving outstanding changes, performing a phone call, or zooming into an image.
ReactiveCommand adds the concept of Input and Output generic types. The Input is often passed in by the View, and the Output is the result of executing the command. ReactiveCommand's are
IObservable<TOutput> which can be used like any other IObservable. For example, since the
IObservable<TOutput> you can
Subscribe() to it like any other observable, and add the output to a List on your view model. The
Unit type is a functional programming construct analogous to void and can be used in cases where you don't care about either the input and/or output value.
ReactiveCommand has full support for asynchronous logic and will block re-execution while executing.
ReactiveCommand guarantees the result of events are delivered to the provided
IScheduler (which defaults to the main thread scheduler). The executing logic thread safety is the user's responsibility but any result from the logic is guaranteed to arrive on the specified
ReactiveCommand is created using static factory methods which allows you to create command logic that executes either synchronously or asynchronously. The following are the different static factory methods:
CreateFromTask()- Executes a C# Task Parallel Library (TPL) Task. This allows use also of the C# async/await operators.
CreateFromObservable()- Execute the logic using an
Create()- Execute a synchronous Func or Action.
ReactiveCommand may or may not be executable in a given situation. For example, the command backing the Save menu item might be unavailable if there are no unsaved changes. We pass into the
IObservable<bool> of when the ReactiveCommand should be allowed to be executed. The
ReactiveCommand uses an IObservable eventing system to determine if execution should be allowed which differs from other frameworks where you might have the command continuous poll if execution is allowed. The ReactiveCommand approach has some performance advantages in that the value is cached between the can execute observable being fired. You commonly will create your can execute observable using the
WhenAnyValue functions provided by the ReactiveUI framework. Parameters, unlike in other frameworks, are typically not used in the canExecute conditions, instead, binding View properties to ViewModel properties and then using the WhenAnyValue() is far more common.
ReactiveCommand are fully integrated into the Reactive Extensions framework.
ReactiveCommand provides an IsExecuting property (also of type
IObservable<bool>) which tells you whether the command is currently executing. This is often useful if you want to trigger activity animations or you want to prevent other commands from executing while the command is executing.
ReactiveCommand can be connected to the View by either using XAML binding on supported platforms, or using the inbuilt ReactiveUI binding method
BindCommand. Use of BindCommand is preferred but not required where XAML binding is supported.
ReactiveCommand implements the
ICommand for UI framework compatibility and backwards compatibility only. It is recommended you don't use the
ICommand interface directly in your code.
ReactiveCommand is explicitly derived from the
ICommand interface to avoid users accidentally calling the non-reactive style methods. The
ICommand methods do not lend well to long-running and also asynchronous commands, such as those that perform I/O operations. The
ICommand also focuses on an imperative style of execution over the reactive style.
ReactiveCommand provides methods and observable properties that are the equivalent of the
Execute() provides an Observable which you can
Subscribe() to execute the logic of the
CanExecute is also exposed through a read-only property. Additionally
ReactiveCommand provides the
IsExecuting observable which is functionally not provided by the