Manually executing a command in ReactiveUI 7.2
Asked Answered
B

3

5

I'm trying to execute a command so that a function I have runs asynchronously in from within the constructor of my view. I understand that running something asynchronously in a constructor isn't necessarily good practice, but I need to load a datagrid when the view opens which takes anywhere from 3-5 seconds, so I thought I could load a progress bar with an IsLoading property while my command to fetch the data runs on a separate thread.

Here is my command / property declaration to do the above:

public ReactiveCommand EnterCmd { get; private set; }
ObservableAsPropertyHelper<bool> _isLoading;
public bool IsLoading => _isLoading.Value;

And here are my instantiations in the constructor:

EnterCmd = ReactiveCommand.CreateFromTask(LoadGridData);
EnterCmd.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading);

I'd like to run start my command by doing something like EnterCmd.Execute(). It's worth noting that I did find a similar question here, but Execute() doesn't seem to be a valid method on a ReactiveCommand anymore. Any ideas would be appreciated.

Brahmi answered 3/5, 2017 at 1:14 Comment(0)
W
6

In addition to Jon's answer, you need to ensure you're accessing a ReactiveCommand<TParam, TResult>, not just ReactiveCommand (which is a base class that has no notion of execution).

So make sure your EnterCmd property is of the correct type, such as ReactiveCommand<Unit, Unit>.

Waneta answered 3/5, 2017 at 5:44 Comment(2)
Out of curiosity, what is a Unit? I can't seem to find solid documentation on it.Brahmi
@Brahmi it's basically a voidQuincey
G
14

The Exexute() method was changed in version 7. It now returns an observable, so you need to subscribe to it for it to work:

EnterCmd.Execute().Subscribe();
Gradualism answered 3/5, 2017 at 2:53 Comment(1)
I needed to add <Unit, Unit> at the end of my command declaration so that Execute() became available to my command type, that's why I made Kent's answer the correct one. I up-voted yours, however, as it still helped me get the rest of the way there. Thanks!Brahmi
S
7

Another way to accomplish the same is to call commands using the method InvokeCommand.

You can find more information on how to use it in the following link: Invoking Commands

Also one thing is also recommended in ReactiveUI is not to execute commands in the constructor (not good test design). Instead, try to call the command from the View like this:

this.WhenActivated(disposables =>
{
    this.WhenAnyValue(view => view.ViewModel.LoadData)
        .Select(cmd => Unit.Default)
        .InvokeCommand(this.ViewModel.LoadData)
        .DisposeWith(disposables);                     
});

You can find more information about this topic here

Hope this helps

Suspicious answered 3/5, 2017 at 9:28 Comment(1)
I'll give this a try. Thanks for the tip!Brahmi
W
6

In addition to Jon's answer, you need to ensure you're accessing a ReactiveCommand<TParam, TResult>, not just ReactiveCommand (which is a base class that has no notion of execution).

So make sure your EnterCmd property is of the correct type, such as ReactiveCommand<Unit, Unit>.

Waneta answered 3/5, 2017 at 5:44 Comment(2)
Out of curiosity, what is a Unit? I can't seem to find solid documentation on it.Brahmi
@Brahmi it's basically a voidQuincey

© 2022 - 2024 — McMap. All rights reserved.