Reputation: 1479
I am developing a WPF application and i want to show Dialogs in the active Window using a PopUp or a Different grid (by changing ZIndex in this grid).
currently my solution works using Event and Event Handlers:
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;
}
So, I'm using it in this way :
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;
}
this is a ugly code and i don't want to make my codes more Complicated. i have tried to wait for DialogResult but this Dialog is in the same thread and waiting will blocks my execution.
is there any way to do this work in a cleaner way ?
Upvotes: 1
Views: 743
Reputation: 3033
You can accomplish this very nicely by making use of the async
/await
keywords and 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;
}
An then you can call it like this:
private async void Button_Click(object sender, RoutedEventArgs e)
{
DialogResult result = await DialogCenter.ShowDialogAsync(new Test());
//do stuff (dialog is completed at this point)
}
You may notice the async void
which is commonly considered bad practice; however, the main exception to that general rule is for event handlers, which is exactly how we are using it.
Upvotes: 2