WPF 动态更改资源文件和主题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17928616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Dynamically change resource file and theme
提问by Shawn
My project uses a ProjectTheme.xaml file for all WPF windows through out the project. The ProjectTheme.xaml file references a style theme as follows
我的项目在整个项目中为所有 WPF 窗口使用 ProjectTheme.xaml 文件。ProjectTheme.xaml 文件引用了一个样式主题,如下所示
<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's theme, change this line -->
<ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
All WPF Windows references WindowBase.xaml
所有 WPF Windows 引用 WindowBase.xaml
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyProject;component/View/WindowBase.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
WindowBase.xaml references customized titlebar Bar1.xaml
WindowBase.xaml 引用自定义标题栏 Bar1.xaml
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Bar1.xaml" />
</ResourceDictionary.MergedDictionaries>
Bar1.xaml references ProjectTheme.xaml
Bar1.xaml 引用 ProjectTheme.xaml
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyProject;component/ProjectTheme.xaml"/>
</ResourceDictionary.MergedDictionaries>
So the heriarchy is
所以继承关系是
- Window1 references WindowBase.xaml
- WindowBase references Bar1.xaml
- Bar1 references ProjectTheme.xaml
- ProjectTheme.xaml reference the real theme resource file.
- Window1 引用 WindowBase.xaml
- WindowBase 引用 Bar1.xaml
- Bar1 引用 ProjectTheme.xaml
- ProjectTheme.xaml 引用真实的主题资源文件。
This works fine. Now I want to dynamically change the project theme at run time without quitting the app. Assuming that I have several theme style files
这工作正常。现在我想在不退出应用程序的情况下在运行时动态更改项目主题。假设我有几个主题样式文件
- Customized.xaml
- Customized1.xaml
- Customized2.xaml
- 自定义.xaml
- 自定义1.xaml
- 自定义2.xaml
My question is if it possible to dynamically update ProjectTheme.xaml file at run time to change the line from
我的问题是是否可以在运行时动态更新 ProjectTheme.xaml 文件以更改行
<ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized.xaml" />
to
到
<ResourceDictionary Source="/MyProject;component/Themes/WPFThemes/Customized1.xaml" />
to achieve my objective? If yes, how do I do it? If no, what is the reason and what is the best (other) way to achieve my purpose?
达到我的目标?如果是,我该怎么做?如果不是,原因是什么,实现我的目的的最佳(其他)方法是什么?
I have tried the following but none of them work: the style does not change.
我尝试了以下但没有一个工作:风格没有改变。
way 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 dynamic resource and static resource. Does that matters?
注意:在我的真实主题样式文件(Customized.xaml...)中,我使用了动态资源和静态资源的组合。那重要吗?
Thanks in advance.
提前致谢。
回答by Will Eddins
There are a few things to consider here.
这里有几件事情需要考虑。
First, anything defined with StaticResourcewill not get updated on a change. If you want a control to support changing the theme at runtime, you need to use DynamicResourceso it knows to look for changes.
首先,任何定义的内容StaticResource都不会在更改时更新。如果您希望控件支持在运行时更改主题,则需要使用DynamicResource它,以便它知道查找更改。
Your overall approach to changing the theme is correct. The easiest way to accomplish this is using Application-scoped resource dictionaries, making sure your ResourceDictionaryis defined in your App.xaml. For adding a new resource, I've used snippets similar to the following:
您更改主题的总体方法是正确的。完成此操作的最简单方法是使用应用程序范围的资源字典,确保您ResourceDictionary的App.xaml. 为了添加新资源,我使用了类似于以下内容的片段:
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(dict);
The part you may be confusing yourself over is when using resources within base classes. When you define a resource in a class, the resource will be local to an instance of that type. Think of the XAML compiling into it's own InitializeComponent()method on classes, meaning you can't change the original XAML and expect the changes to go to all instances. On the same note, changing the resources on a class instance doesn't effect other instances.
您可能会混淆的部分是在基类中使用资源时。当您在类中定义资源时,该资源将是该类型实例的本地资源。考虑将 XAML 编译成它自己的InitializeComponent()类方法,这意味着您无法更改原始 XAML 并期望更改会应用于所有实例。同样,更改类实例上的资源不会影响其他实例。
Since your question really contains two separate concerns (application theming and changing control resources), I would focus on ensuring your application resources are updating properly and using DynamicResource, and hopefully the information I've provided would be sufficient for understanding why certain other resources may not be updating yet.
由于您的问题确实包含两个单独的问题(应用程序主题和更改控制资源),我将重点确保您的应用程序资源正确更新和使用DynamicResource,希望我提供的信息足以理解为什么某些其他资源可能不会还在更新。

