This project is read-only.

Your Last About Dialog

Creating an about dialog, or something comparable, is mandatory for a Windows Phone app. In the technical certification requirements (5.6) you are required to include "easily discoverable" information about the application name, version and technical support contact options. On the other hand, statistics show that the about or help screen of an application is one of the least used features of apps (some claim something as low as only 3% of the users are accessing it). This results in the need for something that:
  • Is only loaded when the user actually requests it, to avoid unnecessary bloating of the apps memory footprint and wasting performance
  • Updates the information e.g. about the app version dynamically to minimize your efforts and to eliminate the risk of forgetting to do that manually
  • Looks good but doesn't require too much time to implement, and can be reused easily for future projects.
  • Allows you to easily extend the content with additional information or data you want to present for a particular app only.

YLAD is exactly that. It's easy to integrate into your own app, it pulls the required data from your application dynamically so you'll never forget to manually update it, it's loaded dynamically when the user requests it and still optimized to show first content as quickly as possible, and you can extend it easily with both local, static content as well as content that is fetched from a remote source and can be switched and changed dynamically even after publishing your app. In addition, the dialog supports localization. All this is achieved through configuration and doesn't require to write additional code. For more information, please scroll down.

A bit of history, and a thank you

I owe a thanks for the motivation to create this project to Jeff Wilcox, who has blogged about a similar idea back in July here. You will see that parts of the design and idea are taken from that post. However, when I tried to implement Jeff's sample code I ran into some minor problems (one of which even let me fail certification once, see below), so I improved his code, added some new features and localization support. In the end I decided that it would be a nice piece of code for others to use, in particular because Jeff did not release the source code as a separate package, so I created this project.

Features at a glance

The following is contained in the package:
  • Shows information about your app dynamically (name, version, author etc.), all of which can be overriden explicitly.
  • Shows a configurable list of hyperlinks to your web site or email addresses etc.
  • Shows a button that lets the user rate your app in the Marketplace.
  • Allows adding an arbitrary number of additional pivot items to the dialog, containing local or remote content.
  • Freely configurable fallback content for remote sources if there's no network connection or in case of network errors.
  • Supports both text content (with auto-formatting/highlighting) and XAML content.
  • Can be localized for any culture you want to support.
  • Can be styled to fit your particular needs
  • Allows pre-selecting a specific item (for example if you want to show the version history directly after your app was updated).
  • Supports trial apps in various ways

How to use

You basically have two options to make use of YLAD:
  • Download the package from CodePlex, reference the included assembly in your project, then follow the configuration steps below OR
  • Use NuGet to pull the dialog into your project from within Visual Studio (recommended)

Using NuGet

When you use NuGet (recommended), you can either use the package manager UI and search for the "ylad" package, or install that package from the command line. The benefit of installing the library using NuGet is that the component is automatically referenced in your project, and a sample configuration as well as the default styles file is automatically added to the right place, with the correct build actions set. This means you can get up and running with only a single line of code!

Navigating to the about dialog

Integration of the dialog into your app is extremely simple. Use the navigation service of a page or other ways of navigation to go to the about page:

NavigationService.Navigate(new Uri("/YourLastAboutDialog;component/AboutPage.xaml", UriKind.Relative));

This can be put in the click event handler of an application bar button, or any other place you want to invoke the about dialog at.

You can use query strings to determine what pivot item should be pre-selected, for example if you want to show the version history after your application has been updated:

  string url = string.Format("/YourLastAboutDialog;component/AboutPage.xaml?{0}={1}", AboutPage.SelectedPivotItemIndexKey, 1);
  NavigationService.Navigate(new Uri(url, UriKind.Relative));

Instead of specifying the index, you can also use the item header for this. Remember that you need to determine the correct header value dynamically when you support multiple languages. This parameter is case-sensitive.

  string url = string.Format("/YourLastAboutDialog;component/AboutPage.xaml?{0}={1}", AboutPage.SelectedPivotItemHeaderKey, "history");
  NavigationService.Navigate(new Uri(url, UriKind.Relative));

Configuration

YLAD uses an XML file for configuration, and a convention based approach to load it: the file must be named "Data.xml" and located in the "Content/About" folder of your application. If you have pulled the dialog from the NuGet library, this file has been created and added automatically for you.

[image:data-xml.png]

The build action for the file needs to be "Content". The general format of the configuration is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<About>
  <App />
  <Items>    
    <MainItem>
      <Links>        
        <Link />
		<Link />
		<!-- ... -->
      </Links>
    </MainItem>    
    <Item />
	<Item />
    <!-- ... -->
  </Items>
</About>

The following sections describe the individual configuration options for each element.

The "App" element

