I’ve been creating Windows Phone apps for more than two years, so more and more concepts I use in the Phone apps should be ported to Windows Style apps (former Metro). One of these concepts is the question to review the app after 5 application starts. I currently have made two Windows Style apps, and more are coming, but it’s time to improve the quality and get some reviews.
Yesterday evening I started working on a solution and also discussed it with Matthijs Hoekstra, Fons Sonnemans, Martijn de Meulder and Glenn Versweyveld. So let’s start with the end result. How does it look?!

Yes it’s just a flyout with two buttons. The “Review” button should take you directly to the Store’s review page for the current app. But what about the “Improvements” button? The idea came from Martijn, give your users a way to tell you things you could improve in the app and you’ll definitely get less 1- and 2-star ratings. So it should open the e-mail app.
Store app startup count
Of course something like the startup count can be easily stored in the RoamingSettings, so that even over more than one device you won’t show the review question more than once.
private static int ApplicationStarts
{
get
{
object val = ApplicationData.Current.RoamingSettings.Values["ReviewHelper.AppStarts"];
return val == null ? 0 : (int)val;
}
set { ApplicationData.Current.RoamingSettings.Values["ReviewHelper.AppStarts"] = value; }
}
Flyout
The easiest way to get a flyout in your app is by making use of the Callisto framework created by Tim Heuer. Just make use of nuget to get it installed.
I’m just construction the UI you’ve seen in the example above in code. It’s not difficult code, but most of you probably create the UI only in Xaml. I thought this was easier to combine with the Flyout.
var appName = Application.Current.Resources["AppName"] as string;
var content = new StackPanel
{
Margin = new Thickness(16)
};
content.Children.Add(new TextBlock
{
Text =
string.Format(
"Thanks for using the {0} app. Would you like to review this app?",
appName),
TextWrapping = TextWrapping.Wrap,
FontSize = 16,
});
var improveButton = new Button
{
Content = "Improvements?",
HorizontalAlignment = HorizontalAlignment.Right,
Background = new SolidColorBrush(Colors.Red),
Foreground = new SolidColorBrush(Colors.White),
};
improveButton.SetValue(ToolTipService.ToolTipProperty, "Send an e-mail with improvements.");
improveButton.Click +=
(s, e) =>
{
};
var reviewButton = new Button
{
Content = "Review",
HorizontalAlignment = HorizontalAlignment.Right,
Background = new SolidColorBrush(Colors.Red),
Foreground = new SolidColorBrush(Colors.White)
};
reviewButton.Click += (s, e) =>
{
};
var buttonPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right
};
buttonPanel.Children.Add(improveButton);
buttonPanel.Children.Add(reviewButton);
content.Children.Add(buttonPanel);
var flyout = new Flyout
{
Content = content,
Placement = PlacementMode.Top,
PlacementTarget = page,
};
We should not forget to open the flyout.
Handling the Button clicks
We are still missing the click implementations of the buttons. So let’s do the Improve button’s click implementation. I want to show the e-mail application with a subject prefilled. This is something that I’m used to do in websites by using the mailto uri scheme this also works in Windows Style apps. To be more precise using Uri’s is one of the ways to integrate your app with apps like Mail, Maps and the Store. Sadly the Uri schemes you can use are often not that well documented, yet. But we’re lucky, the mailto scheme, is well documented.
improveButton.Click +=
(s, e) =>
{
Launcher.LaunchUriAsync(
new Uri(string.Format("mailto:{0}?subject=Improvements for {1}",
"support@someurl.com", appName.Replace("&", "%26"))));
};
That was the easy part, how do we access the Store app? We can use an Uri scheme as well, documented, but not completely. We’re lucky again, Andy Beaulieu found out a way to show the review page for an app. That information together with the knowledge that we can get the “Package Family Name” through code as well, give us this code.
reviewButton.Click +=
(s, e) =>
{
string familyName = Package.Current.Id.FamilyName;
Launcher.LaunchUriAsync(
new Uri(string.Format("ms-windows-store:REVIEW?PFN={0}", familyName)));
};
Completing
So I package the above code in side a class (toggle to view the code).
public static class PageExtensions
{
private static int ApplicationStarts
{
get
{
object val = ApplicationData.Current.RoamingSettings.Values["ReviewHelper.AppStarts"];
return val == null ? 0 : (int) val;
}
set { ApplicationData.Current.RoamingSettings.Values["ReviewHelper.AppStarts"] = value; }
}
public static void AskForReviewAfter(this Frame page, int times)
{
ApplicationStarts++;
if (ApplicationStarts != times)
{
var appName = Application.Current.Resources["AppName"] as string;
var content = new StackPanel
{
Margin = new Thickness(16)
};
content.Children.Add(new TextBlock
{
Text =
string.Format(
"Thanks for using the {0} app. Would you like to review this app?",
appName),
TextWrapping = TextWrapping.Wrap,
FontSize = 16,
});
var improveButton = new Button
{
Content = "Improvements?",
HorizontalAlignment = HorizontalAlignment.Right,
Background = new SolidColorBrush(Colors.Red),
Foreground = new SolidColorBrush(Colors.White),
};
improveButton.SetValue(ToolTipService.ToolTipProperty, "Send an e-mail with improvements.");
improveButton.Click +=
(s, e) =>
{
Launcher.LaunchUriAsync(
new Uri(string.Format("mailto:{0}?subject=Improvements for {1}",
"support@someurl.com", appName.Replace("&", "%26"))));
};
var reviewButton = new Button
{
Content = "Review",
HorizontalAlignment = HorizontalAlignment.Right,
Background = new SolidColorBrush(Colors.Red),
Foreground = new SolidColorBrush(Colors.White)
};
reviewButton.Click +=
(s, e) =>
{
string familyName = Package.Current.Id.FamilyName;
Launcher.LaunchUriAsync(
new Uri(string.Format("ms-windows-store:REVIEW?PFN={0}", familyName)));
};
var buttonPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right
};
buttonPanel.Children.Add(improveButton);
buttonPanel.Children.Add(reviewButton);
content.Children.Add(buttonPanel);
var flyout = new Flyout
{
Content = content,
Placement = PlacementMode.Top,
PlacementTarget = page,
};
flyout.IsOpen = true;
}
}
}
And I call this code just after activating the Window in the App.xaml.cs file.
// Ensure the current window is active
Window.Current.Activate();
rootFrame.Loaded +=
(s, e) =>
{
//Rootframe loaded.
Debug.WriteLine("RootFrame Loaded.");
(s as Frame).AskForReviewAfter(5);
};