ReactiveUI:使用ReactiveCommand.CreateFromObservable()时,UI不会更新,直到命令完成

时间:2016-12-15 19:26:52

标签: reactiveui

我正在使用带有WPF和.NET 4.5.2的ReactiveUI 7.0。

我试图从Observable创建一个ReactiveCommand。代码可以工作,但是UI在命令完成之前不会更新。我有一个进度条和一个进度窗口,我想在命令运行时更新它。此外,在ReactiveCommand执行时,UI没有响应(我无法点击取消按钮或其他任何内容)。我希望这是我忽略的东西,对于比我聪明的人来说显而易见。或者我可能只是做错了。

感谢您的光临。

以下是相关代码:

我的ViewModel声明:

public ReactiveCommand<Unit, string> PerformSelectedOperationCommand { get; set; }

private StringBuilder sb;

在我的ViewModel构造函数中:

PerformSelectedOperationCommand = ReactiveCommand.CreateFromObservable(PerformOperationObservable,
            this.WhenAnyValue(x => x.SelectedPath, x => x.TotalFilesSelected,
                (x, y) => x != null && y > 0));

    // listen to the messages and append to output
    PerformSelectedOperationCommand.Subscribe(s =>
    {
        sb.AppendLine(s);
        ProgressWindowOutput = sb.ToString();
    });

这是我的ViewModel中包含的Observable,它在单击Go按钮时运行(注意它正在修改我的ViewModel的属性):

private IObservable<string> PerformOperationObservable()
    {
        sb.Clear();
        return Observable.Create<string>((o) =>
        {
            using (cts = new CancellationTokenSource())
            {
                // this creates a copy of the file list which will keep us safe
                // if the user is clicking around on the UI and changing the list.
                var selectedFiles = FileList.Where(x => x.IsChecked).ToArray();
                int total = selectedFiles.Length;
                int count = 0;
                foreach (var file in selectedFiles)
                {
                    ProgressBarMessage = $"Processing {count + 1} of {total}";
                    o.OnNext($"Processing file {file.Name}");
                    SelectedFileOperation.PerformOperation(file.FullPath);
                    count++;
                    PercentComplete = (int)(((double)count / total) * 100);
                    if (cts.IsCancellationRequested)
                    {
                        PercentComplete = 0;
                        ProgressBarMessage = string.Empty;
                        break;
                    }
                }
                ProgressBarMessage = string.Empty;
            }
            o.OnCompleted();
            return Disposable.Empty;
        });
    }

1 个答案:

答案 0 :(得分:1)

Observable本质上是单线程的,您需要指定工作的位置。你可以这样做,我相信:

select a.c1, sum(b.c1) from a join b on a.c0 = b.c0 ....

您显式订阅了任务池上的observable,移动了UI线程的工作。在使用输出之前,您将返回到UI线程,以便能够在UI上进行更新。