MessageBox.Show() in WinRT

By Fons Sonnemans, posted on
4924 Views 5 Comments

I'm currently in the process of converting some of my Windows Phone apps to the Windows 8 Consumer Preview. While doing so I discovered there is no MessageBox.Show() method in WinRT. The alternative is to use the new MessageDialog class. This means I have to rewrite a lot of code which I try to avoid. Therefore I came up with my own MessageBox helper class which mimics the behavior of the WP7 MessageBox. In this post I will demonstrate this, using the following sample application.

Suppose I have the following code in my Windows Phone application:

private void Button1_Click(object sender, RoutedEventArgs e) {
    var result = MessageBox.Show("This is MessageBox", "Title", MessageBoxButton.OKCancel);
    if (result == MessageBoxResult.OK) {
        // do something    
    }
    Button1.Content = result.ToString();
}

In Windows 8 I would have to rewrite it to the following:

private async void Button1_Click(object sender, RoutedEventArgs e) {
    MessageDialog md = new MessageDialog("This is a MessageDialog", "Title");
    bool? result = null;
    md.Commands.Add(
       new UICommand("OK", new UICommandInvokedHandler((cmd) => result = true)));
    md.Commands.Add(
       new UICommand("Cancel", new UICommandInvokedHandler((cmd) => result = false)));

    await md.ShowAsync();
    if (result == true) {
        // do something    
    }
    Button1.Content = result.ToString();
}

As you can see I have marked the Button1_Click() method with the async keyword. This is necessary because the ShowAsync() method is called, using the new await keyword. The MessageDialog is shown in an seperate thread which will allow the main thread to continue to execute. This allows all animations running on the main thread to continue to play.

My MessageBox show helper class makes my conversion much easier. You only have to change the Show() call to a ShowAsync() call and add the await and async keywords.

private async void Button2_Click(object sender, RoutedEventArgs e) {
    var result = await MessageBox.ShowAsync("This is a MessageBox", 
                                            "Title", MessageBoxButton.OKCancel);
    if (result == MessageBoxResult.OK) {
        // do something    
    }
    Button2.Content = result.ToString();
}

Here is the code of my MessageBox helper class:

using System;
using System.Threading.Tasks;
using Windows.UI.Popups;

namespace ReflectionIT.Windows8.Helpers {

    class MessageBox {

        public static async Task<MessageBoxResult> ShowAsync(string messageBoxText, 
                                                             string caption, 
                                                             MessageBoxButton button) {

            MessageDialog md = new MessageDialog(messageBoxText, caption);
            MessageBoxResult result = MessageBoxResult.None;
            if (button.HasFlag(MessageBoxButton.OK)) {
                md.Commands.Add(new UICommand("OK", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.OK)));
            }
            if (button.HasFlag(MessageBoxButton.Yes)) {
                md.Commands.Add(new UICommand("Yes", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.Yes)));
            }
            if (button.HasFlag(MessageBoxButton.No)) {
                md.Commands.Add(new UICommand("No", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.No)));
            }
            if (button.HasFlag(MessageBoxButton.Cancel)) {
                md.Commands.Add(new UICommand("Cancel", 
                    new UICommandInvokedHandler((cmd) => result = MessageBoxResult.Cancel)));
                md.CancelCommandIndex = (uint)md.Commands.Count - 1;
            }
            var op = await md.ShowAsync();
            return result;
        }

        public static async Task<MessageBoxResult> ShowAsync(string messageBoxText) {
            return await MessageBox.ShowAsync(messageBoxText, null, MessageBoxButton.OK);
        }
    }

    // Summary:
    //     Specifies the buttons to include when you display a message box.
    [Flags]
    public enum MessageBoxButton {
        // Summary:
        //     Displays only the OK button.
        OK = 1,
        // Summary:
        //     Displays only the Cancel button.
        Cancel = 2,
        //
        // Summary:
        //     Displays both the OK and Cancel buttons.
        OKCancel = OK | Cancel,
        // Summary:
        //     Displays only the OK button.
        Yes = 4,
        // Summary:
        //     Displays only the Cancel button.
        No = 8,
        //
        // Summary:
        //     Displays both the OK and Cancel buttons.
        YesNo = Yes | No,
    }

    // Summary:
    //     Represents a user's response to a message box.
    public enum MessageBoxResult {
        // Summary:
        //     This value is not currently used.
        None = 0,
        //
        // Summary:
        //     The user clicked the OK button.
        OK = 1,
        //
        // Summary:
        //     The user clicked the Cancel button or pressed ESC.
        Cancel = 2,
        //
        // Summary:
        //     This value is not currently used.
        Yes = 6,
        //
        // Summary:
        //     This value is not currently used.
        No = 7,
    }
}

I have also added the 'Yes' and 'No' Buttons to the MessageBoxButton enum. This is something I was always missing in the Windows Phone API. Now you can not only use OK/Cancel but also Yes/No/Cancel.

private async void Button3_Click(object sender, RoutedEventArgs e) {
    var result = await MessageBox.ShowAsync("This is a MessageBox", "Title", 
                                            MessageBoxButton.YesNo | MessageBoxButton.Cancel);
    if (result == MessageBoxResult.Yes) {
        // do something    
    }
    if (result == MessageBoxResult.No) {
        // do something    
    }
    Button3.Content = result.ToString();
}

Download my sample project which contains all source code.

Cheers,

Fons

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.

Leave a comment

Blog comments

taz

12-Feb-2013 12:50
this code now out of date? the "result" keyword is not recognised...

Smartis

03-Jul-2013 8:25
Great Workaround! Thanks

Lucian

10-Oct-2013 10:36
I think what'd hurt most about this is the lack of localization, i.e. translating "OK/Cancel" into different languages...

Jorge Cupi

21-Oct-2013 12:48
Nice job!!! Thx for sharing

Scott

17-Dec-2013 5:35
very handy, thank you for posting.