25

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?

5 Answers 5

37

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")); 
Sign up to request clarification or add additional context in comments.

6 Comments

@grv_9098: I don't know.
what if I have only the name of the theme and not the URI?
@PieroAlberto: The URI can directly be constructed from name and location of the theme. See MSDN.
@H.B. I've done it in this way: ThemeManager.ApplicationThemeName = this.p_PRF_TEMA; but it is very slow... is there something reasons to slow down this action?? it takes something like 15 20 seconds to change the theme!
@PieroAlberto: Well, it has to recreate the entire UI, depending on its complexity that may take quite a while.
|
7

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.

1 Comment

I did something similar visible here, I think it's more MVVM friendly, moreover, it automatically feed the list of available themes.
7

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

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

1 Comment

This will replace all the resources in your Application object, which may not be what you want.
7

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();

Comments

2

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)); } 

3 Comments

Although it will use the new dictionary on new calls It does not update the window with current values even after I call InvalidateVisual
I have the same problem. Did you managed to get it working eventually?
It might be because you're using StaticResource rather than DynamicResource in your XAML.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.