1

How can I apply different color themes to my program using a ComboBox?

Such as ThemeBlue.xaml, ThemeRed.xaml, ThemePurple.xaml.

I need it to swap out one theme xaml file for another on selection change.

Blue Theme Example

Here's the example project file:
https://drive.google.com/open?id=0BycnCTAQ1U7gSU5kUUdaNzRIZDg


Themes

I have a theme file ThemeBlue.xaml with colors set for controls and window.

<SolidColorBrush x:Key="TextBoxCustom.Static.Background" Color="Blue"/>
<SolidColorBrush x:Key="TextBoxCustom.Static.Border" Color="Blue"/>

<Style x:Key="TextBoxCustom" TargetType="{x:Type TextBox}">
    <Setter Property="Background" Value="{StaticResource TextBoxCustom.Static.Background}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TextBoxCustom.Static.Border}"/>
...

ComboBox Theme Select

XAML

<ComboBox x:Name="cboTheme" Style="{StaticResource ComboBoxCustom}" HorizontalAlignment="Left" Margin="199,120,0,0" VerticalAlignment="Top" Width="75" SelectionChanged="themeSelect_SelectionChanged">
    <System:String>Blue</System:String>
    <System:String>Red</System:String>
    <System:String>Purple</System:String>
</ComboBox>

C#

This is where I need help to apply the theme file.

private void themeSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Apply theme file to App.xaml from option selected
    // Blue
    // Red
    // Purple
}

App.xaml

The theme file is loaded through App.xaml at startup

<Application x:Class="MyProgram.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">

    <Application.Resources>
        <ResourceDictionary Source="ThemeBlue.xaml"/>
    </Application.Resources>

</Application>

MainWindow.xaml

A TextBox with the Theme Style applied:

<TextBox x:Name="textBox1" Style="{StaticResource TextBoxCustom}" HorizontalAlignment="Left" Height="22" Margin="93,43,0,0" Width="464" />

Saving Theme

I save and load the theme through Settings.

private void themeSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Save Theme for next launch
    Settings.Default["Theme"] = cboTheme.SelectedItem.ToString();
    Settings.Default.Save();
    Settings.Default.Reload();
}
Matt McManis
  • 4,475
  • 5
  • 38
  • 93

2 Answers2

1

Try this:

private void themeSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string theme = cboTheme.SelectedItem.ToString();

    App.Current.Resources.MergedDictionaries.Clear();
    App.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("Theme" + theme + ".xaml", UriKind.RelativeOrAbsolute) });
    // Save Theme for next launch
    Settings.Default["Theme"] = theme;
    Settings.Default.Save();
}

App.xaml:

<Application x:Class="MyProgram.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ThemeBlue.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>
mm8
  • 163,881
  • 10
  • 57
  • 88
  • When I make ThemeRed.xaml and include in project, I get these errors on compile. https://i.imgur.com/A3NvqrA.png – Matt McManis Apr 09 '17 at 13:37
  • What changes did you do the MainWindow!? Obviously the sample code I posted has nothing to do with those errors. – mm8 Apr 09 '17 at 13:38
  • I made no changes to MainWindow. This is the code https://kopy.io/fuXE7 – Matt McManis Apr 09 '17 at 13:40
  • No, that's the markup...please try to rebuild your project and upload a full reproducible sample of your issue if you need any further help. – mm8 Apr 09 '17 at 13:41
  • Heres the project with ThemeRed.xaml https://drive.google.com/open?id=0BycnCTAQ1U7gSU5kUUdaNzRIZDg – Matt McManis Apr 09 '17 at 13:46
  • 1
    Remove the x:Class="WpfApplication23.MainWindow" attribute from the resource dictionaries (ThemeBlue.xaml and ThemeRed.xaml) and it will work. – mm8 Apr 09 '17 at 13:50
  • It is loading the themes now. Though it will only apply background color to the window, but not the textbox or button. – Matt McManis Apr 09 '17 at 14:00
  • I have asked a new question here https://stackoverflow.com/questions/43307874/changing-themes-only-applies-window-background-color – Matt McManis Apr 09 '17 at 14:28
0

You neet to replace the resource of the App.xaml with another resource in code behind. You can take the resource by loading the component. Here is a possible solution:

private void themeSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    AssemblyName assemblyName = Assembly.GetAssembly(this.GetType()).GetName();

    ResourceDictionary dictionary = (ResourceDictionary)Application.LoadComponent(
        new Uri(assemblyName.Name + @";component/" + cboTheme.SelectedItem + ".xaml", UriKind.Relative))));

    App.Current.Resources.MergedDictionaries.Clear();
    if (dictionary != null)
    {
        App.Current.Resources.MergedDictionaries.Add(dictionary);
    }
}
Fruchtzwerg
  • 10,999
  • 12
  • 40
  • 49