WPF MVVM异步事件调用



我迷路了,我希望我的ViewModel使用事件委托,以便我可以订阅它,打开一些对话框并等待对话框结果。稍后,ViewModel应该在对话框结果中做任何想做的事情。

这是我实现它的方式(恢复代码):

public class MyViewModel()
{
   public delegate TributaryDocument SearchDocumentEventHandler();
   public event SearchDocumentEventHandler SearchDocument;
   //Command for the search button
   public CommandRelay SearchDocumentCommand { get; set; }
   //Document that i found in the dialog.
   public TributaryDocument Document { get; set; }
   public MyViewModel()
   {
      SearchDocumentCommand = new CommandRelay(DoSearchDocument);
   }
   //The command execution
   public void DoSearchDocument()
   {
       //Event used here !
       Document = SearchDocument?.Invoke();
   }
}
public class MyUIControl : UserControl
{
    public MainWindow MainWindow { get; }
    public MyUIControl()
    {
       MainWindow = Application.Current.Windows[0] as MainWindow;
       DataContextChanged += MyUIControl_DataContextChanged;
    }
    private void MyUIControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var modelView = (MyViewModel)DataContext;
        modelView.SearchDocument += MyUIControl_SearchDocument;
    }
    private TributaryDocument MyUIControl_SearchDocument()
    {
       //Dont know what to do here... i am lost on this part.
       return await MainWindow.ShowDialog(new MyDocumentSearcherDialog());
    }
}
//The signature for MainWindow.ShowDialog
public async Task<object> ShowDialog(object dialog)
{
   return await DialogHost.Show(dialog, "MainDialog");
}

MyDocumentSearcherDialog只是一个对话框,我在其中搜索并返回TributaryDocument对象。

我理解的问题来自这部分(因为我无法编译):

private TributaryDocument MyUIControl_SearchDocument()
{
   return await MainWindow.ShowDialog(new MyDocumentSearcherDialog());
}

我无法在没有将方法签名更改为异步的情况下使用。如果将其更改为异步,则必须返回Task<TributaryDocument>并更改事件委托:

    public delegate Task<TributaryDocument> SearchDocumentEventHandler();
    //On MyUIControl
    private Task<TributaryDocument> MyUIControl_SearchDocument()
    {
       return await MainWindow.ShowDialog(new MyDocumentSearcherDialog());
    }
   //On MyViewModel
   public async void DoSearchDocument()
   {
       //Event used here !
       Document = await Task.Run(async () => await SearchDocument?.Invoke());
   }

如果这样做,我会得到以下例外:

其他信息:调用线程必须是sta,因为许多 UI组件需要此。

似乎您需要做的就是删除 Task.Run(在这种情况下,无需 offload )。Task.Run肯定会给您 sta线程异常,如果您正在从内部进行 ui 工作。

然而,简而言之

public async void DoSearchDocument()
{ 
   await SearchDocument?.Invoke();
}

note :由于这是一个事件,它是唯一可以使用async void的地方>

最新更新