我有一个简单的MVVM应用程序。某些ViewModel执行异步处理,这需要通知View有关状态更新和处理完成的时间。
由于MVVM中对View的直接调用受到限制,因此我选择了 Commands 。不幸的是,即使任务被同步到主(UI)线程,从连续任务调用时也不会执行命令:
public void DoAction()
{
//NOTE: command gets executed correctly
AppCommands.SomeCommand.Execute(null, null);
// run some task asynchronously
Task task = new Task( ... );
task.ContinueWith(
taskAntecedent =>
{
//NOTE: command does not get executed at all!
AppCommands.SomeCommand.Execute(null, null);
},
TaskScheduler.FromCurrentSynchronizationContext());
task.Start();
}
如果Execute方法包含正确的目标元素,那么总是会执行coomand(这样WPF就可以在可视树上走,并找到命令绑定)。 但这不能在ViewModel中完成,因为它不应该看到View。
我尝试过的其他一些解决方案:
依赖注入 - 通过构造函数将View作为一些接口注入ViewModel。可行,但这会产生错误的空间:1。ViewModel不能在XAML中使用,因为ViewModel不再具有空的构造函数。 2.即使我定义了一个空的构造函数,开发者也可能忘记使用正确的构造并在其中注入适当的View(一些视图有几个可以被用户替换的ViewModel)。
路由事件 - ViewModel应该是可替换的,这意味着View必须从旧模型中取消挂钩事件并重新挂钩到需要在View中进行代码优化的新模型(不像MVVM一样)
服务 - 某些视图是UserControls,与Windows不同,它们没有Loaded,Unloaded事件 - 因此没有好的位置来注册和取消注册服务。还可以创建多个控件,从而多次注册相同的服务,然后Views和ViewModels之间的绑定不会是1:1。
问题很简单:
如何例如从UserControl的ViewModel关闭窗口,在View端或用户/开发人员没有大量额外编码?
我想在vanilla WPF中执行此操作,而不是使用第三方MVVM框架,因为应用程序应该是轻量级/易于理解的(尽可能少的黑魔法)。
答案 0 :(得分:0)
尝试使用实际加入执行操作的ContinueWith
的{{1}}方法的正确重载,即调用命令,返回UI线程:
TaskScheduler
如果由于某种原因这不起作用,我建议您提供a Minimal, Complete, and Verifiable example您的问题。