设置
我有一个窗口和一个视图模型。 viewmodel有一个执行Task
的命令。任务完成后,我希望效果为窗口关闭。
最可接受的(最佳实践)方式是什么?
我倾向于认为Dispatcher.Invoke是hacky和bad,但这是一个没有实际意义的因素,因为viewmodel没有对窗口或其调度程序的引用。
编辑:为了澄清,该窗口属于UI线程。该命令本身调用一个包装器来执行异步http请求(返回一个任务)。该命令可以附加一个ContinueWith。
我不想将视图模型紧密地耦合到视图(例如通过将窗口传递给视图模型)
public class Api
{
Task MakeHttpCall();
}
public class ViewModel, DependencyObject
{
private Api _api;
public Task DoHttpCall() { return _api.MakeHttpCall(); }
public MyCommand MyCommandInst { get; private set; }
}
public class MyCommand : ICommand
{
void Execute(object parameter)
{
var viewModel = GetViewModel(parameter);
viewModel.DoHttpCall().ContinueWith( t => HandleCompletionAndSomehowTriggerWindowClose(t));
}
}
然后是view.xaml:
<Button Command={Binding MyCommandInst} CommandParameter={Binding}>Do Stuff</Button>
答案 0 :(得分:1)
我使用MVVM Light来帮助推动这一过程。 ViewModel没有引用View,它只是发布要关闭的消息,并且View已注册以接收这些消息。
在我的观点背后的代码中,我订阅了这样的Messenger服务:
public class MyView
{
public MyView()
{
InitializeComponent();
Messenger.Default.Register<NotificationMessage>(this, msg =>
{
if ((msg.Sender == this.DataContext) && (msg.Notification.ToUpper() == "CLOSE"))
this.Close();
});
}
}
然后在ViewModel中(在异步进程的回调方法中或在命令方法结束时,如果没有运行异步):
Messenger.Default.Send(new NotificationMessage(this, "Close"));
答案 1 :(得分:0)
通常,我认为,使用MVVM模式关闭窗口取决于在视图所订阅的视图模型上引发某种形式的Close
事件:
public class MyView
{
public MyView(MyViewModel viewModel)
{
this.DataContext = viewModel;
viewModel.Close += (_, __) => Dispatcher.Invoke(this.Close);
}
}
从任务的Close
操作中提升ContinueWith
事件,您就完成了。