WPF -使用MVVF命令关闭运行新线程的窗口

本文关键字:线程 窗口 新线程 运行 使用 MVVF 命令 WPF | 更新日期: 2023-09-27 18:11:55

设置

我有一个窗口和视图模型。视图模型有一个执行Task的命令。当任务完成时,我想要的效果是窗口关闭。

最可接受的(最佳实践)方法是什么?

我倾向于认为Dispatcher。调用很糟糕,但这是一个没有意义的问题,因为视图模型没有对窗口或其调度程序的引用。

edit:澄清一下,这个窗口属于UI线程。该命令本身调用包装器来执行异步http请求(它返回一个任务)。该命令可以附加一个ContinueWith。

我不想将视图模型与视图紧密耦合(例如通过将Window传递给视图模型)

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>

WPF -使用MVVF命令关闭运行新线程的窗口

我使用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中(无论是在async进程的回调方法中,还是在没有运行async的命令方法的末尾):

Messenger.Default.Send(new NotificationMessage(this, "Close"));

一般来说,我认为,使用MVVM模式关闭窗口取决于在视图订阅的视图模型上引发某种形式的Close事件:

public class MyView
{
    public MyView(MyViewModel viewModel)
    {
        this.DataContext = viewModel;
        viewModel.Close += (_, __) => Dispatcher.Invoke(this.Close);
    }
}

从任务的ContinueWith动作中引发Close事件,然后完成。