RezaNoei
RezaNoei

Reputation: 1479

Implementing ShowDialog which is work in the same thread

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

Answers (1)

Dave M
Dave M

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

Related Questions