首页 > 解决方案 > Material Design Template WPF DialogHost 等到关闭并与 Prism EventAggregator 集成

问题描述

我正在尝试MessageBoxDialogHost来自MaterialDesign库的替换标准 WPF,但我不知道如何等到用户从对话框中选择“确定”或“取消”。我面临的问题是因为我从使用事件聚合器调用的函数中调用对话框的显示。下面是我的代码:

private async void OnMessageRequest(MessageArgs obj)
{
   MessageDialogModel = _messageDialogCreator();
   MessageDialogModel.Load(obj.Message, obj.HasButtons);
   var view = new SampleDialog
   {
      DataContext = MessageDialogModel
   };

   await DialogHost.Show(view, "RootDialog");

}

当我使用MessageBox它时,它按预期工作。这是代码:

if (obj.HasButtons)
{
   var result = MessageBox.Show(obj.Message, obj.Title, MessageBoxButton.OKCancel);
   var submitArg = result == MessageBoxResult.OK
      ? MessageDialogResult.OK
      : MessageDialogResult.Cancel;
   _eventAggregator.GetEvent<MessageDialogResultEvent>().Publish(submitArg);
}
else
{
   MessageBox.Show(obj.Message, obj.Title);
}

基本上需要的是在显示对话框后停止代码并等待用户选择和选项。我希望这是有道理的

标签: c#wpfmvvmprism

解决方案


您需要做的就是等待DialogHost.Show方法的结果并处理它,具体取决于您传递CommandParameterCloseDialogCommand. 例如,我MessageBoxResult对对话框中的按钮使用 as 命令参数,表示确定和取消。

<Button Content="OK"
        Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
        CommandParameter="{x:Static MessageBoxResult.OK}"/>
<Button Content="Cancel"
        Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
        CommandParameter="{x:Static MessageBoxResult.Cancel}"/>

然后在代码中,我等待结果并像在您提供的代码中一样处理它。

var result = (MessageBoxResult)await DialogHost.Show(msg, "RootDialog");

var submitArg = result == MessageBoxResult.OK
   ? MessageDialogResult.OK
   : MessageDialogResult.Cancel;

_eventAggregator.GetEvent<MessageDialogResultEvent>().Publish(submitArg);

after 的代码DialogHost.Show将在对话框关闭后执行。

从评论更新

既然您已经澄清了您需要发布事件的方法来等待,那么问题就完全不同了。

我想要发生的是停在“结果”处,显示对话框并等待答案。一旦用户选择 Ok 或 Cancel 继续使用代码。

DialogHost故意构建为异步使用。目前还没有同步调用的方法,请看这个问题。相反,Prism 的事件聚合器没有Publish返回 a Taskor的异步方法Task<T>。因此,不能等待。此外,事件聚合器用于触发和忘记事件,因此根据定义,它不适合您当前显示对话框的同步方法,我不认为这是正确的方法。

如果要保留DialogHost,请返回一个Taskfrom OnMessageRequest,以便能够获得await它。

private async Task OnMessageRequest(MessageArgs obj)

然后您可以等待显示对话框的方法,它应该按预期工作。

private async void OnOpenContractorDetailView(int? contractorId)
{
   if (ContractorDetailViewModel != null && ContractorDetailViewModel.HasChanges)
   {
      var messageArgs = new MessageArgs { Message = "You've made changes. Are you sure you want to navigate away?", Title = "Question", HasButtons = true };
      await void OnMessageRequest(messageArgs);

      if (_dialogResult == MessageDialogResult.Cancel)
         return;
   }
   ContractorDetailViewModel = _contractorDetailViewModelCreator();
   await ContractorDetailViewModel.LoadAsync(LoadMenuArgs, contractorId);
}

您应该考虑通过OnMessageRequest直接将对话结果作为返回值传递Task<MessageDialogResult>,因为在处理异步方法时使用实例成员可能会导致数据竞争。


推荐阅读