Fixing Color Themes on Windows Phone
There’s a lesser-known feature of Windows Phone that allows customization of control colors without touching their Style or Template. This is accomplished by overriding special color resources defined by the OS. In fact there’s a whole page on MSDN dedicated to listing the color resources and how they’re used by various controls.
For example, adding this to App.xaml:
Produces this in the designer:
And in Windows Phone 7.0 that’s what you see at run time too. However, starting with Windows Phone 7.5 the colors DON’T display correctly at run time. At run time the color changes lost and the default OS colors are used instead.
This is a known issue and it’s discussed several places, but the article I like best is Windows Phone Mango Custom Application Theme Step-by-Step. I like the workarounds they provide too, especially Option1: Dynamically load all colors from a XAML file. With this approach, color resources are moved to an external file then loaded in at run time. The problem I have with their implementation is that it breaks the design experience since it does not allow these resources to be merged during design. So I set off to provide a simple solution that would work at both design time and at run time.
My solution starts in a similar way by adding a resource dictionary to the application that will contain the color theme:
I put mine in a subfolder but that’s just a matter of taste.
Next, we change the Build Action of this file to ‘Content’ instead of ‘Page’ (more on that in a moment).
Now we need to move all of our color resources out of App.xaml and into this resource dictionary. Here’s what mine looks like after the move:
Finally – and this is one of the differences in my approach – we go back to App.xaml and merge this resource dictionary back in:
Now build the application and when you view the page in the Visual Studio (or Blend), you’ll see the color changes applied:
We’re not quite done yet though because the changes are still lost at run time. So what did we gain by moving the resources to a separate dictionary? We got the ability to update them quickly and easily at runtime using a little code.
In the sample code you’ll find a file called ResourceExtensions.cs. With this added to our project we can call one line of code and our colors are fixed at run time too. The method is called MergeColors and it’s an extension method added to the ResourceDictionary class itself. This method needs to be called inside the App() constructor. It should be called after InitializeComponent() but before InitializePhoneApplication(). Here’s a snippet:
MergeColors first looks to see if the specified resource dictionary is already merged into the application (which it should be, since we merged it above so we can see our colors at design time). If the dictionary is merged it’s removed. Otherwise, it’s loaded into memory. Finally, each of the color resources is updated in the parent dictionary.
Now we have our custom colors at both design time and run time.
So, why did we change the Build Action above to ‘Content’ instead of ‘Page’? It’s because the Uri for a ‘Content’ dictionary is much closer to the Uri at run time. That makes it easier for MergeColors to see if the dictionary is merged at runtime and remove it.
That’s everything you need if you download the source. For completeness and for those who would rather copy and paste than download, here’s what’s inside the MergeColors extension method: