Asynchronous Commands in Windows Store Apps

The Model-View-View Model (MVVM) pattern is more popular than ever and is built into the Visual Studio templates for creating Windows Store apps. Developers familiar with Silverlight already encountered the platform shift to using asynchronous operations because it was impossible to generate a WCF client with synchronous methods. The Windows Runtime (WinRT) takes this further by dictating any operation that may potentially take longer than 50ms to complete should be asynchronous.

How does the MVVM pattern handle asynchronous operations, when the command interface ICommand only exposes synchronous methods?

namespace System.Windows.Input
{
     public interface ICommand
     {
         event EventHandler CanExecuteChanged;
         bool CanExecute(object parameter);
         void Execute(object parameter);
     }
}

Now consider a simple implementation of a command we’ll call an ActionCommand because it allows you to specify a delegate to perform and action when it is invoked. It also provides a predicate to condition the command and a public method to notify the command when the conditions for the predicate have changed.

namespace MyApp.Common
{
     using System;
     using System.Windows.Input;
     public class ActionCommand : ICommand
      {
         private readonly Action action;
         private readonly Func<bool> condition;

         public ActionCommand()
         {
             this.action = delegate { };
             this.condition = () => true;
         }
         public ActionCommand(Action action)
         {
             this.action = action;
             this.condition = () => true;
         }




         public ActionCommand(Action action, Func<bool> condition)
         {
             this.action = action;
             this.condition = condition;
         }
         

         public event EventHandler CanExecuteChanged = delegate { };
         public void RaiseExecuteChanged()
         {
             this.CanExecuteChanged(this, EventArgs.Empty);
         }
         public bool CanExecute(object parameter)
         {
             return this.condition();
         }
         public void Execute(object parameter)
   &nbsp

;     {
             this.action();
         }
     }
}

As you can see, there is no Task in the implementation of ICommand, nor any asynchronous code. As you are also aware, WinRT requires asynchronous code when you are performing various operations including a dialog. Here is an example of code that copies text and HTML to the clipboard and then shows a dialog to the end user they must confirm to acknowledge the copy was successful. The method is asynchronous.

private async Task Copy()
{
     var package = new DataPackage();
     package.SetText(this.DataManager.CurrentPage.Text);
     package.SetHtmlFormat(HtmlFormatHelper.CreateHtmlFormat
        (this.DataManager.CurrentPage.Html));
     Clipboard.SetContent(package);
     var dialog = new MessageDialog(
        "The web page was successfully copied to the clipboard.");
     await dialog.ShowAsync();
}

Now you have to wire it to the command implementation that is not asynchronous. How can you? Fortunately, the magic that is asynchronous code is able to combine forces with lambda expressions to enable you to handle asynchronous code “on the fly.” Here is the code to wire-up the command to call the Copy method asynchronously:

this.CopyCommand = new ActionCommand(
     async () => await this.Copy(),
     () => this.CopyEnabled);

That’s it. The action itself may be implemented as an asynchronous operation simply by invoking the async keyword and using the await operator. That’s how easy it is! While you should typically declare your interface consistently – for example, declaring them to return a Task when they should be implemented asynchronously – using this technique you can apply an asynchronous operation to the existing contract when needed. This means your commands can be asynchronous if and when needed, in full compliance with the WinRT guidelines.

Jeremy Likness

View Comments

Recent Posts

8-Step AWS to Microsoft Azure Migration Strategy

Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…

16 hours ago

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

1 week ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago