1
場景(WPF桌面應用,.NET 4.6)螺紋親和力:與ReactiveUI 6
我有顯示某些 「任務」 列表框。 目標是啓動一個異步過程,它將迭代所有任務,執行其中的每個任務。
這是一個長時間運行的過程,因此期望的行爲是禁用大多數命令而不鎖定UI,因此用戶仍然可以取消它。 它應該標記每個任務(待機,運行,完成),以便可以動態更新UI,向最終用戶提供反饋(使用基於「狀態」枚舉的樣式)。
的問題
當執行指令(ExecuteTasks
)得到消息:
這種類型的CollectionView的不支持從一個線程從發送器線程不同,以它的SourceCollection變化。
我的問題是:如何使用ReactiveUI解決此問題?我相信答案是圍繞調度程序的某個地方,但目前爲止我還無法弄清楚。
下面是代碼的樣子:
public ReactiveCommand<object> AddTask { get; }
public ReactiveCommand<object> ExecuteTasks { get; }
public IPlugin SelectedTask
{
get { return selectedTask; }
set { this.RaiseAndSetIfChanged(ref selectedTask, value); }
}
public ReactiveList<IPlugin> Tasks
{
get { return tasks; }
}
public ReactiveList<PluginFactoryGroup> TaskFactories
{
get
{
return taskFactories;
}
}
public AppViewModel(IExecutionContext context, IEnumerable<PluginFactoryGroup> taskFactories)
{
this.context = context;
// initialize lists
tasks = new ReactiveList<IPlugin>() { ChangeTrackingEnabled = true };
this.taskFactories = new ReactiveList<PluginFactoryGroup>(taskFactories);
// create observables to determine whether or not commands can be executed
var canEdit = /*...*/
var canExecute = /*...*/
// initialize commands
AddTask = ReactiveCommand.Create(canEdit);
AddTask.Subscribe(_ => {
if (SelectedFactory != null)
{
var t = SelectedFactory.Create(this.context);
Tasks.Add(t);
SelectedTask = t;
}
});
ExecuteTasks = ReactiveCommand.CreateAsyncTask(canExecute, _ =>
{
return Task.Run(() =>
{
object result = null;
foreach (var item in Tasks)
{
item.Clear();
item.Validate();
}
if (Tasks.Any(e => e.Status == TaskStatus.Error))
{
Tasks.Reset();
return result;
}
foreach (var item in Tasks)
{
item.Status = XrmTools.Plugins.TaskStatus.Running;
item.Execute();
item.Status = XrmTools.Plugins.TaskStatus.Completed;
}
return result;
});
});
}
太棒了。錯誤消失了,它沒有像預期的那樣阻塞UI,非常感謝。有一件事,狀態的改變 - 「item.status =/* new_status * /'不是用信號通知用戶界面。該集合正在改變,但用戶界面不是。我的工作方式是在每次更改(兩次)後添加'Tasks.Reset()',這看起來不正確。 – Ebrito