Implement Settings Popup Pages for Windows Store Apps

Preface

No, this is not the first sample to be found in the internet on this topic. Anyway, I decided to add another one because the two I was looking at (see links below) gave good ideas, but did not satisfied me at all.

Changes to App.xaml.cs

To begin, new items need to be added to the settings charm somehow. I did this by changing the app.xaml.cs. This is my starting point here.

First thing is to add a new using statement:

using Windows.UI.ApplicationSettings

Next, we need to know when to add our items to the settings charm. The class SettingPane has an event called CommandsRequested, which “… occurs when the user opens the settings pane. Listening for this event lets the app initialize the setting commands and pause its UI until the user closes the pane.” (description copied from MSDN docs).

So I added an event handler as the last statement of the App.OnLaunched method.

SettingsPane.GetForCurrentView().CommandsRequested 
  += OnSettingsCommandsRequested;

The handling method OnSettingsCommandsRequested is implemented in this sample like this:

private void OnSettingsCommandsRequested
  (
  SettingsPane settingsPane,
  SettingsPaneCommandsRequestedEventArgs args
  )
{
  args.Request.ApplicationCommands
    .Add(new SettingsCommand("about", "About", OnSettingsInvoked));

  args.Request.ApplicationCommands
    .Add(new SettingsCommand("popupHeaderBackgroundSlidesIn", 
     "Background slides in", OnSettingsInvoked));

  args.Request.ApplicationCommands
    .Add(new SettingsCommand("popupHeaderWithoutTransition", 
     "Header without transition", OnSettingsInvoked));

  args.Request.ApplicationCommands
    .Add(new SettingsCommand("popupHeaderWithTransition", 
     "Header with transition", OnSettingsInvoked));
}

As you can see, no matter which command is selected by the user, the method OnSettingsInvoked is called. Because the SettingsCommand constructor takes a settingsCommandId as first parameter, I am able to distinguish between the actions to be taken inside OnSettingsInvoked. Of course, one can also implement different handlers for each new command. I decided to us a single one in this sample because the action to be taken is very similar.

private void OnSettingsInvoked
  (
  IUICommand command
  )
{
  // Get the command id.
  string commandId = command.Id as string;

  // Has to be set, otherwise return.
  if (commandId == null)
  {
    return;
  }

  switch (commandId)
  {
    case "about":
      OpenSettingsPage<AboutPage>();
      break;
    case "popupHeaderBackgroundSlidesIn":
      OpenSettingsPage<HeaderBackgroundSlidesInPage>();
      break;
    case "popupHeaderWithoutTransition":
      OpenSettingsPage<HeaderWithoutTransitionPage>();
      break;
    case "popupHeaderWithTransition":
      OpenSettingsPage<HeaderWithTransitionPage>();
      break;
    default:
      break;

  }
}

The magic of opening a settings popup page is encapsulated by the method OpenSettingsPage<TPage>. It takes a type parameter to know what kind of popup page should be created. The type needs to be derived from SettingsPageBase to make sure the correct kind of page will be opened.

private void OpenSettingsPage()
  where TPage : SettingsPageBase, new()
{
  SettingsPopup = new Popup();

  SettingsPopup.IsLightDismissEnabled = true;
  SettingsPopup.Width = App.SettingsPopupWidth;
  SettingsPopup.Height = Window.Current.Bounds.Height;

  // Add the proper animation for the panel.
  SettingsPopup.ChildTransitions = new TransitionCollection();
  SettingsPopup.ChildTransitions.Add(new PaneThemeTransition()
  {
    Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ?
           EdgeTransitionLocation.Right :
           EdgeTransitionLocation.Left
  });

  // Create a SettingsFlyout the same dimenssions as the Popup.
  TPage settingsFlyout = new TPage();
  settingsFlyout.Width = SettingsPopup.Width;
  settingsFlyout.Height = SettingsPopup.Height;

  // Place the SettingsFlyout inside our Popup window.
  SettingsPopup.Child = settingsFlyout;

  // define the location of our Popup.
  SettingsPopup.SetValue(Canvas.LeftProperty, 
    SettingsPane.Edge == SettingsEdgeLocation.Right 
    ? (Window.Current.Bounds.Width - SettingsPopup.Width) 
      : 0);
  SettingsPopup.SetValue(Canvas.TopProperty, 0);
  SettingsPopup.IsOpen = true;
}

