实现在同一线程中工作的ShowDialog

时间:2018-07-21 11:50:10

标签: c# wpf modal-dialog

我正在开发WPF应用程序,我想使用弹出窗口或其他网格(通过更改此网格中的ZIndex)在活动窗口中显示对话框。

当前,我的解决方案使用事件和事件处理程序:

 public static void ShowDialog(IDialog DialogControl)
 {
     // Get Active Window ...
     CurrentWindow = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
     CurrentContent = (UIElement)CurrentWindow.Content;
     CurrentWindow.Content = null;
     CurrentContent.IsEnabled = false;     

     Grid DialogGrid = new Grid();
     Panel.SetZIndex(DialogGrid, 1);
     // ... 
     var Dialog = DialogControl.GetUserControl();

     DialogGrid.Children.Add(Dialog);

     DialogControl.OnDialogComplete += (object sender, DialogResult result) => { RestoreWindow(); OnDialogComplete?.Invoke(sender, result); };

     CurrentWindow.Content = DialogGrid;
 }

 interface IDialog
 {
     UserControl GetUserControl();
     event DialogComplete OnDialogComplete;
 }

所以,我以这种方式使用它:

 private void Button_Click(object sender, RoutedEventArgs e)
 {
     DialogCenter.OnDialogComplete += DialogCenter_OnDialogComplete;
     DialogCenter.ShowDialog(new Test());
 }

 private void DialogCenter_OnDialogComplete(object sender, DialogResult result)
 {
     // Take Result and Do something 
     DialogCenter.OnDialogComplete -= DialogCenter_OnDialogComplete;
 }

这是一个丑陋的代码,我不想使我的代码更加复杂。 我试图等待DialogResult,但是此Dialog在同一线程中,等待将阻止我的执行。

有什么方法可以更清洁地完成这项工作?

1 个答案:

答案 0 :(得分:1)

通过使用async / await关键字和TaskCompletionSource<T>,可以很好地完成此操作。

public static Task<DialogResult> ShowDialogAsync(IDialog DialogControl)
{
    //setup code ...

    var taskCompletionSource = new TaskCompletionSource<DialogResult>();

    DialogControl.OnDialogComplete += (object sender, DialogResult result) => 
    { 
        RestoreWindow();
        taskCompletionSource.SetResult(result); 
    };

    CurrentWindow.Content = DialogGrid;

    return taskCompletionSource.Task;
}

然后您可以这样称呼它:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    DialogResult result = await DialogCenter.ShowDialogAsync(new Test());
    //do stuff (dialog is completed at this point)
}

您可能会注意到async void,这通常被认为是不良做法;但是,该通用规则的主要例外是事件处理程序,这正是我们使用它的方式。