The App element is a reflection of the information that is located in WMAppManifest. The dialog pulls the information from the manifest automatically, but specifying any of the following attributes takes precedence over the manifest values and allow you to override them. I recommend overriding at least the author/publisher information, see below.
  • Title: Overrides the title attribute value from the WMAppManifest.xml file. Important: If you are using App title localization as described on MSDN, then you need to make use of this attribute and override the title manually to get correct results. More on this issue can be found in this blog post.
  • Author: Overrides the author attribute value from the WMAppManifest.xml file.
  • Description: Overrides the description attribute value from the WMAppManifest.xml file.
  • Publisher: Overrides the publisher attribute value from the WMAppManifest.xml file.
  • Version: Overrides the version attribute value from the WMAppManifest.xml file.
  • AdditionalNotes: There's no equivalent of this value in the WMAppManifest.xml file, you can only specify its content here.
  • FullVersionProductId: There's no equivalent of this value in the WMAppManifest.xml file, you can only specify its content here. This is only relevant for trial/lite app scenarios (see below).

I recommend using the author/publisher attribute to override what's written in the WMAppManifest.xml file. The reason for this is that the WMAppManifest is rewritten during the submission process to the Marketplace. Apparently it depends on the type of account that you have whether this processing will add author OR publisher information. For example, my Marketplace account is a company account, and even though I had my author name in the manifest file, the author node was completely removed during that processing, resulting in that piece of information missing afterwards (which in turn let the app fail certification). Because of that, the default config file created by the NuGet installation already contains placeholders for the author and publisher, to encourage you to override this information manually.

You should not override the version or other information or you'll lose the benefit of the dialog updating that information automatically when you change it in the project settings.

You can explicitly set those entries to empty strings to hide them (including their labels) from the dialog. This is useful if you don't want to show certain data (e.g. a publisher string) or don't have additional notes or similar..

A sample looks like this:
<!-- Overrides the author, sets some additional notes. 
     The publisher information is removed from the about dialog (including the label).
     All other information (version, app name etc.) is taken from the manifest. -->
<App Author="[Your name here]"
   Publisher=""       
   AdditionalNotes="[Fill in additional info here]" />

The "MainItem" element

You can specify the content of all labels contained on the main item to override the default values. This allows you to change that to something you like, or to localize the main item to a desired language (more on that see below). The MainItem contains a collection of Links items that you can use to specify a list of hyperlinks you want to appear in the dialog.

Possible attributes of the MainItem element:
  • Title: Overrides the title of the pivot item. Default is "about"
  • AppAuthorLabel: Overrides the label used for the author name. Default is "by"
  • AppDescriptionLabel: Overrides the label used for the description. Default is "Description:"
  • AppPublisherLabel: Overrides the label used for the publisher. Default is "Publisher:"
  • AppVersionLabel: Overrides the label used for the version. Default is "Version:"
  • AppAdditionalNotesLabel: Overrides the label used for the additional notes. Default is "Additional Notes:"
  • AppReviewButtonContent: Overrides the content used for the rate button. Default is "Review this app!". Set the value of this attribute to an empty string to force hiding of this button.
  • AppBuyButtonContent: Overrides the content used for the buy button. Default is "Buy this app!". By default this button is only shown when the app is running in trial mode. Set the attribute value to an empty string to force hiding, even if the app is a trial mode app. More on trial mode below.

A sample looks like this:
<!-- A bit pointless, because all values are overridden to the default values :) -->
<MainItem Title="about"
		  AppAuthorLabel="by"
		  AppDescriptionLabel="Description:"
		  AppPublisherLabel="Publisher:"
		  AppVersionLabel="Version:"
		  AppAdditionalNotesLabel="Additional Notes:"
		  AppReviewButtonContent="Review this app!">
  <Links>
  <!-- ... -->

The "Link" elements

Each link entry contains of three parts: the url to use for navigation, the content to display as hyperlink, and a label text placed in front of the hyperlink that is not part of the actual hyperlink. This means that three attributes need to be set:
  • NavigateUri: Specifies the uri to use for navigation. Doesn't need to be a web site (http://), can also point to an email address (mailto:) or other supported protocols.
  • Content: Specifies what is used as content for the hyperlink button
  • Label: Specifies the content of the label in front of the hyperlink.

You can add as many hyperlinks as required. A sample of a single entry looks like:
<Link NavigateUri="http://www.example.com"
      Content="http://www.example.com"
      Label="Web site:" />

Additional Items (the "Item" elements)

You can add additional pivot items easily by adding Item elements to the Items collection, next to the MainItem element. An Item element supports three attributes for the title, the (optional) Uri of the remote content, and the type of the content. In addition, Item elements support direct content which is either treated as static content (no Uri given), or as fallback content if the remote content could not be retrieved.
  • Title: This attribute specifies the title of the pivot item that is created.
  • Type: Specifies the type of content, which only supports "xaml" or "text" at the moment.
  • Uri: The remote url the content should be fetched from. If this attribute is missing, the dialog does not fetch remote content but uses the element content for display.

A sample of an item entry looks like this:
<!-- The title of the pivot item will be 'more', and the item will display Xaml content
     retrieved from http://localhost/SampleRemoteXamlFile.xaml, unless there's no network
	 connection; then it will display "With network access, you..." instead -->
<Item Title="more"
	  Uri="http://localhost/SampleRemoteXamlFile.xaml"
	  Type="xaml">
  With network access, you can see more information here.
</Item>

The sample code shows an interesting twist: The fallback content can be of type text instead of Xaml. If the dialog fails to parse the fallback content as Xaml, it will treat it as normal text instead automatically.

Local and remote Xaml

The remote Xaml file obviously cannot contain a code-behind file or additional C# code. However, you are free to add and use any features that can be included in Xaml you like. This includes references to locally available components (local to the application installation) that are not part of the runtime. A normal workflow would for example be to create this Xaml page in your application (using Visual Studio or Expression Blend) and then remove the code behind file (and the class reference in Xaml) before you upload it to your server.

Local item content can also consist of Xaml. To avoid pollution of the configuration file with potentially large definitions of Xaml content, you can create a user control in your project, and then only reference that user control from within the configuration file. The only twist with that is that you need to specify the namespace correctly, so the runtime knows where to find the component. This means that something like is totally valid to do:

<Item Title="tutorial"
      Type="xaml">
  <my:TutorialView xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:my="clr-namespace:MyApp.Views;assembly=MyApp"
                   HorizontalAlignment="Stretch"
                   VerticalAlignment="Top" />
</Item>

This enables you to cleanly design new and additional pages for your about dialog using the tools you'd normally use, and then integrate these pages using a single element entry in the configuration file.

Auto-highlighting of text content

Text content is automatically highlighted. The algorithm that does this simply takes every line that is preceded by an empty line and highlights it (including the very first line). This means that e.g. a text version history like this:

<Item Title="history"	  
	  Type="text">
  1.0.0.0
  This release includes the following changes:
  - Added a fantastic new feature
  - Added another feature
  - Removed feature Z because
  - Fixed issue with Y

  0.9.0.0
  This release includes the following changes:
  - Updated dependent libary Z
  - Added support for Mango
  - Fixed bug #1024

  0.8.0.0
  This is the initial public version.
</Item>

...will be automatically converted to an output like this:

version-highlighting-small.png

Localization

To localize the dialog, there's a simple algorithm built into the library that works as follows:

localization-algorithm.png
As you can see, the dialog first tries to find a localized configuration file (based on the current culture), which can be provided either for a particular country/region, or for a specific language. The detailed logic is:
  • If there's a file named "Data.[culture name].xml", it will be used
  • If not, then the logic looks for a file named "Data.[two-letter ISO language code].xml"
  • If there's also no language specific file, the invariant file "Data.xml" will be used.

Example:

Let's say you have an invariant file "Data.xml" (that effectively contains English resources). In addition you want to support German language settings for your users. Do that by adding a file named "Data.de.xml" which contains the German translations. If you further want to provide specific resources only to Austrian users, you would create yet another file "Data.de-AT.xml". With this setup...
  • ... "Data.de-AT.xml" will only be used if the current culture is set to Austrian (de-AT).
  • ... "Data.de.xml" will be used for all German cultures except Austrian (e.g. de-DE, de-CH etc.).
  • ... "Data.xml" will be used for any other culture setting.

This approach allows you to use separate configuration files for each culture, where you can translate both the content of your attributes and elements to the language in question as well as point Uri properties to different remote resources that are also translated. For example, if the version history in the normal "Data.xml" looks like this:

<Item Title="history"	  
      Uri="http://localhost/version-history.txt"
	  Type="text">
  Fallback text for the version history.
</Item>

... then in a localized configuration file for German ("Data.de.xml"), the same section could look like:

<!-- Point to version-history.de.txt instead -->
<Item Title="history"	  
      Uri="http://localhost/version-history.de.txt"
	  Type="text">
  Ersatzinhalt für die Versionshistorie.
</Item>

Note that not only a translated local text is used, but the url also points to a different remote resource that in turn has localized content.

Styling

Starting from version 2.0, YLAD creates a default styles file when you install it from NuGet. The file is named "AboutStyles.xaml" and located in the "Content/About" folder of your project. If you create the file manually (e.g. adding it from the CodePlex release package), make sure that the build action is set to "Content" (installing from NuGet does this automatically for you too).

Available styling options