It is worth to mention that SettingsPopup is a property of the App class. When implementing my first settings pages, I made this a local variable. But whenever I clicked somewhere into the main window while the settings page was open, my app crashes. I was not able to debug the problem. Even no UnhandledException handler helped me out.

SettingsPageBase

To avoid copy & paste development for the back button click handler, I created a base class for the settings pages. This is the class SettingsPageBase, located in the Common folder. The handler’s task is to close the Popup and re-open the settings charm when the back button is pressed.

protected virtual void OnGoBack
  (
  object sender,
  RoutedEventArgs args
  )
{
  // First close our Popup.
  Popup parent = this.Parent as Popup;

  if (parent != null)
  {
    parent.IsOpen = false;
  }

  // If the app is not snapped, then the back button shows the Settings pane again.
  if (ApplicationView.Value != ApplicationViewState.Snapped)
  {
    SettingsPane.Show();
  }
}

Mastering the Transition

When you open up the settings charm of this sample app, you will notice three different settings items: “Background slides in”, “Header without transition”, and “Header with transition”. You might ask why this. The answer is, that these are the three kinds of transitions I noticed when I was starting with settings pages. And it took me a while to figure out why my first attempts did not look the way I expected it (Header with transition).

Background slides in

When you open the “Background slides in” page, look at how the header block behaves, especially the background. It slides in, together with the button, text and logo. So when the page pops in, there is a tiny block on the left where the background color is the page’s background, not to the header’s.

The header controls slide in as expected, together with the content of the page, but that did not satisfied me. So I dig into the samples, because they did not behave that way. There, I found the next version:

Header without transition

On this page, the background of the header is set correctly. No slide in. But also, no slide in of the button, text, and image. Their position is fixed in relation to the upper left corner even when the page opens, while the describing text slides in. So still not satisfied (and not comply with the UX requirements).

Header with transition

This is the way I like it. The background is not sliding, while the header’s controls do, together with the page’s content.

To get this done, I had to change different things. When you find an easier way, I would be happy if you post it in a comment.

First, the root element of the page must not contain any Transitions definition. So no child element will slide in by default.

The settings pages consists of a Grid having two rows. One for the header, one for the content.

I put two Grids into the header row. The first, without transition, to have the background be in place when the page pops in. The second, containing the back button, text, and image, with a transition definition:

<Style x:Key="SettingsHeaderContentStyle" TargetType="Grid">
  <Setter Property="Transitions">
    <Setter.Value>
      <TransitionCollection>
        <EntranceThemeTransition/>
      </TransitionCollection>
    </Setter.Value>
  </Setter>
</Style>

This makes sure only the content of the header will slide in.

And because the root element of the page does not contain any transition definitions, also the content part, which is a StackPanel in the second row of the main Grid in my sample, needs the same transition definition.

All application-specific styles can be found in Common/ApplicationStyles.xaml.

UX Design Requirements

This app satisfies the following UX design requirements (all copied from Windows 8 User experience guidelines):

  • Place your settings Flyout on the same side of the screen as the charms. The charms and the settings window may be on the left side of the screen if the system’s text direction is right-to-left (like Arabic).
  • Settings Flyouts should be narrow (346 pixels) or wide (646 pixels).
  • Settings Flyouts should have a header that includes a back button, the name of the entry point that opened the Flyout, and the app’s icon (small one, 30x30px).
  • Use a light-dismiss surface, so that the settings Flyout disappears when the user touches anywhere on the screen outside of the surface.

The Dev Center sample “Settings Flyout” names a few more requirements, which I was not able to find in the guidelines. But they all seem reasonable, so I will list them here too:

  • Height has to be 100% of the screen.
  • Header is 80px high.
  • Header’s background must match the start tile’s background (from the manifest).
  • Flyout’s border must be darker than the header’s background (80% of its value). For instance, the background color in the example below is #999999, so the boarder color is rgb(0.8 * #99, 0.8 * #99, 0.8 * #99), which is rounded to #797979a.
  • The background of the main content area must be white. This can cause a problem if your app requests the dark theme; the text foreground color is white in the dark them, which renders it invisible when the background color is white. To request the light theme, set RequestedTheme="Light" in the app.xaml.
  • Both of the header’s and content’s controls must be animated.

