Commands

Commands

ReactiveCommand is a Reactive Extensions and asynchronous aware implementation of the ICommand interface.

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 ReactiveCommand is 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 IScheduler.

A 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 IObservable.
  • Create() - Execute a synchronous Func or Action.

A 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 ReactiveCommand an 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 ICommand interface. Execute() provides an Observable which you can Subscribe() to execute the logic of the ReactiveCommand and CanExecute is also exposed through a read-only property. Additionally ReactiveCommand provides the IsExecuting observable which is functionally not provided by the ICommand interface.