Loading Styles Dynamically on Windows 8

1 minute read

Windows 8 is very ambitious in its breadth of supported form factors.  Huge screens down through small tablets, it is quite variety of display surfaces supported with different dimensions, aspect ratios, and resolutions

Common Sizes for Windows 8

While designing flexible layouts is a must; there are limits. Add to that the difference in use cases for a person interacting with a large monitor at their desk on the one hand, or viewing a television across the room on the other.  The screens would have similar dimensions and aspect ratios, but the former demands a lot of data be available up close while the latter prefers less data well presented.  DUI or Distance UI is a term for this concept, and dynamic themes may provide some solutions.

On Windows 8 I can easily determine the screen size and the resolution and adjust the styles accordingly. The basic templates handle the current window’s SizeChanged event giving me an opportunity to adjust for a larger screen size.

1
2
3
4
5
private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs e)
{
    LoadStylesForSize(e.Size);
    this.InvalidateVisualState();
}

or I can adjust for a change in resolution in the event handler for the DisplayProperties LogicalDpiChanged event

1
2
3
4
private void DisplayProperties_LogicalDpiChanged(object sender)
{
  LoadStylesForResolution(DisplayProperties.ResolutionScale);
}

To load a new template, I create a new MergedDictionary with the styles that I want and apply it to the current application resources.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private void LoadStylesForSize(Size size)
{
  ResourceDictionary merged = new ResourceDictionary();
  ResourceDictionary generic = new ResourceDictionary();
  ResourceDictionary theme = new ResourceDictionary();

  generic.Source = new Uri("ms-appx:/Common/StandardStyles.xaml");

  if(size.Width < 1366)
  {
      theme.Source = new Uri("ms-appx:/Common/AppStyles-Custom1.xaml");
  }
  else if(size.Width < 1800)
  {
      theme.Source = new Uri("ms-appx:/Common/AppStyles-Custom2.xaml");
  }
  else{
      theme.Source = new Uri("ms-appx:/Common/AppStyles-Custom3.xaml");
  }

  merged.MergedDictionaries.Add(generic);
  merged.MergedDictionaries.Add(theme);

  App.Current.Resources = merged;

  this.Frame.Navigate(this.GetType(), "AllGroups");
 }

When you are creating your themes, remember to pay close attention to dependencies so that a resource doesn’t try to reference another resource that is not yet defined. See MSDN on Merged Dictionaries to see what resource is loaded and when. Also, you will have to move all resources from App.xaml into your generic resource dictionary because they will be cleared when you reset your application resources to your new merged dictionary.

The updates only seem to take effect when the elements are recreated, so a navigation is required to apply the changes.

Files: StyleDemo.zip

Updated: