我正在使用带有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;
});
}
答案 0 :(得分:1)
Observable本质上是单线程的,您需要指定工作的位置。你可以这样做,我相信:
select a.c1, sum(b.c1) from a join b on a.c0 = b.c0 ....
您显式订阅了任务池上的observable,移动了UI线程的工作。在使用输出之前,您将返回到UI线程,以便能够在UI上进行更新。