Busy-Indicating Dialog for Windows Store Apps in C# / XAML

Preface

Some of you might know the BusyIndicator from the WPF Toolkit or from Silverlight.

I was using this control in Silverlight to disable user interaction while the application was performing some long running operations. This makes it really easy to make sure the user will not start a new task while another has not yet finished. And – very important – it does not block the UI thread, so the application does not seem to be unresponsive to the operation system.

Microsoft does not offer such a control for Windows Store apps. But even in a Windows Store app I needed to make sure the user ‘waits’ for the completion of a task, before a new is started. And I do not wanted to implement this by adding a flag telling no new task can be started (and/or disable controls based on that flag, …).

So what I wanted was a control that meets the following requirements:

  • Disable user interaction (‘lock’ the app)
  • Give visual feedback to let the user know interaction is disabled
  • Do not block the UI thread
  • Show some progress indication
  • Enable the user to cancel the operation

Disable User Interaction

Disabling the user to interact with the app is quite simple. Rob Caplan gave me the initial idea in his answer on how one might implement a modal popup. He suggested to use a full screen popup with a similar look to the MessageDialog.

Creating a full screen popup, or better say a popup having the current size of the app, and setting the focus to that popup, no interaction with the app is possible any more. No matter if the user clicks, taps, or uses the keyboard or pen.

The first requirement is fulfilled.

Give Visual Feedback

Depending on how the full screen popup is implemented, the user might not recognize that the interaction is disabled.

Looking at MessageDialog, one might notice that the area that is not covered by the dialog itself is dimmed out.

To achieve this, a UserControl is implemented. In the sample code, this user control is named BusyIndicatingDialog and can be found in UI/Xaml/Popups.

BusyIndicatingDialog contains one Grid without any content. This Grid has a black background and an opacity of 0.4.

Setting an instance of BusyIndicatingDialog as the child of the Popup, the app’s window gets dimmed out when the Popup is opened. The second requirement is fulfilled.

Do Not Block the UI Thread

Because common UI controls are used, this requirement can be fulfilled without any additional effort.

Of course, one has to take care that the operation to be performed is non-blocking. Means it should be implemented in an asynchronous way. But this is independent from the implementation of the BusyIndicatingDialog.

Show Some Progress Indication

Now, the user sees that the interaction is disabled. But there is no information about what is going on. This might lead to the impression that the app has stopped working.

To show that there is something going on in the background, BusyIndicatingDialog contains a second Grid. It is something like a modal dialog, showing the current processing state. It contains some TextBlocks and a ProgressBar.

These controls are bound to a view model, implemented by BusyIndicatingViewModel. This class can be found in ViewModels.

BusyIndicatingViewModel implements an event handler, OnItemProcessed. The class that implements the long-running operation, MainPage in this sample, needs to fire an appropriate event every time an item is processed (or when an update of the progress should be displayed). This event is implemented by MainPage.ItemProcessed.

And because BusyIndicatingViewModel implements the INotifyPropertyChanged interface (via its base class BindableBase), setting the properties in OnItemProcessed updates all the controls of the dialog.

Cancel the Operation

So far, we are able to stop user interaction with the app, give visual feedback on this, do not block the UI thread, and show how the operation proceeds. But maybe the user wants to cancel that operation, for whatever reason.

To enable the user to do this, a cancel button is added to the BusyIndicatingDialog. Pressing this button, the Cancel event is fired by the BusyIndicatingViewModel. This is implemented by binding the Command property of the Button control to the CancelOperationCommand of the view model.

Of course, just firing an event does not stop anything at all. The class that implements the long-running operation, MainPage in this sample, has to register an event handler on this event. The event handler (OnCancelOperation) sets a flag. This flag is evaluated on each iteration of the long-running operation. When it is set, the operation stops.

This feature makes the BusyIndicatingDialog ready to use.

Creating the Busy-Indicating Dialog

The following code snippet shows all the steps that needs to be done to show the busy-indicating dialog.

// Implemented by BusyIndicatingDialog
public static BusyIndicatingDialog LockScreen
  (
  int numberOfItemsToProcess
  )
{
  // Create a popup with the size of the app's window.
  Popup popup = new Popup()
  {
    Height = Window.Current.Bounds.Height,
    IsLightDismissEnabled = false,
    Width = Window.Current.Bounds.Width
  };

  // Create the busy-indicating dialog as a child, 
  // having the same size as the app.
  BusyIndicatingDialog dialog 
    = new BusyIndicatingDialog(numberOfItemsToProcess)
  {
    Height = popup.Height,
    Width = popup.Width
  };

  // Set the child of the popop
  popup.Child = dialog;

  // Postion the popup to the upper left corner
  popup.SetValue(Canvas.LeftProperty, 0);
  popup.SetValue(Canvas.TopProperty, 0);

  // Open it.
  popup.IsOpen = true;

  // Set the focus to the dialog
  dialog.Focus(FocusState.Programmatic);

  // Return the dialog
  return (dialog);
}

