WPF dynamically change resource file and theme

My project uses the ProjectTheme.xaml file for all WPF windows through the project. The ProjectTheme.xaml file references the style theme as follows

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ResourceDictionary.MergedDictionaries> <!-- In order to modify the project theme, change this line --> <ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> 

All links to WPF Windows WindowBase.xaml

 <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyProject;component/View/WindowBase.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> 

WindowBase.xaml refers to the custom bar1.xaml header

 <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Bar1.xaml" /> </ResourceDictionary.MergedDictionaries> 

Links Bar1.xaml ProjectTheme.xaml

 <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyProject;component/ProjectTheme.xaml"/> </ResourceDictionary.MergedDictionaries> 

So the heriarchy

  • Links Window1 WindowBase.xaml
  • Links WindowBase Bar1.xaml
  • Links Bar1 ProjectTheme.xaml
  • ProjectTheme.xaml refers to the actual theme resource file.

It works great. Now I want to dynamically change the theme of the project at runtime without leaving the application. Assuming I have some theme style files

  • Customized.xaml
  • Customized1.xaml
  • Customized2.xaml

My question is: if it is possible to dynamically update the ProjectTheme.xaml file at run time to change the line from

 <ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized.xaml" /> 

to

 <ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized1.xaml" /> 

to achieve my goal? If so, how do I do this? If not, what is the reason and what is the best (other) way to achieve my goal?

I tried the following, but none of them work: the style does not change.

method 1

 Application.Current.Resources.MergedDictionaries.Clear(); Uri NewTheme = new Uri(@"/MyProject;component/Themes/WPFThemes/Customized2.xaml", UriKind.Relative); ResourceDictionary dictionary = (ResourceDictionary)Application.LoadComponent(NewTheme); Application.Current.Resources.MergedDictionaries.Add(dictionary); 

way 2

 Application.Current.Resources.MergedDictionaries.RemoveAt(0); Uri NewTheme = new Uri(@"/MyProject;component/Themes/WPFThemes/Customized2.xaml", UriKind.Relative); ResourceDictionary dictionary = (ResourceDictionary)Application.LoadComponent(NewTheme); Application.Current.Resources.MergedDictionaries.Insert(0, dictionary); 

Note: In my real theme-style files (Customized.xaml ...), I used a combination of a dynamic resource and a static resource. It is important?

Thanks in advance.

+8
wpf mvvm
source share
1 answer

There are a few things here.

Firstly, everything that is defined using StaticResource will not be updated upon change. If you want the control to support theme change at runtime, you need to use DynamicResource so that it knows what to look for changes.

Your general approach to changing the topic is correct. The easiest way to achieve this is to use application resource resource dictionaries , making sure your ResourceDictionary defined in App.xaml . To add a new resource, I used fragments similar to the following:

 ResourceDictionary dict = new ResourceDictionary(); dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative); Application.Current.Resources.MergedDictionaries.Add(dict); 

The part that you can confuse is the use of resources in base classes. When you define a resource in a class, the resource will be local to an instance of this type. Consider compiling XAML into your own InitializeComponent() method for classes, which means that you cannot modify the original XAML and expect the changes to pass to all instances. In the same note, changing the resources of an instance of a class does not affect other instances.

Since your question really contains two separate problems (using applications and changing management resources), I would focus on ensuring the correct updating of application resources and using DynamicResource , and I hope the information I provided will be sufficient to understand why some other resources are still not updated.

+13
source share

All Articles