For the past two days, I’ve been trying to get the infrastructure in place for skinning a WPF application. My goal is to support multiple skins and swap them out dynamically while the app is open.
I could get the skin to affect the UI if I set it in the main window’s resource dictionary. However there was a quirk… The application uses WPF frames and pages. The skin was not showing up on frame’s pages. It would only show up on the main window.
I searched Bing, Google and StackOverflow for answers. No luck.
I setup VS to pull down the MS debug symbols so that I could step through the source code for the .NET framework. This was very cool, but not an immediate help.
I went back to StackOverflow and searched for stuff about pages, frames and resource dictionaries. I stumbled on this article and found a comment that provided the solution. It wasn’t the accepted answer, nor was it detailed, but it worked for me! The comment by “Chris” indicating that I should check that the App.Xaml’s code-behind is calling InitializeComponent. I added this call and all of a sudden my pages were skinned too!
Chris indicated that this call to InitializeComponent is what “merges the resource dictionaries.” I looked at the code that is in this generated method and it appears that it is responsible for calling LoadComponent on the App.Xaml file. Without this call, there is no “Application Level” resource dictionary defined in the application. As such, it seems that there is no application container (resource dictionary) available to host the resources for the app.
There is an interesting quirk. At one point, I removed the explicitly included skin such that the App.Xaml file had no resources in its resource dictionary. Then, my code wouldn’t compile. It said that there was no “InitializeComponent” method defined on the App code-behind. What the heck! It was just there!
I added an item back into the App.Xaml’s resource dictionary and then the method was back, plus my app was responding to the skin properly.
So, I’m thinking that I need to follow these rules to get reliable styling / skinning in a WPF app.
- Make sure there is at least one resource in the App.Xaml’s resource dictionary.
- Make sure the App.Xaml’s code-behind calls InitializeComponent.