Prepare the Long Running Operation

Because there are several steps to be done before the long running operation can start, this is encapsulated in a separate method.

// Implemented by MainPage
private BusyIndicatingDialog PrepareLongRunningOperation
  (
  int numberOfItemsToProcess
  )
{
  // Disable the app bar
  BottomAppBar.IsEnabled = false;

  // Lock the screen
  BusyIndicatingDialog indicatorDialog 
    = BusyIndicatingDialog.LockScreen(numberOfItemsToProcess);

  // Set the view model as the event handler for processed items
  ItemProcessed += indicatorDialog.ViewModel.OnItemProcessed;

  // Set the handler for the cancel event.
  indicatorDialog.ViewModel.Cancel += OnCancelOperation;

  // Reset the flag for canceling the operation.
  CancelOperation = false;

  // return the dialog
  return (indicatorDialog);
}

Please notice the fact that the app bar is disabled explicitly. The popup does not ‘block’ the app bar.

Cleanup

When the long running operation has finished, some cleanup is required.

// Implemented by MainPage
private void CleanUpLongRunningOperation
  (
  BusyIndicatingDialog indicatorDialog
  )
{
  // Operation has finished => deregister the event handler 
  // so the garbage collector can release the dialog
  ItemProcessed 
    -= indicatorDialog.ViewModel.OnItemProcessed;

  // close the dialog
  indicatorDialog.Close();

  // Enable the app bar
  BottomAppBar.IsEnabled = true;
}

Additional Considerations

I consider this implementation to be useful in cases where many items (or tasks) should be processed sequentially, while the processing of each single item does not take too long. Having one task that takes very long, no progress can be displayed and no cancelation is possible. If you have to cover such a scenario, I think you need to find another solution.

One thing really important is to give the UI thread a chance to update the dialog control and react on user input. To do so, you should add an await Task.Delay(1); between the processing of each item. Otherwise, in case the processing of the single item is really fast, the dialog might not be updated and(!) pressing the cancel button does not have any effect.

Consider Windows Store App Lifecycle

In the article “The Windows Store App Lifecycle“, Rachel Appel points out that “Windows 8 is changing how and when applications run”. In fact, it does!

Unlike desktop applications, Windows 8 suspends Windows Store apps (after a few seconds) when the user switches to another app. No matter what the app is currently doing. You cannot keep the app ‘alive’.

One should be aware of this. It means the user has to wait for long running operation to complete, and should not switch to another app meanwhile. This is kind of ‘blocking’ the device. Keeping this in mind, one should think twice before using Windows Store apps to execute long running operations, e.g. copy gigabytes of data.

Yes, there are background tasks available. But you cannot trigger them from within your app. So the usage is limited.

The Sample

can be found here.

Main screen

Processing

Links

Forum question Modal popup

Simple and Generic ICommand Implementation for Usage in XAML

The Windows Store App Lifecycle

Background Tasks

Forum question ‘Trigger background task manually

Simple and Generic ICommand Implementation for Usage in XAML

Preface

The Commanding Overview says “Commanding is an input mechanism in Windows Presentation Foundation (WPF) which provides input handling at a more semantic level than device input. Examples of commands are the Copy, Cut, and Paste operations found on many applications.

Well, one should extent the definition and mention Windows Store apps too. Commanding is not limited to WPF.

When looking for a sample implementation that could be used in Windows Store apps too, I found this forum post: ICommand and MVVM.

The implementation looked quite easy to me, but lacks of type safeness from my point of view.

So I extended the DelegateCommand class from this post to be more typesafe.

Generic ICommand Implementation

/// <summary>
/// Generic implementation of <see cref="ICommand"/>.
/// </summary>
/// <typeparam name="T">
/// Type of the parameter the command expects.
/// </typeparam>
/// <remarks>
/// Copied from http://social.msdn.microsoft.com/Forums/en-US/f457c906-56d3-49c7-91c4-cc35a6ec5d35/icommand-and-mvvm
/// </remarks>
public class DelegateCommand<T> : ICommand
{
  #region Private Properties

