How do I make a direct call to ReactiveCommand.Execute() in ReactiveUI 7 correct?
Asked Answered
R

1

10

I'm trying to convert my project from ReactiveUI 6.5 to version 7. In the old version I called

// var command = ReactiveCommand.Create...;
// ...
if(command.CanExecute(null))
    command.Execute(null);

in order to execute a command from my code behind.

Now the CanExecute method is no longer available and replaced with a property of IObservable<bool>. Is the CanExecute Observable automatically called if I just make a call to Execute().Subscribe() or must I call it explicitly?

For now I replaced the above code with

command.Execute().Subscribe();
Reticulum answered 29/11, 2016 at 9:21 Comment(0)
R
21

I found three different solutions to call my command's CanExecute and Execute methods like I could before in ReactiveUI 6.5:

Option 1

This is equal to the call in version 6.5, but we need to explicitly convert the command to an ICommand:

if (((ICommand) command).CanExecute(null))
    command.Execute().Subscribe();

Option 2

if(command.CanExecute.FirstAsync().Wait())
    command.Execute().Subscribe()

or the async variant:

if(await command.CanExecute.FirstAsync())
    await command.Execute()

Option 3

Another option is to make us of the InvokeCommand extension method.

Observable.Start(() => {}).InvokeCommand(ViewModel, vm => vm.MyCommand);

This respects the command's executability, like mentioned in the documentation.


In order to make it more comfortable I've written a small extension method to provide a ExecuteIfPossible and a GetCanExecute method:

public static class ReactiveUiExtensions
{
    public static IObservable<bool> ExecuteIfPossible<TParam, TResult>(this ReactiveCommand<TParam, TResult> cmd) =>
        cmd.CanExecute.FirstAsync().Where(can => can).Do(async _ => await cmd.Execute());

    public static bool GetCanExecute<TParam, TResult>(this ReactiveCommand<TParam, TResult> cmd) =>
        cmd.CanExecute.FirstAsync().Wait();
}

You can use this extension method as follows:

command.ExecuteIfPossible().Subscribe();

Note: You need the Subscribe() call at the end, just like you need it for the call to Execute(), otherwise nothing will happen.

Or if you want to use async and await:

await command.ExecuteIfPossible();

If you want to check if a command can be executed, just call

command.GetCanExecute()
Reticulum answered 29/11, 2016 at 16:17 Comment(1)
Thanks for figuring out work arounds for CanExecute(null) when upgrading from 6.5.Iasis

© 2022 - 2024 — McMap. All rights reserved.