Theming in Windows Phone
A theme is a visual definition of the look & feel for common controls in an Operating System.
Themes are usually end-user selectable, changing the theme at the OS level, impacts the look & feel of running applications that are ‘theme aware’. As an example, on Windows Vista and Windows 7, a popular/desired theme is the Aero theme.
Windows Phone supports theming. Here is a screenshot of the themes in action in Windows Phone.
This is the exact same app. No code changes, and no recompile. I switched the OS themes to get the different look and feel.
Since theming is new to Silverlight, I went under the hood for the implementation details, below are my findings (when dissecting the MIX Preview release).
Note: This is pre-released preview software, it will definitely change [I will point a few coming changes, and I am sure there will be more than I know about now] .
Details on how end-users will configure themes:
- The pre-defined themes are a combination of a background + accents colors.
- You get a Dark or a Light Background.
- The accent colors can be Orange, Blue, Red, Green
[Figure to the right of this paragraph shows the themes configuration screen].
- OS themes are not extensible; you can’t create and install your own theme. You can install your own application skin; a skin would change the look and feel for just your app; where a theme can affect all apps.
- Users can select the active theme on the OS [or the emulator] from Settings –> Themes.
[The emulator does not persist the theme selection across emulator runs, but if you change the theme it is persisted in memory, allowing you to use that theme for the duration of your emulator session]
Developer/implementation details:
- As expected (for Silverlight applications), theming is implemented using resources and resource dictionaries.
- The way the themes are implemented is this:
- There are pre-defined names for the resources in a theme. Most of the names follow this format: Phone<Feature/Functionality><Type> for example: PhoneBackgroundColor or PhoneAccentBrush.
- You can take a peek at the resources in a theme from the resource dictionaries at C:\Program Files (x86)\Microsoft SDKs\WindowsPhone\v7.0\Design (or just program files if running 32-bit OS).
- These theme resources are injected into the run-time at application startup.
- The resources are resolved as if they were at a higher level than Application level Resources.
If you are familiar with Silverlight or WPF, the {StaticResource} markup extension look-ups are resolved bottom-up, where a UIElement first looks for a desired resource in its Resources collection; if the resource is not there it will query up the visual tree on its Parent’s resources collection (and iteratively the parent’s parent, ,all the way up to the root of the tree. If the resource is not found, the resource resolution logic then looks in the Application.Resources collection.
For Windows Phone, if the resource is not found in the standard resolution above, it will then query the themed resources collection (inserted by the OS) to try to resolve it.
Note: see known issues below for known bugs on resource resolution at MIX release] - The resources are injected before Application.InitializeComponent is called.
This means, if you insert a resource into App.xaml, that references a Theme resource, you will be fine..
At the same time, it is nice that they live in its own private collection - There is some magic on where these are stored. You cant’ see them at run-time (there is no exposed object that shows them), but you can reference and query for them. See Figure 2 below, the debugger tells me there is no resources on the Page or Application Resources collections, but when I query them, they are there.
Personally, I am still undecided with theme resources resolving at Page level (via this.Resources).
I think this has implications with regards for those of us that have our equivalent to WPF’s TryFindResource, but not a huge deal since these are supposed to be Theme resources. Again, just don’t use the names in the theme.
- The resources are resolved as if they were at a higher level than Application level Resources.
- Since you are running Silverlight applications (so only StaticResources) the expectation is that theming changes are picked up once per application at start-up. There is no system-wide event or notification that tells you that the current active theme has changed. [This should not be an issue; but wanted to save you from looking for the event]
- There is no API to detect the active theme. As a workaround, you can peek into the resources (e.g. look at PhoneBackgroundColor, to know if you are running the Dark or Light theme and look at PhoneAccentColor to know the accent).
A known issues at MIX release:
There is a bug in the MIX preview release that makes resource resolution behave different from what I described above. The bug is that {StaticResource} lookups are looking at the “themed resources” collection first instead of looking at application resources first. This is a bug and will be fixed in later builds.
Note that this is not a big issue, you would only see this issue if your themed resources, and your application resources do not match. There is two scenarios when this can happen:
-
If you try to override the theme by inserting your own resources into App.Resources with the same names. I have to recommend that you do not do that. If you don’t want theming it is safer to create custom templates and styles to get your look & feel right (and bullet proof).
If your design-time resources – inserted by VS2010 tooling into App.xaml - are not matching the theme running on the OS. This is a variation of #1 above, but with this one, the developer had no intention to override the resources, therefore I had to highlight it separately. It also had me all confused given it behaves different from SL on desktop and WPF.
Here is a detailed explanation on the resources in App.xaml:
The VS 2010 tooling inserts the equivalent of the DarkBlue theme into App.xaml, in the resources collection.
This is handy for design-time and it works at run-time due to bug above. That said, the resources in App.xaml are not required at run-time. You can remove most of the resources in App.xaml and check that still your works. You can see this in my sample code attached to this post.The only two resources from App.xaml that you should not remove are the two styles: PhoneTextpageTitle1Style and PhoneTextPageTitle2Style. These two styles are not themed resources and are referenced by the default PhoneApplicationPage template created by Visual Studio. What I did for my app was move these resources back to the Page resources collection, ending up an empty App.Resources collection, and two styles in the MainPage resources collection.
Sample code is at https://learningwindowsphone.com/samples/LearningWindowsPhone.ThemesAtMIX.zip
That is it all you should need to know to get going with themes. Now, you can plan for your Windows Phone application to be theme-aware.
Comments
- Anonymous
March 30, 2010
Wow. Nice and fantastic themes.