  /// <summary>
  /// Gets / sets the action to be executed.
  /// </summary>
  private Action<T> ExecuteAction { get; set; }

  #endregion Private Properties


  #region Public Events

  /// <summary>
  /// Occurs when changes occur that affect whether 
  /// the command should execute.
  /// </summary>
  public event EventHandler CanExecuteChanged;

  #endregion Public Events


  #region Public Constructors

  /// <summary>
  /// Initializes a new instance of <see cref="DelegateCommand"/>
  /// with the action to be executed.
  /// </summary>
  /// <param name="executeAction">
  /// Action to be executed.
  /// </param>
  public DelegateCommand
    (
    Action<T> executeAction
    )
  {
    ExecuteAction = executeAction;
  }

  #endregion Public Constructors


  #region Public Methods

  /// <summary>
  /// Determines whether the command can execute in its current state.
  /// </summary>
  /// <param name="parameter">Data used by the command.</param>
  /// <returns>
  /// <c>true</c> if this command can be executed; 
  /// otherwise, <c>false</c>.
  /// </returns>
  public bool CanExecute
    (
    object parameter
    )
  {
    return true;
  }

  /// <summary>
  /// Invokes the method to be called.
  /// </summary>
  /// <param name="parameter">Data used by the command.</param>
  public void Execute
    (
    object parameter
    )
  {
    ExecuteAction((T) Convert.ChangeType(parameter, typeof(T)));
  }

  #endregion Public Methods
}

Usage

This class is used something like this:

public class MyViewModel
{
  …
  public ICommand SomeMethodCommand { get; private set; }
  …
    public MyViewModel ()
    {
      // Set the command.
      SomeMethodCommand = new DelegateCommand(SomeMethod);
    }
  …
    public void SomeMethod
      (
      bool value
      )
    {
      // Do something
    }
}

The usage in XAML is like this:

<Button Content="Invoke SomeMethod" 
  Command="{Binding SomeMethodCommand}" 
  CommandParameter="true"/>

where the DataContext of the page is set to an instance of MyViewModel.

Limitations of the Implementation

As said, this is a simple implementation of ICommand.

It does not evaluate the value passed to CanExecute. And it does not fire an event in case the CanExecute state changes (which is not implemented here too).

Links

Commanding Overview

Forum Post ICommand and MVVM

Unit-Testing of Private Async Methods with Visual Studio

Description

Given there is the need to unit-test a private async method. The class to be tested might look like this:

public ClassWithPrivateAsyncMethod
{

// Some stuff

  private async Task PrivateMethodAsync
    (
    string input
    )
  {
    // Call some async framework method
    var result = await SomeFrameworkMethodAsync(input);
    // do something with the result
  }

// Some more stuff

}

In former – pre VS 2012 – times, one would have right-clicked inside this method, selected “Create Private Accessor…” and “Create Unit Tests…”, and implemented the test. Well, this was then, and this is now. Nowadays, Visual Studio does not have the ability to create private accessors and unit test bodies.

But still, you are able to create a unit test yourself. And instead of having a private accessor, we can use Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject, which is included in %Program Files (x86)%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll (path might vary slightly with version changes, this is the path for Visual Studio 2012). To use this assembly, I had to set the Copy Local property of the reference to true.

Instead of wring much more prose, here is the implementation of the unit test method:

using Mut = Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
// some other usings

[TestClass]
public ClassWithPrivateAsyncMethodTest
{
  [TestMethod]
  public async Task TestPrivateMethodAsync()
  {
    // Create an instance of the class to be tested.
    ClassWithPrivateAsyncMethod instance 
      = new ClassWithPrivateAsyncMethod();

    // Create a PrivateObject to access private methods of instance.
    Mut.PrivateObject privateObject 
      = new Mut.PrivateObject(instance);

    // Create parameter values
    object[] args = new object[] { "SomeValue" };

    // Call the method to be tested via reflection, 
    // pass the parameter, and await the return
    await (Task)privateObject.Invoke("PrivateMethodAsync", args);

    // Do some validation stuff
  }

// Some more stuff

}

Have a look at the checklist to be sure not to miss a detail.

Checklist

Check Combine async with return type Task in method declaration. Even if the method returns void, the declaration should be async Task. Otherwise, it cannot be awaited, what would lead to some trouble in testing the method.

Check Add reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll in your test project. You have to browse for it. The assembly can be found in %Program Files (x86)%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v4.0\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll (path might vary slightly with version changes, this is the path for Visual Studio 2012).

