我正在开发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在同一线程中,等待将阻止我的执行。
有什么方法可以更清洁地完成这项工作?
答案 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
,这通常被认为是不良做法;但是,该通用规则的主要例外是事件处理程序,这正是我们使用它的方式。