It was proposed to add dynamic theme switching to our application, and I had problems figuring out how to do it.
Here's the current situation: our application has a unified resource dictionary with explicit (implicit) styles. The views in our application apply to these styles through the StaticResource markup extension. The reason we don't use implicit styles is because we repeatedly look at common types of controls; for example, buttons in one place look different than buttons in another.
So what we want to do is create themes that replace these named styles with a new set of named styles.
Approach 1
The first attempt was to create resource dictionaries for each topic. I deleted one of the styles from regular dictionaries and placed them in each topic dictionary, giving each copy a separate look, for example:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"> <Style x:Key="HeaderContentStyle" TargetType="ContentControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Grid Margin="0" Background="Red"> <ContentPresenter Content="{TemplateBinding Content}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"> <Style x:Key="HeaderContentStyle" TargetType="ContentControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Grid Margin="0" Background="Blue"> <ContentPresenter Content="{TemplateBinding Content}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Then I added code to dynamically load one of the resource dictionaries from XAML and insert it into the integrated application dictionaries:
// In App.xaml.cs var themeUri = new Uri( "OurApp;component/Themes/RedTheme.xaml", UriKind.Relative); var resourceInfo = GetResourceStream(themeUri); using (var stream = resourceInfo.Stream) { using (var reader = new StreamReader(stream)) { var xamlText = reader.ReadToEnd(); var dict = XamlReader.Load(xamlText) as ResourceDictionary; Resources.MergedDictionaries.Add(dict); } }
It worked to some extent. If I downloaded the "theme" during startup, this theme style was displayed. However, what didnโt work was trying to switch to another topic after launch. Adding another theme topic dictionary to the combined dictionaries did not change the user interface. Also failed to clear the old theme dictionary and add a new one. None of them were also executed by deleting the root visualization and re-adding it.
Approach 2
After that, I tried using the Silverlight Toolkit template. I believe this did not work, because it is intended to switch implicit styles, not explicit ones. I created my class-derived class, installed its resource URI, and added this theme to the root visual ContentControl . Then, however, when I created my main user interface, the explicit style referenced by the user interface was not found, so an exception occurred at runtime.
So, I tried to load one of the thematic resource dictionaries into the integrated application dictionaries. This allowed us to create and place the main user interface class inside the Style object. However, explicit styles within the Style resource dictionary were not able to override the styles defined within the merged application dictionaries. Therefore, nothing has changed.
Current approach
So now I am considering the third approach. It will include an attached property, used something like this: Theming.Style="StyleName" . Then, elsewhere in the application, a relationship will be maintained between theme names and style name overrides. Whenever a theme changes, the correct styles for the theme will be applied.
Dilemma
I would prefer not to reinvent the wheel, if there is already one. Is there anything in Silverlight that allows you to switch themes that contain explicit styles? Are there any third-party libraries that will allow me to do what I want?