MessageDialog met Custom Content

In WinRT geeft de MessageDialog al aanzienlijk meer vrijheid dan de MessageDialog zoals we die in WinForms of WPF kennen, zo is het nu mogelijk zelf knoppen toe te voegen en het label hiervan zelf te bepalen waar je eerst van zat aan de standaard Ja Nee Annuleren etc labels.

Echter is de content nog beperkt tot enkel een string. Soms kan het handig zijn om hier wat rijkere content neer te zetten. Kijk eens bijvoorbeeld naar de mail applicatie. Deze maakt gebruik van een dergelijke popup voor het toevoegen van een nieuw account. Bij deze een ContentPopup waarmee je een eigen control/user control eenvoudig op een zelfde wijze kan tonen

public async void ShowPopup()
{
     var dialog = new ContentPopup("Title", new UserControl());
     await dialog.ShowAsync();
}

En hier kan je hem downloaden: 

Win8.Controls.zip (15,81 kb)

Wat ik zelf erg mooi gedaan vind van het MessageDialog is het gebruik van async en await keyword. Hierdoor kan je wachten tot de gebruiken een optie selecteert zonder gedoe met eventhandlers of callbacks te krijgen. Ik heb geprobeerd, en volgens mij goed gelukt, het zelfde gedrag na te bouwen voor het ContentPopup.

Wanneer je beetje bekend bent met async en await weet je dat je method een Task moet terug geven en await vervolgens met behulp van een TaskAwaiter gaat wachten tot wanneer de Task compleet is en vervolgens her resultaaat van de task uitpakt en dan verder gaat met de onderstaande code.

Wanneer je MessageDialog class bestudeerd zie je dat ShowAsync echter geen Task terug geeft meer een IAsyncOperation<TResult>. Microsoft heeft extension methods geschreven om deze IAsyncOperation<T> om te zetten naar een Task. Dit word allemaal door de compiler geregeld en daar kan je ook awaiten op een IAsyncOperation. Waarom dan niet meteen een task gebruiken? De class Task komt uit TPL en naast awaiten op een Task kan je ook echt Task.Wait gebruiken en gezien de hele operatie vaak niks met threads of Tasks te maken heeft hang je je applicatie meteen op. Door gebruik te maken van IAsyncOperation<TResult> verkom je dat.

Voor het ContentPopup heb ik een eigen implementatie gemaakt van IAsyncOperation<TResult>. Wanneer ShowASync word aangeroepen maar ik een nieuwe instantie aan van dat object en geef ik deze terug. Ook hou ik in het control een referentie vast naar dit instantie:

public sealed class ContentPopup
{
   private IAsyncOperation<IUICommand> _action;

   public IAsyncOperation<IUICommand> ShowAsync()
   {
       if (_action != null)
          throw new InvalidOperationException();

       // code to show the popup

       return _action = new ContentPopupShowAsyncOperation();
   }
}

Er word nu een AsyncOperation terug gegeven en moet er nog worden gezorgd de IAsyncOperation ook word beeindigd. Dat moet gebeuren wanneer de gebruiker op een knop (ok / cancel / etc) drukt in de UI. Door SetResult en en Close aan te roepen op de IAsyncOperation word de operatie beeindigd.

private void ButtonClick(object sender, RoutedEventArgs e)
{
    var button = (Button)sender;
    IUICommand command = button.DataContext as IUICommand;
    if (command != null)
    {
        _action.SetResult(command);
        _action.Close();
        _action = null;
    }
}
  •   RT @VisualStudio: In this episode, we're joined by Kasey Uhlenhuth (@kuhlenhuth) who shows some of the refactoring features available in Vi…
  •   @VSTS problems with build queues atm?
  •   RT @donasarkar: Hi #WindowsInsiders we have released Build 17713 to the Fast ring! This build has several new features we think IT Pros wil…
  •   RT @maryjofoley: ICYMI, another Windows 10 on ARM PC is available: Lenovo Miix 630 ARM-based 2-in-1 Windows tablet goes on sale for $900 ht…
  •   the moment you have a meeting and skype for business protocol handller is lost again ...
  •   @LocalJoost Surface Go vanaf 27 augustus te bestellen?
  •   tnx @VistaHypotheken https://t.co/qFoQS6mQ63
  •   @gotheap based on the link i understand they should show up after a build as well? i only see them for the test on… https://t.co/XadwWJjIAM
  •   @panos_panay will the surface go with lte have gps? i need a new device to run my own app for navigation while flying around
  •   @aaronbjork @IoannisKarlis @Jira @VSTS and replace delivery plans with the feature timeline extension. that is really helpful!