title: UWP - Trying to make a Dialog control. How to send a signal from UI thread to other waiting thread?
body: <p>I'm developing an app for UWP with C#/XAML. Both target and min versions are Windows 10 version 1903.</p>
  <p>Not happy with the <code>ContentDialog</code> control, because it doesn't allow to control the dialog size. I'm trying to make a dialog-like control, with a functionality like the <code>ContentDialog</code> class, using the <code>Popup</code> control. The popup would occupy the whole screen.</p>
  <p>We use the <code>ContentDialog</code> with async pattern as follows:</p>
  <pre><code>var dialog = new ContentDialog() {...};
  var result = await dialog.ShowAsync();
  </code></pre>
  <p>So I want to do the same, passing the content as a <code>Page</code> type:</p>
  <pre><code>var result = await Singleton&lt;GeneralPopup&gt;.Instance.NavigateAndOpen(typeof(OpAmpLibraryExplorer));
  </code></pre>
  <p>Where <code>OpAmpLibraryExplorer</code> is a <code>Page</code> that needs to be shown. The <code>Singleton</code> class automatically constructs the instance invoking the parameterless constructor.
  The page must met the <code>IGeneralPopup</code> interface:</p>
  <pre><code>public interface IGeneralPopup 
  {
      object OKSignal();
  }
  </code></pre>
  <p>Because the footer buttons are outside of the content. We send the <code>OKSignal()</code> method to the page. So the page performs some processing before closing (like storing everything in the database), and outputs a result <code>object</code> eventually.</p>
  <p>The GeneralPopup class is:</p>
  <pre><code>public class GeneralPopup
  {
       private Windows.UI.Xaml.Controls.Primitives.Popup _popup { get; }
       private Windows.UI.Xaml.Controls.Frame _frame; 
       private System.Type loadedType;
  
       private double buttonWidth = 200;
       private double buttonHeight = 50;
  
       private Windows.UI.Xaml.Controls.Button primaryButton;
       private Windows.UI.Xaml.Controls.Button secondaryButton;
  
       private object resultObject;
       private Windows.UI.Xaml.Window currentWindow =&gt; Window.Current;
  
       public bool IsOpen
       { 
           get =&gt; _popup.IsOpen;
           set { _popup.IsOpen = value; }
       }
  
       public GeneralPopup()
       {
           _frame = new Frame();
  
           _grid = new Grid()
           {
               Width = currentWindow.Bounds.Width,
               Height = currentWindow.Bounds.Height 
           };
  
           _grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });  //page content
           _grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) });  //footer buttons (ok, cancel, etc)
  
           _grid.Children.Add(_frame);
  
           Grid.SetRow(_frame, 0);
  
           var stkFooterButtons = new StackPanel()
           {
               Margin = new Thickness(8),
               Spacing = 8,
               Orientation = Orientation.Horizontal,
               HorizontalAlignment = HorizontalAlignment.Right
           };
  
           primaryButton = new Button()
           {
               Padding = new Thickness(8),
               Content = &quot;OK&quot;,
               Width = buttonWidth,
               Height = buttonHeight,
               Command = new RelayCommand(() =&gt;
               {
                   IsOpen = false;
                   if (typeof(IGeneralPopup).IsAssignableFrom(loadedType))
                   {
                       resultObject = (_frame.Content as IGeneralPopup).OKSignal();
                   }
               })
           };
  
           secondaryButton = new Button()
           {
               Padding = new Thickness(8),
               Content = &quot;Cancel&quot;,
               Width = buttonWidth,
               Height = buttonHeight,
               Command = new RelayCommand(() =&gt; { IsOpen = false; })
           };
  
           stkFooterButtons.Children.Add(primaryButton);
           stkFooterButtons.Children.Add(secondaryButton);
  
           _grid.Children.Add(stkFooterButtons);
           _grid.Background = (Brush)Application.Current.Resources[&quot;ApplicationPageBackgroundThemeBrush&quot;];
           Grid.SetRow(stkFooterButtons, 1);
  
           currentWindow.SizeChanged += windowSizeChanged;
  
           _popup = new Popup()
           {
               HorizontalOffset = PopupPadding.Left,
               VerticalOffset = PopupPadding.Top,
               Width = currentWindow.Bounds.Width - (PopupPadding.Left + PopupPadding.Right),
               Height = currentWindow.Bounds.Height - (PopupPadding.Top + PopupPadding.Bottom),
               Child = _grid
           };
       }
  
       public async Task&lt;object&gt; NavigateAndOpen(Type pageType, object parameter = null)
       {
           IsOpen = true;
           loadedType = pageType;
  
           _frame.Navigate(pageType, parameter);
  
           var result = await ...  //what can I do here to get the page result?
           
           return result;
       }
  }
  </code></pre>
  <p>Now comes the problem and question. When we navigate and open the popup, we return to the UI thread, so the user interacts with the page, do some stuff, and then hit the OK <code>primaryButton</code>, the <code>OKSignal()</code> is sent to the Page, the Page do some processing and close.</p>
  <p><strong>But how to return this result <code>object</code> to the waiting thread in the <code>NavigateAndOpen</code> method?</strong>, so this thread finishes, the <code>NavigateAndOpen</code> finishes, and outputs the resulting object to the original async caller.</p>
  <p><strong>My goal is to imitate the usage pattern in <code>ContentDialog</code> Control</strong>. I see this class uses the <code>IAsyncOperation</code> interface, that seems to be the key. But I can't figure out how to use it.</p>
  <p>Any help you could bring is welcome. Thanks!</p>