我正在尝试将ReactiveUI 6.5用于WinForms。
我需要一个在viewmodel上调用并在视图上同步执行的命令。我尝试了ReactiveCommand.Create()
和.Execute()
,但这显然是异步执行的,这不是我需要的。
我所拥有的是这样的:
public class MyViewModel : ReactiveObject
{
public ReactiveCommand<object> AddNewThingToControl { get; private set; }
public ThingType Thing { get; set; }
// Ctor
public MyViewModel()
{
AddNewThingToControl = ReactiveCommand.Create();
}
// Thing factory, called from somwhere not shown
public void CreateAndAddThing()
{
Thing = new ThingType();
// should not return before Thing is added to myControl
AddNewThingToControl.Execute(null);
// Code that needs Thing added to myControl goes here.
// This doesn't work because DoAddThing() has not been called yet!
}
}
public class MyView : Form, IViewFor<MyViewModel>
{
public MyViewModel VM { get; set; }
// Ctor
public MyView()
{
VM = new MyViewModel();
VM.AddNewThingToControl.Subscribe(x => { DoAddThing(); });
}
private void DoAddThing()
{
// This doesn't get called until some unknown time
// after AddNewThingToControl.Execute() returns!
myControl.Things.Add(VM.Thing);
}
// -----------
#region IViewFor Implementation not shown
}
代码在UI线程或某种工作线程上调用 CreateAndAddThing()
。
创建了一个新的Thing
,应该在到达AddNewThingToControl.Execute()
之后的行之前将其添加到视图中的控件上。
如何使用ReactiveCommand
?
答案 0 :(得分:1)
MethodThatNeedsThingAdded()
to return Task
, in order to be awaitable.CreateAndAddThing()
method async
, and await
first for the execution of the command, and then for the MethodThatNeedsThingAdded()
.Execute
on the ReactiveCommand
, but ExecuteAsyncTask
which is awaitable!This could be the code:
public async void CreateAndAddThing()
{
Thing = new ThingType();
await AddNewThingToControl.ExecuteAsyncTask(null);
await MethodThatNeedsThingAdded();
}
This solution is elegant, clear, and you're sure that the two methods are always called in the right order. So to speak, the whole work is asynchronous respect to the UI Thread, but is sequential and predictable as you want.
You will say: "but I wanted all this round to be synchronous!". Do you really need a synchronous execution? For what purpose? If you really need this, imho you've chosen the wrong library. Try to implement a Command
class on your own (deriving from ICommand
as needed by WPF controls).