Check Set Copy Local to true for the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll reference.

Check Declare an alias for the Microsoft.VisualStudio.TestTools.UnitTesting namespace if you also use Microsoft.VisualStudio.TestPlatform.UnitTestFramework. This helps you to avoid using classes of the wrong namespace. There are some overlappings.

Check Declare testing method async Task, not async void. Otherwise, it will not be recognized as a test method, even when the TestMethodAttribute is set.

Check Use PrivateObject to access private methods of instances. It is located in the namespace Microsoft.VisualStudio.TestTools.UnitTesting.

Check Cast PrivateObject.Invoke‘s return value to Task to make sure the call can be awaited.

Check Await PrivateObject.Invoke. Otherwise, the tests in the testing method might be performed before the tested method returns.

Links

Async Return Types (C# and Visual Basic)

Handling of Out-Parameters with .NET Reflection

MDI / Multiple Tabs Flat Navigation App Bar in Windows Store Apps

Summary

The Windows 8 User Experience Guidelines mentions two different navigation designs: the hierarchical and the flat system. As said in the guidelines, most Windows Store apps use the hierarchical system. But I needed a flat navigation. And in addition, I needed a way to implement a Multiple Document Interface (MDI) like approach. Or, in other words, an IE 10 like multiple tabs flat system interface.

IE 10 Tab Navigation

This sample implements such an app bar. The user can add new tabs (pages), switch between open pages, and of course remove existing. The app bar holds a navigation list of all currently open pages.

The user can enable / disable some app bar animation when a new page is added. The side effects of this, and a reason why one might prefer the animation, are explained in detail below.

Another configuration setting is available to set the way the navigation list reacts on user interaction. One option is to open an existing tab by just tapping on it (single tap). To select an item from the navigation list, the user has to right tap it. The app gives visual feedback when right tapping is registered. (Right tapping means to press and hold until a time threshold is crossed.)

The other option is to select the navigation item by a single tap and open the page by double tapping. Because tap events a fired by finger tapping, mouse click or pen input, the app does not have to distinguish between different input devices.

Below you will find descriptions and explanations of some of the implementation details.

You Cannot Capture a Screenshot

My initial idea was to capture a screenshot of the current page and display the list of screenshots in the app bar. This is what the IE 10 app is doing.

But I had to learn that this is not possible in XAML Windows Store apps (see How to capture screen in Metro app?? in Dev Center).

Even using DirectX will not solve the problem. I tried the .NET / RT DirectX implementation SharpDX. It lacks of one key feature: create a copy of the output to be able to acquire the next frame. But from what I understand, this is not a SharpDX issue.

For those who ask why IE can: it is using its own rendering engine.

This is why there is no thumbnail thing in the navigation list, but a simple rectangle containing text. Of course, one might put some time in symbol design. But that is not the focus of this sample.

Global App Bar Definition

The navigation app bar might be defined for every page class that is used by the app. In this sample, the app bar is declared globally. The reason is that no matter which page is opened, the app bar always looks the same. Having different kinds of content pages, there might be the need to define different kinds of app bar.

The global AppBar is defined in the MainPage XAML. The main page itself has no content (beside some informational text that is hidden when a content page is added). It contains a Frame that hosts the current content page. Instead of navigating to the newly created page, the frame’s content is set to this page. So the MainPage is always present, and this is why its app bar will be shown.

I found the initial sample for this in Create Global AppBar in Windows Store Apps Using XAML/C#.

App Bar Animation

Animating new tabs means that the app bar stays open for a while when the add button is pressed. An indeterminate progress bar gets started. The new page opens, the new tab is added to the app bar’s list (animated), and then the app bar closes.

Having no animation, the app bar closes immediately when the add button is pressed, while the new page opens.

A drawback of having no animation, from my point of view, is when you open the app bar for the first time after a new tab was added. Without animation, all tabs are newly rendered with transition. On my machine, this took a while. I was not able to find out how to disable the transition. So the user waits a while until all tabs are visible. Opening the app bar again, without adding new tabs, the items are visible immediately.

Having the animation, the app looks like some background activities are required to setup the new page. The time the app bar stays open is not deterministic. So you might have to change to delay when using it in your own app. But when the app bar is re-opened, all items are displayed immediately.

All the content page adding code, together with the app bar animation, can be found in MainPage.OnAddButtonClicked.

Animation Update (V1.1.0.0)

Checking the sample on a Windows 8.1 Preview system, I noticed that the navigation tabs were shown with transition every time the app bar was opened – no matter if animation was enabled or not.

So I started again looking for the right place to disable transition of GridViewItems in the app bar. And I found it 🙂 In C# you have to set

GridView.ItemContainerTransitions = null;

or define in XAML

 <GridView>
  <GridView.ItemContainerTransitions/>
</GridView>

To be able to animate new items in the list, the sample stores the ItemContainerTransitions in MainPage.NavigationItemTransitionCollection when all UI controls were initialized. The collection is restored only in MainPage.OnAddButtonClicked when animation is requested and a new content page gets added.

Update 2013-10-25
In case you cannot see any animation under Windows 8.1, please check the Performance Options setting “Animate controls and elements inside windows” (System / Advanced system settings / Performance / Settings). If this option is not set, transition is disabled for Windows Store apps too.

User Interaction Considerations

My first approach for user interaction with the tab navigation was like this: single click opens the selected page. Right click selects the item for removal. Why just clicking? Because my dev machine has no touch display, and I almost do not run the apps in the simulator.

After having this coded, I switched to the simulator, testing the navigation in basic tap mode. Have you ever tried to right tap? The Quickstart: Static gestures says “A single contact that does not move until a time threshold is crossed. […] Right tap is closely associated with the press and hold gesture. The right tap event is fired when the press and hold is released.”. This is true so far. I received right tap events.

But there is no (visual) feedback by default for GridView when the time threshold is crossed. So when will the user knows she has right tapped? And the app won’t know either. This is because the RightTapped event is fired when the press and hold is released, not when the time threshold is crossed. Accordingly, the app cannot give visual feedback itself.

So I re-designed the navigation. Single click / single tap selects an item. Double click / double tap opens it.

Then I found this thread: Right tapped visual feedback rectangle. OK, the visual feedback is not built in, but can be added with a few event handler. So I implemented both versions. Still can’t tell which one I like more.

Failed to start tracking the pointer because it is already being tracked

Handling the CoreWindow.PointerPressed, CoreWindow.PointerReleased, and CoreWindow.PointerMoved for right-tapped visual feedback, I sometimes had an unhandled exception saying “Failed to start tracking the pointer because it is already being tracked”.

Well, the thread Failed to start tracking the pointer because it is already being tracked gave the important information, and I found it also in the remarks of the docs of UiElement.PointerCaptureLost event (unfortunately not in the remarks of CoreWindow.PointerPressed): “PointerCaptureLost might fire instead of PointerReleased. Don’t rely on PointerPressed and PointerReleased events always occurring in pairs. To function properly, your app must listen for and handle all events that represent likely conclusions to the Press action, and that includes PointerCaptureLost. A pointer can lose capture either because of user interactions or because you programmatically captured another pointer or released the current pointer capture deliberately.

Adding a PointerCaptureLost handler helped on this.

private void OnCoreWindowPointerCaptureLost
  (
  object sender,
  PointerEventArgs args
  )
{
  // Just set the flag that we've lost the capture.
  PointerCaptureIsLost = true;
}

The flag needs to be tested by the PointerPressed handler.

private void OnCoreWindowPointerPressed
  (
  object sender,
  PointerEventArgs args
  )
{
  // In case we've lost the pointer capture, just reset the flag and do nothing.
  // Otherwise, an exception will be thrown that says 
  // "Failed to start tracking the pointer, because it is already being tracked".
  if (PointerCaptureIsLost)
  {
    PointerCaptureIsLost = false;
    return;
  }

  // We still have the capture, so handle the event.
  GestureRecognizer.ProcessDownEvent(args.CurrentPoint);
}

Which Source of Pointer Events?

I was playing around to figure out from which source the pointer events should be handled. At least I think it is best to take Window.Current.CoreWindow. All pointer event handling is implemented in MainPage.

One approach was to only handle these events from the GridView that contains the navigation list. This lead to some unwanted behavior. When I right-tapped the app bar, waited until the visual feedback was shown, then moved the pointer without releasing it, the highlighted rectangle stayed open. Even when I switched to another app, the start screen, or close the app: the rectangle was not closed any more. At least this is how the app behaved in the simulator.

Tapping Empty GridView in AppBar Causes Unhandled Exception

Some unexpected things happen when I tapped into the empty GridViewGridView, and then into the main window (so that the app bar closes). When I repeat these steps for a second time (starting with opening the app bar), after tapping into the main window, the app terminates. As soon as the GridView contains at least one item, the error does not occur.

At the time of writing, I have not received a response / explanation for this. So maybe you want to make sure there is at minimum one item left in the list, means one content page needs to be open.

Get the Sources Directly

Click here to download the source code.

Load It From The Windows Store

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

Screenshots

Sample Settings
Behavior Settings

Flat System Navigation App Bar
Tab Navigation App Bar with selected items

History

2013-10-25: Source code update V1.2.0.0
Crashes on Windows 8.1 – fixed.

2013-08-14: Source code update V1.1.0.0
Corrections on transition / animation of items in navigation bar.

2013-08-13: Source code update V1.0.0.1
Instance Factory Logo changed.

Links

Click here to download the source code.

Windows 8 User Experience Guidelines

Dev Center UX Guide

Forum thread How to capture screen in Metro app??

.NET / RT implementation DirecX implementation SharpDX

Create Global AppBar in Windows Store Apps Using XAML/C#

The Quickstart: Static gestures

Forum thread Right tapped visual feedback rectangle

Forum thread Failed to start tracking the pointer because it is already being tracked

Implement Settings Popup Pages for Windows Store Apps

Microsoft Advertising Services AdControl Error Handling in XAML/C#

Preface

The Do’s + Don’ts of the Advertising SDK say “DO plan for times when no ads are available.” The links of that item leads to the ErrorCode enumeration and a rudimentarily error handling sample, writing text to debug output.

In this post, I will show an error handling where the AdControl is replaced by a TextBlock when an error occurs. Of course, this is still not a high sophisticated error handling. But it might give an idea what to do when no ad is available.

Ian Ferreira suggests in his blog post Keep Users First By Using These Resources For Ad Control Error Handling to hard code a house ad into the real-estate where an ad will appear.

Error Handling by Convention

The error handling is based on naming conventions. What it does is looking for a TextBlock having a name matching the naming pattern.

Following the convention, the name of the TextBlock has to be the name of the AdControl to be replaced, extended by ErrorTextBlock.

Sample: The name of the AdControl receiving an error is AdControlBottom. According to the naming convention, the name of the TextBlock to handle the error is AdControlBottomErrorTextBlock.

This makes it easy to implement a search for the correct replacement control. No additional properties need to be defined for the AdControl. And it follows MVC’s “Convention instead of Configuration” approach.

When an error occurs, the AdControl is made invisible, while the TextBlock at the same position will become visible. To make sure the design of the page does not change, the control that replaces the AdControl must have the same size as the AdControl.

In the sample app, just the name of the error-causing control, the reason, and the error text is displayed, no matter what the error code is. In real world scenarios, one should handle different errors differently. For example, just because an ad cannot be refreshed, I would not replace the existing one.

Here is how the handler is implemented:

protected virtual void OnAdControlErrorOccurred
  (
  object sender,
  AdErrorEventArgs args
  )
{
  AdControl adControl = sender as AdControl;

  // If event is not thrown by an Ad Control, do nothing
  if (adControl == null)
  {
    return;
  }

  // Just write out an error message.
  Debug.WriteLine("AdControl error (" + adControl.Name + "): " 
    + args.Error + " ErrorCode: " + args.ErrorCode.ToString());

  // Replace adControl by TextBlock showing error message.
  // Find the TextBlock by naming conventions. 
  // The name of the TextBlock is the name of the AdControl plus "ErrorTextBlock".
  TextBlock textBlock = FindName(
    String.Format("{0}ErrorTextBlock", adControl.Name)) 
  as TextBlock;

  if (textBlock == null)
  {
    return;
  }

  // Hide the AdControl
  adControl.Visibility = Visibility.Collapsed;

  // Show the TextBlock and copy properties.
  textBlock.Visibility = Visibility.Visible;

  textBlock.Height = adControl.Height;

  textBlock.Width = adControl.Width;

  // Set some text.
  textBlock.Text = String.Format("Sorry!{0}"
    + "Can't show AdControl '{1}'.{0}{0}ErrorCode: {2}{0}{0}ErrorMessage: {3}", 
    Environment.NewLine, adControl.Name, args.ErrorCode, args.Error.Message);
}

Please have a look at the sample code to see the XAML implementation. You can look at SubPages/SamplePage300x250.xaml, SubPages/SamplePage300x600.xaml, or SubPages/ SamplePageMultiple.xaml.

Sample Code

The sample code is part of the post Configure Microsoft Advertising Services’ AdControl using XAML/C#.

Links

Ads in Apps for Windows 8

AdControl Error Handling

AdControl ErrorCode Enumeration

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