Question

Our WPF application has several UI skins that can be switched at runtime and be applied to specific framework element and it's children. Skin is compiled xaml resource dictionary that is stored in Theming dll, Skinning is implemented by using custom SkinManager class and attached dependency property Skin, that is actually changing skin by adding skin's resource dictionary to targeted FrameworkElement.Resources.MergedDictionaries. Skin dictionary contains styles that have TargetType="SomeType" and BasedOn="{StaticResource {x:Type SomeType}}", and thus applying this style to all framework elements of SomeType, based on implicit style from WPF system themes. This approach works greatly, but we've encountered problems when we try to introduce Theming to our application.

Theme by our definition is a custom skin, that applied to entire application + specific system theme (Classic, Luna, Royale, Aero, Aero2 (aka Metro)). It is implemented by loading corresponding resource file from system dll (aero.normalcolor.xaml from PresentationFramework.Aero for Aero theme) to Application.Resources.MergedDictionaries. If we add skin to this resourcedictionary -it is ignored, thus skin is applied to every active Window. This also works fine, however we've encountered difficulties with switching theme in runtime:
If theme is based on same system theme - than there is no problem, otherwise we get nasty and undesired behavior: framework elements with applied skin does not change their appearance that introducted through implicit styles (e.g. button doesn't change it's chrome and padding when royale theme changed to aero), moreover if we try to store unique instances of resourcedictionaries for skins and for themes, then we get situation when themes with same skin are visually merged into same theme: if we try to apply these themes, the one that was applied first is applied every time (e.g. if theme1 = royale+ blueskin, theme2 = aero+blueskin,then if theme1 is applied first then application of theme1 and theme2 applies "royale" appearance in both situations)
Is there any possible way to overcome these problems and change WPF implicit styles at runtime? Or we failed in noticing some important details about WPF mechanism of resource dictionaries?

Was it helpful?

Solution 2

We've succeeded in applying specific system themes by using MS.Win32.UXThemeWrapper class in a way that is used here https://github.com/danielmoore/SystemThemeChange/blob/master/ThemeHelper.cs by changing actual system theme for WPF Internals and removing BasedOn declarations for implicit styles.

OTHER TIPS

if i understand you right with the problem of the first "skin" being applied even when you set another, try clearing the merged resource dictionary first...

there are many topics on here related to loading resources at runtime, for example switching wpf resource dictionaries at runtime

which shows:

ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dic);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top