Entity
Entity

Reputation: 8212

Change theme at runtime

I have a WPF application with a theme (ShinyRed.xaml) and I want to have a button that when clicked changes the theme to ShinyBlue.xaml

I load in the theme initially in App.xaml:

<Application.Resources>
    <ResourceDictionary Source="/Themes/ShinyBlue.xaml"/>
</Application.Resources>

How might I do this?

Upvotes: 25

Views: 42455

Answers (5)

Thanh Bao
Thanh Bao

Reputation: 67

App.xaml

    <Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Themes/Font.xaml" />
            <ResourceDictionary Source="Themes/Light.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

In your code:

> Application.Current.Resources.MergedDictionaries[1].Source = new Uri("Themes/Dark.xaml", UriKind.RelativeOrAbsolute);

you can check with this to be sure nothing grow

Application.Current.Resources.MergedDictionaries.Count.ToString();

Upvotes: 7

brunnerh
brunnerh

Reputation: 185290

How you could do it:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary x:Name="ThemeDictionary">
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="/Themes/ShinyRed.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    <!-- ... -->
public partial class App : Application
{
    public ResourceDictionary ThemeDictionary
    {
        // You could probably get it via its name with some query logic as well.
        get { return Resources.MergedDictionaries[0]; }
    }

    public void ChangeTheme(Uri uri)
    {
        ThemeDictionary.MergedDictionaries.Clear();
        ThemeDictionary.MergedDictionaries.Add(new ResourceDictionary() { Source = uri });
    }

    //...
}

In your change method:

var app = (App)Application.Current;
app.ChangeTheme(new Uri("New Uri here"));

Upvotes: 37

Brock Hensley
Brock Hensley

Reputation: 3655

H.B.'s answer did not run for me, I had to do this (works, tested):

Uri dictUri = new Uri(@"/Resources/Themes/MyTheme.xaml", UriKind.Relative);
ResourceDictionary resourceDict = Application.LoadComponent(dictUri) as ResourceDictionary;
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(resourceDict);

To pretty it up:

// Place in App.xaml.cs
public void ChangeTheme(Uri uri)
{
    ResourceDictionary resourceDict = Application.LoadComponent(uri) as ResourceDictionary;
    Application.Current.Resources.MergedDictionaries.Clear();
    Application.Current.Resources.MergedDictionaries.Add(resourceDict);
}

// Example Usage (anywhere in app)
private void ThemeRed_Click(object sender, RoutedEventArgs e)
{
    var app = App.Current as App;
    app.ChangeTheme(new Uri(@"/Resources/Themes/RedTheme.xaml", UriKind.Relative));      
}

Upvotes: 2

ShadowKras
ShadowKras

Reputation: 343

Im using the following command to set the theme at runtime:

Application.Current.Resources.Source = new Uri("/Themes/ShinyRed.xaml", UriKind.RelativeOrAbsolute);

Upvotes: 7

IAmTimCorey
IAmTimCorey

Reputation: 16755

Here is an article that will walk you through it:

http://svetoslavsavov.blogspot.com/2009/07/switching-wpf-interface-themes-at.html

Basically you need to remove the "old" theme from the resource dictionary and then merge in the new one. The above article shows you how to make this change very simple.

Upvotes: 7

Related Questions