Technically, the styles file contains a resource dictionary that has entries for all of the styles used by YLAD internally. In particular, you can target styles to all of the following elements individually:
  • PhoneApplicationPage (Key: AboutPageStyle) - allows you to set all the properties of the phone page that displays the about content.
  • Pivot (Key: AboutPivotStyle) - the style for the pivot control that is the root content element of the about page.
  • PivotItem (Key: AboutPivotItem) - you can set the general style of the pivot items here.
  • TextBlocks (Keys: AboutTextTitleStyle, AboutTextSubTitleStyle, AboutTextNormalStyle, AboutTextNormalHighlightedStyle) - these are the different text-based styles used by YLAD for captions, text and highlighted parts.
  • HyperlinkButton (Key: AboutHyperlinkButtonStyle) - allows you to modify the style used for the hyperlinks shown on the about page.
  • Button (Key: AboutButtonStyle) - can be used to change the looks of the buttons YLAD shows (like the rate or buy buttons, if applicable).

Sample: Showing the System Tray

The styles can be used like any other styles you're used to. This means that you can also use them to set attached properties like the visibility of the System Tray at the page level. The following demonstrates how to define the "AboutPageStyle" to enable the System Tray on the about page:

<Style x:Key="AboutPageStyle"
       TargetType="controls:PhoneApplicationPage">
  <!-- ... -->
  <Setter Property="shell:SystemTray.IsVisible" Value="True" />
  <!-- ... -->
</Style>

For more samples, take a look at the comments in the "AboutStyles.xaml" file. It contains sections that describe various scenarios, like adding page transitions (from the Silverlight Toolkit), or changing foreground and background colors.

Trial Mode

The project supports applications that run in trial mode. The default behavior is: YLAD checks the LicenseInformation.IsTrial() method to get information about whether the app runs in trial mode or not. If it does, a button labeled "Buy this app!" is shown on the about page, just below the "Review this app!" button. When the user taps the button, they are taken to the detail page of the app in the Marketplace, where they then can make the purchase. You can change this default behavior in the following ways:

Force trial mode support off

If you do not want to expose the buy functionality from the about page (e.g. because you have covered this by other means somewhere else in your application), you can simply set the "AppBuyButtonContent" attribute value of the "MainItem" to an empty string. This will hide the button from the about page:

<!-- Hide the buy button even when the app is running in trial mode -->
<MainItem Title="about"
          AppBuyButtonContent="">
...

Force trial mode support on

In some cases you may want to show the buy button even when your app is not running in trial mode. There's a certain pattern some app authors are using that works in that a "lite" version of a paid app is submitted to the Marketplace. This "lite" version is made available for free, which tends to attract more people than trial-mode enabled paid apps. Technically, the "lite" and paid version of the app are two different products. To support a buy mechanism, the "lite" app has to take the user to a different app (the paid version) in the Marketplace to perform the purchase. YLAD supports this in the following way:
  • Specify the Id of the product you want to take the user to in the Marketplace by using the "FullVersionProductId" attribute on the "App" element in the configuration file (see the documentation on the "App" element above). This forces YLAD to use the alternate Id for the Marketplace Details task, instead of the Product Id of the current app.
  • Optional: Specify a different buy button content in the "AppBuyButtonContent" attribute on the "MainItem" element in the configuration (see the documentation on this above), to make it clear to the user they're buying a separate paid full version of your product.
  • When navigating to the about page, specify a query parameter that forces YLAD to show the buy button, even though the app is not running in trial mode:

  string url = string.Format("/YourLastAboutDialog;component/AboutPage.xaml?{0}=True", AboutPage.ForceBuyButtonKey);
  NavigationService.Navigate(new Uri(url, UriKind.Relative));

You can dynamically adjust this parameter depending on you personal preferences, to show/hide the button whenever you want (for example, if you're able to detect that the user has bought your full version app, you can remove that parameter to hide the buy button).

What else?

You can also take a look at the source code which includes a sample project with some examples for all kinds of configuration options. Also, if you find any bugs or have feature requests, feel free to use the issue tracker or contact me.

About me

My name is Peter Kuhn ("Mister Goodcat"), and among much other I'm a Windows Phone enthusiast :).
You can learn more about me here, and read more from me on my blog, or follow me on Twitter.

Last edited Apr 30, 2012 at 6:31 PM by Mister_Goodcat, version 8

Comments

rajah Feb 12, 2012 at 6:30 AM 
Awesome! thank you!

uxadditives Feb 11, 2012 at 1:43 PM 
Thanks a lot! very useful.

CtrlAltDel Jan 31, 2012 at 12:01 PM 
This is awesome! Now we need a WPF version...

janierdavila Nov 8, 2011 at 12:02 PM 
Awesome idea! Will use in all my projects. Thanks. While populating the Additional Notes section I had the need to have spaces within my paragraphs. Simple entering space separated paragraphs on the Data.xml does not work. Of course, this is a xaml thing. I added &#13; to create space. Hope it helps somebody.

Thank you