Cameron MacFarland
Cameron MacFarland

Reputation: 71856

UI access from ReactiveAsyncCommand

I want to register an async command that opens a file and processes it.

OpenFileCommand = new ReactiveAsyncCommand();
OpenFileCommand.RegisterAsyncAction(_ =>
{
    var path = GetOpenFilePath(); // This needs to be on the UI thread
    if (String.IsNullOrEmpty(path))
        return;

    ProcessFile(path);
});

Similar to this question

Asynchronous command execution with user confirmation

But I'm not sure how to apply that answer here. I need to pass the path value to the processor.

How would I do this?

Upvotes: 1

Views: 563

Answers (1)

Ana Betts
Ana Betts

Reputation: 74654

The hack way is to create OpenFileCommand in the ViewModel but call RegisterAsyncAction in the View, which is kind of gross.

Another thing you can do would be to inject an interface into the ViewModel that represents the common file dialog (i.e. the open file chooser). This is great from a testing perspective because you can simulate the user doing various things. I'd model it as:

public interface IFileChooserUI
{
    // OnError's if the user hits cancel, otherwise returns one item
    // and OnCompletes
    IObservable<string> GetOpenFilePath();
}

Now, your async command becomes:

OpenFileCommand.RegisterAsyncObservable(_ => 
    fileChooser.GetOpenFilePath()
        .SelectMany(x => Observable.Start(() => ProcessFile(x))));

Or if you want to rock the awaits (which if you're using RxUI 4.x and VS2012, you can):

OpenFileCommand.RegisterAsyncTask(async _ => {
    var path = await fileChooser.GetOpenFilePath();
    await Task.Run(() => ProcessFile(path));
});

Upvotes: 3

Related Questions