The Sample Code

can be found here. To build an run the sample, you need Windows 8 and Visual Studio 2012.

Sample Screenshot

Links

Guidelines for app settings (Windows Store apps)

Store apps UX Guidelines Index

Dev Center Settings Flyout sample

Dev Center App settings sample (Windows 8)

Use OpenFileDialog and FileBrowserDialog in WPF

WPF does not contain a OpenFileDialog or FileBrowserDialog. Nevertheless, I needed them in a WPF application.

Searching the web, I found several approaches. One published on GitHub (https://github.com/tillias/wpFolderPicker) implements a new control for folder browsing. But I wanted a “cheap” solution. And found the starting point here: WPF OpenFileDialog and FolderBrowserDialog.

Ben suggested to add WindowsFormsIntegration to the project’s references. That did not worked for me (.NET 4.5, VS 2012). But adding System.Windows.Forms to the references and using statements made the OpenFileDialog and FileBrowserDialog working in my WPF application 🙂

Microsoft Advertising Services AdControl Transition in XAML/C#

Preface

According to the documentation, AdControls are hosted in a WebView control. For some reasons I was not able to figure out, WebView controls do not slide in when a page loads (or pop in, whatever the correct wording is). This means that your AdControl will not slide in neither.

Now imagine the following: You have created a great page including an AdControl. When the page is opened, all content slides in, except the AdControl. Would you like that? I do not.

Make AdControls Sliding

For all who are familiar with transitions and storyboards in XAML, this won’t bring much or any news. For those who are not, like I was when using AdControls the first time, this might help save some time.

The key is to add a Storyboard to the page containing the AdControl. And luckily, there is a predefined ThemeAnimation to do the pop in: the PopInThemeAnimation. Here is a sample:

<Page.Resources>
  <Storyboard x:Name="PopInStoryboard">
    <PopInThemeAnimation 
        Storyboard.TargetName="AdControlPanel728x90" 
        FromHorizontalOffset="120" 
        SpeedRatio=".3"/>
  </Storyboard>
</Page.Resources>

The Storyboard.TargetName is the name of the control to animate. In case you use the AdControl configuration presented in the post Configure Microsoft Advertising Services’ AdControl using XAML/C#, make sure that you assign the name to the dynamically created AdControl. The class AdControlContainingPage of the sample takes care of it.

The FromHorizontalOffset “… sets the distance by which the target is translated in the horizontal direction when the animation is active” (description copied from MSDN online docs). Unfortunately, the docs don’t say what the reference point is. So you have to play around a little bit to make sure the AdControl slides in the same distances as the other controls do. In my sample, it was almost the left margin of topmost panel – but only almost, not always.

The SpeedRatio is “… a finite value greater than 0 that specifies the rate at which time progresses for this timeline, relative to the speed of the timeline’s parent. If this timeline is a root timeline, specifies the default timeline speed. The value is expressed as a factor where 1 represents normal speed, 2 is double speed, 0.5 is half speed, and so on.” (description copied from MSDN online docs). In my experience, the value of 0.3 makes the AdControl slide in as fast as the other controls.

Adding the storyboard is only on half of the work. The other part is to make the storyboard run.

// Run storyboard if one exists.
Storyboard storyboard = FindName("PopInStoryboard") as Storyboard;

if (storyboard != null)
{
  storyboard.Begin();
}

I put this code sniped into the LoadState method of my AdControlContainingPage base class, which is derived from LayoutAwarePage. LoadState is called when the page is about to be displayed. I think this is a good place to start transitions.

The AdControlContainingPage is the base class of all pages containing AdControls. So I just have to define the StoryBoard in the XAML, and I am done 🙂

Links

The AdControl animation is part of the sample code of the post Configure Microsoft Advertising Services’ AdControl using XAML/C#, where you can download the code.

Configure Microsoft Advertising Services’ AdControl using XAML/C#

Preface

The Microsoft Advertising SDK for Windows 8 allows developers to show ads in their apps. When you look at the walkthrough for putting ads in an app using XAML/C#, you can see that you have to set the ApplicationId and AdUnitId property of each AdControl control in your app.

For testing purposes, Microsoft has defined the ApplicationId d25517cb-12d4-4699-8bdc-52040c712cab and several AdUnitIds (can be found on the Test Mode Values page). These values are required in case you have no ids created in the pubCenter for yourself or in case you want to test your app in the emulator. (Well, on my machine the emulator showed productive ads even though the docs says it does not.)

Since I do not want to change my app every time I switch between the emulator and my dev machine, I was looking for a way to make these setting configurable.

Where to Store the Configuration Data?

In common .NET applications, the answer to this question is very simple: put it in the app.config. Unfortunately, for Windows Store apps the app.config approach is not available, or at least not offered by .NET for Windows Store apps.

So I built my own app.config mimic. Please have a look at the post Mimic app.config in Windows Store Apps for further details.

How to Change the Values During Runtime?

My first try was to define the AdControls in the XAML file and change both ApplicationId and AdUnitId in the constructor of the page’s class right after the call to PageClass.InitializeComponent. After receiving “NoAdAvailable” errors (which shows how important it is to implement an error event handler for AdControls), I had a look at the documentation.

In the remarks to the AdUnitId property the docs says that “This property can be set only when the AdControl is instantiated using the default constructor. Once set, this property cannot be modified.” The ApplicationId can be changed whenever you want. But that won’t help, because ApplicationId and AdUnitId are strongly tied together. Means, an AdUnitId is only valid in conjunction with its corresponding ApplicationId.

This means I cannot change the AdUnitId of all the AdControls that are defined in the XAML. Bad news? Not that bad – because we can also create UI controls during runtime, not only in XAML!

The AdControl Replacement Approach

After playing around a little bit I was choosing a replacement approach. This means that I define AdControls in XAML, and replace them during page initialization with those AdControls having the correct values for Application- and AdUnitId.

I prefer this approach because it offers the ability to check the look of the page also during design time, not only at runtime. So it is much easier to see if the page looks good. This requires me to set the (matching) height and width of the AdControls properly both in the XAML and configuration.

There is one prerequisite to use the replacement approach the way I implemented it: the AdControl to be replaced has to be a child control of a Panel (or derived class). Otherwise it is not possible to put the new AdControl at the place where the old one was.

The definition of the required config values is encapsulated by the class AdControlConfigData. The class looks like this:

public class AdControlConfigData
{
  [XmlAttribute]
  public string AdControlName { get; set; }

  [XmlAttribute]
  public string AdUnitId { get; set; }

  [XmlAttribute]
  public double Height { get; set; }

  [XmlAttribute]
  public double Width { get; set; }
}

The corresponding serialized data in the app.config looks like this:

<AdControlConfigData AdControlName="AdControl300x600" 
  AdUnitId="10043030" Width="300" Height="600"/>

The value of the ApplicationId is not part of this container. It is defined as a simple and single value in the app.config, since it is the same for all AdControls.

Replace the AdControls

In the sample code, I created a class called AdControlContainingPage, which is derived from LayoutAwarePage. This class is the base class of all pages containing AdControls. It holds all the functionality required to replace them, plus a basic handler for AdControl errors.

The XML config data is read by the ConfigurationManager class introduced in the Mimic app.config in Windows Store Apps post, also the XmlDeserialize used later.

For the sample app, the content of the app.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<!-- Configuration settings for Debug Build -->
<configuration>
  <appSettings>
    <!-- Use Microsoft Advertising Services Test ApplicationId -->
    <add key="AdApplicationId" 
            value="d25517cb-12d4-4699-8bdc-52040c712cab"/>
  </appSettings>

  <AdControlConfigList300x600>
    <AdControlConfigData AdControlName="AdControl300x600" 
          AdUnitId="10043030" Width="300" Height="600"/>
  </AdControlConfigList300x600>

  <AdControlConfigList300x250>
    <AdControlConfigData AdControlName="AdControl300x250" 
          AdUnitId="10043056" Width="300" Height="250"/>
  </AdControlConfigList300x250>

  <AdControlConfigListMultiple>
    <AdControlConfigData AdControlName="AdControl160x600" 
          AdUnitId="10043136" Width="160" Height="600"/>
    <AdControlConfigData AdControlName="AdControl728x90" 
          AdUnitId="10042998" Width="728" Height="90"/>
  </AdControlConfigListMultiple>
</configuration>

The different AdControlConfigData entities are extracted by the method AdControlContainingPage.GetAdControlConfiguration, which is shown here:

private static List<AdControlConfigData> GetAdControlConfiguration
  (
  XmlDocument xmlConfig,
  string sectionName
  )
{
  List<AdControlConfigData> configDataList 
    = new List<AdControlConfigData>();

  XmlNodeList xmlConfigDataList 
    = xmlConfig.DocumentElement
      .SelectNodes(
        String.Format("./{0}/AdControlConfigData", sectionName));

  foreach (IXmlNode node in xmlConfigDataList)
  {
    AdControlConfigData configData 
     = XmlDeserializer.Deserialize<AdControlConfigData>(node);

    configDataList.Add(configData);
  }

  return (configDataList);
}

Now that we have the configuration settings as a list of objects, which is really easy to handle, we can go on to replace the controls. This is done by AdControlContainingPage.ReplaceAdControls.

private void ReplaceAdControls
  (
  List<AdControlConfigData> adControlConfigDataList,
  string adApplicationId
  )
{
  // iterate over the list of configured AdControls.
  foreach (AdControlConfigData configData in adControlConfigDataList)
  {
    // Find the AdControl to be replaced.
    AdControl oldAdControl 
      = FindName(configData.AdControlName) as AdControl;

    // If the oldAdControl is not found, we can't replace it. So try the next one.
    if (oldAdControl == null)
    {
      Debug.WriteLine(String.Format("AdControl name >{0}< not found", configData.AdControlName));
      continue;
    }

    // Get the parent of the adcontrol. Needs to be a kind of panel.
    Panel parent = oldAdControl.Parent as Panel;

    // If the parent is not a panel, try the next one.
    if (parent == null)
    {
      Debug.WriteLine(String.Format("AdControl name >{0}< is not placed inside a panel or derived class. AdControl cannot be replaced.",
        configData.AdControlName));
      continue;
    }

    // Keep the position of the old AdControl.
    int postion = parent.Children.IndexOf(oldAdControl);

    // and remove it
    parent.Children.RemoveAt(postion);

    // Create the new AdControl with the correct ApplicationId and AdUnitId.
    AdControl adControl = new AdControl()
    {
      ApplicationId = adApplicationId,
      AdUnitId = configData.AdUnitId, // From msdn: This property can be set only when the AdControl is instantiated. Once set, this property cannot be modified.
      HorizontalAlignment = HorizontalAlignment.Left,
      Height = configData.Height,
      IsAutoRefreshEnabled = true,
      VerticalAlignment = VerticalAlignment.Top,
      Width = configData.Width
    };

    // Add the error hander
    adControl.ErrorOccurred += OnAdControlErrorOccurred;

    // Add the new control to the parent at the correct position.
    parent.Children.Insert(postion, adControl);
  }
}

The orchestration of these activities is done by AdControlContainingPage.SetupAdControls, which looks as follows:

protected async void SetupAdControls
  (
  string configSectionName
  )
{
  try
  {
    // Load the app.config.
    XmlDocument xmlConfig = await ConfigurationManager.GetConfig();

    // Get the AdApplicationId
    string adApplicationId 
      = ConfigurationManager
        .GetAppSettingsValue(xmlConfig, "AdApplicationId");

    // Extract the AdControl config data from the XML into a object list.
    List<AdControlConfigData> adControlConfigDataList 
      = AdControlContainingPage
        .GetAdControlConfiguration(xmlConfig, configSectionName);

    // Replace the AdControls
    ReplaceAdControls(adControlConfigDataList, adApplicationId);
  }
  catch (Exception e)
  {
    Debug.WriteLine(String.Format("Exception occurred:{0}{1}", 
      Environment.NewLine, e));
  }
}

One should call AdControlContainingPage.SetupAdControls right after the call of InitializeComponent of the derived class. In the sample, the derived classes are SamplePage300x250, SamplePage300x600, and SamplePageMultiple, which can be found in the SubPages folder of the solution.

The Sample Code

can be found here. To build and run the sample, you need to have the Microsoft Advertising SDK for Windows 8 installed. Have fun 🙂

Load It From The Windows Store

A slightly extented version of the sample can also be found in the Windows Store.

And finally, some screenshots of the sample app.

Main Page

Sample Page

Sample Page

Sample Page

Make Custom Class Item Templates for Windows Store Apps Visible in VS 2012

Make the Item Visible

One very helpful feature of Visual Studio is the ability to create custom item or project templates. I’m using this feature for years to get a pre-formatted C# class, containing several regions.

In VS 2012, one can set the directory where these custom item templates are located via “Tools / Options / Projects and Solutions” dialog. This folder contains several subfolders for some categories, i.e. JavaScript, Visual Basic, or Visual C#. These were the places where to put the appropriate custom item templates.

The first thing that has changed in VS 2012 (at least Update 3, can’t recall if this has changed before) compared to VS 2010 is that you have to create a “My Templates” folder below the corresponding one. Means, if I have a custom C# class item template, it has to be put into “C:\Users\nnn\Documents\Visual Studio 2012\Templates\ItemTemplates\Visual C#\My Templates” to be shown in the “My Templates” section of the “Add New Item” dialog.

But this did not work for all kinds of project types. At least, it does not work for Windows Store app projects. Even though the item template is located at the right place, it is not listed by the “Add New Item” dialog. Of course it is listed in a Windows console app project.

For whatever reason, the Windows Store app project requires an additional setting in the vstemplate file, which is part of the item template zip file. This setting is the element <TemplateID>Microsoft.CSharp.Class</TemplateID> inside the <TemplateData> section. Putting the updated vstemplate into the class item zip, the template is also listed in the “My Templates” section of the “Add New Item” dialog in Windows Store app projects. The TemplateID is not generated when exporting the template by VS.

You might notice too, that from the moment on when the TemplateID is added, the item template will be listed twice for other project types, i.e. Windows console application.

After making these changes, I had some issues with the item template cache (retrieving an error when selection one of the duplicates in the list). I just deleted the directory ItemTemplatesCache in “C:\Users\nnn\AppData\Roaming\Microsoft\VisualStudio\11.0”.

How to Create a Custom Item Template

In case you hadn’t created a custom item template yet, have a look at How to: Create Item Templates.

On my VS 2012 installation, the “Export Template…” menu item was not part of the File menu. So I had to add it using the “Tools / Customize” dialog. Switched to the “Commands” tab, selected “Menu bar”, “Add Command”, selected “File” from the categories, and already found the missing item.

Exporting the template, it will written to “C:\Users\nnn\Documents\Visual Studio 2012\My Exported Templates” by default. Selecting the “Automatically import the template into Visual Studio” option copies the file to the directory configured in the VS 2012 settings (see above). The default is “C:\Users\nnn\Documents\Visual Studio 2012\Templates\ItemTemplates”. You have to move it into the appropriate subdirectory yourself!

Links

I have to confess that I did not found out all of it by myself. Here are the links to the postings in MS forums where I found most of the informations:

  • Can’t see My Templates (VS 2012 Update 3)
  • Where to put Custom Item Templates for Windows Store Apps (XAML/C#) in VS2012 Update 3?
  • Mimic app.config in Windows Store Apps

    Preface

    I know, the concept of app.config files is not part of Windows Store App development. The docs and postings say that one should use local or roaming settings.

    But I needed something to pass environment depending initial data to the app. One scenario I can think of is the URI of a web service that is consumed by an app. This URI might defer from development environment to test to production in case you develop both the app and the service. Changing the code or using conditional directive (#if) might not be the best idea to implement that.

    appSettings Approach

    The approach copies the appSettings part of .NET app.config usage. Just add an XML file to the project and make sure the “Build Action” property of the file is set to “Content”. This file will be included into the deployment package and can be accessed during runtime.

    The content of this file might look like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="MyConfigSetting" value="The Config Value"/>
      </appSettings>
    </configuration>

    Since app.config is not part of the Windows Store app concept, there is no ConfigurationManager class to ease the access. But it is not that hard to read and parse XML files.

    In my approach, I implemented the loading of the XML file in two steps: get the file and load it.

    StorageFile file = await StorageFile
    .GetFileFromApplicationUriAsync(
     new Uri(String.Format("ms-appx:///Assets/Configuration/{0}",
       ConfigManager.ConfigFileName)));
    
    XmlDocument xmlConfiguration 
    = await XmlDocument.LoadFromFileAsync(configFile);

    As you can see from the URI, I put the config file into the Assets/Confioguration folder. The name is dynamic to give me the chance to use different files for different environments. I will come back to this later.

    If you know the Windows.Data.Xml.Dom.XmlDocument class you might ask why I am not using the XmlDocument.LoadFromUriAsync method. The answer is simple: it did not work right away (using the same URI), and I was too lazy to search for the reason.

    Now that the XML is loaded, it is easy to read the values:

    IXmlNode node 
    = xmlConfiguration.DocumentElement
     .SelectSingleNode(
      "./appSettings/add[@key='MyConfigSetting']/@value");
    
    if (node == null)
    {
      // do some error handling or set default value
      return;
    }
    
    string configValue = (string) node.NodeValue;

    And that’s it. One might want to encapsulate this functionality by a class, implementing additional error handling, and so forth.

    Complex Configuration Data using XML Serialization

    In .NET client applications, one can use sections to handle complex configuration data that does not fit into key / value pairs. Of course, even for .NET client applications there is a good chance you have to write the section handler yourself.

    For Windows Store apps, it is sure you have to write the handling of complex configuration data yourself. But you don’t have write loads of XML readings. Why? Because you can use XML serialization, like in .NET applications. The System.Xml.Serialization.XmlSerializer is available for Windows Store apps too 🙂 Well, at least almost. Not all members available in .NET are available for Windows Store apps. But it became a lot easier to deserialize objects from XML without namespace qualification. (More about this issue for .NET can be found here: http://stackoverflow.com/questions/870293/can-i-make-xmlserializer-ignore-the-namespace-on-deserialization). There is no helper needed any more (at leats for Windows Store apps).

    So what have I done? I created a container class for the complex configuration data. This class might look like this (comments omitted):

    public class ComplexConfigData
    {
      [XmlAttribute]
      public string StringValue { get; set; }
    
      [XmlAttribute]
      public double DoubleValue { get; set; }
    
      [XmlAttribute]
      public int IntValue { get; set; }
    }

    I am using the XmlAttribute attribute to keep the XML compact. The config file with additional complex data looks like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="MyConfigSetting" value="The Config Value"/>
      </appSettings>
    
      <ComplexConfigDataList>
        <ComplexConfigData StringValue='StringValue1' DoubleValue='1.1' IntValue='10'/>
        <ComplexConfigData StringValue='StringValue2' DoubleValue='2.2' IntValue='20'/>
      </ComplexConfigDataList>
    </configuration>

    Here is how all the (manually) serialized ComplexConfigData objects are retrieved from the XML:

    XmlNodeList configDataList 
    = xmlConfiguration.DocumentElement
     .SelectNodes(
      "./ComplexConfigDataList/ComplexConfigData");
    
    foreach (IXmlNode node in configDataList)
    {
      ComplexConfigData configData 
      = XmlDeserializer.Deserialize<ComplexConfigData>(node);
      // do something with configData
    }

    The deserialization is encapsulated by this generic method in my class XmlDeserializer:

    public static T Deserialize<T>
      (
        IXmlNode serializedObject
      )
      where T : class
    {
      return (
        new XmlSerializer(typeof(T))
        .Deserialize(
          new StringReader(
           serializedObject.GetXml())) as T);
    }

    Selecting the Correct File

    Above, where the URI is built to get the config file, a placeholder and a property is used. The property is defined as follows:

    private const string ConfigFileName
    #if DEBUG
      = "Config.Debug.xml";
    #else
      = "Config.Release.xml";
    #endif // DEBUG

    The reason to use the conditional directive (#if) is that I do not want to change the code in case I have different settings for debug (development) and release (production). This approach does not fit for three different environments, but it is a starting point. Of course, you can change the content of the config file whenever you need. But this is more error prone than selecting the wrong build configuration. (The Windows Store only accepts release builds, so this approach will pick the release settings when the app is installed via Windows Store.)

    Sample Variation

    With version 3.0 of the source code, the sample implementation is not exactly what is described here. For demonstration purposes I thought it would be nice to be able to switch the app.config that is used via the Settings charm.

    This means, the name of the app.config file loaded does not depend on the build configuration, but on app configuration values. You can switch it directly. The change is reflected immediately by the UI controls.

    As said, this is for demonstration purposes. I do not think that this approach (giving the user the ability to switch the app.config) will be very useful in real world scenarios. But for this sample I think it is.

    In case you want to use the app.config mimic in your app, the code to couple the app.config to the build configuration is still included in the sample. See Configuration.ConfigurationManager.

    Considerations

    Think twice if you really need this. Don’t use it just because you are used to it from .NET applications.

    If you have the need to save configuration data during runtime, the app.config mimic is not the right approach to me. Better use local or roaming application data then (see links below).

    Load It From The Windows Store

    A slightly extented version of the sample can be found in the Windows Store.

    Finally

    … have fun 🙂

    You can find the sample code here.

    History

    2013-08-13: Source code update V3.0.0.1
    Instance Factory Logo changed; typo fixed.

    2013-08-09: Source code update V3.0
    Select the app.config file via Settings Charm, independend from build configuration.

    2013-07-23: Source code update V2.1
    Minor design changes (logo & splash screen).

    2013-07-10: Source code update V2.0
    UI completely redesigned.

    Sample Screenshot

    Sample Screenshot

    Links

    Local application data (Windows Store apps using C#/VB/C++ and XAML)

    Roaming application data (Windows Store apps using C#/VB/C++ and XAML)

    How to load file resources (Windows Store apps using C#/VB/C++ and XAML)

    Guidelines for app settings (Windows Store apps)

    Implement Settings Popup Pages for Windows Store Apps sample

    Create Custom IE Tracking Protection List

    In case one does not have some third party tracking protection tool installed, there is an easy way to create a custom list.

  • First step is to download an existing tracking protection list. Just open IE and go to Tools / Tracking Protection / Get a Tracking Protection List online…
  • Select one list, probably from a vendor you do trust, i.e. Fraunhofer SIT. Why from a trusted vendor? Because it is possible to add a whitelist to tracking lists too. Means if you load the list from someone you do not know, it might happen that tracking is enabled for someone you don’t like to get tracking information.
  • Install another list that might be a little bit more complete. You can see the content by selecting the list in the Tracking Protection management dialog (Tools / Tracking Protection) and click “More information” underneath the address of the list (in the lower third of the dialog).
  • From that dialog, one can copy the list and paste it into a file. Before proceeding, check whether the list contains any “allow rule” – having a +d in front of a domain instead of -d.
  • Remove that list in the IE management dialog.
  • When done, open the folder Users/username/AppData/Local/Microsoft/Internet Explorer/Tracking Protection. It should only contain one file, having a .tpl suffix.
  • Open that file with an editor and paste your list into it. Make sure no :expires entry is contained. Otherwise your changes might be overridden by IE automatically. Also only one msFilterList should be contained in the file. Then save the file and close the editor.
  • Re-open IE and have a look at the new list. It should contain your settings too now.
  • For more details, see Create and Host Tracking Protection Lists.

    You might ask why not use the sample from the MS description. My answer: it did not work on my machine.

    Drawbacks of this approach: From now on, you have to take care of this list yourself. You won’t receive updates any more (as far as I understand the docs). So maybe you want to enable the personalized list too.