WPF 动态更改资源文件和主题 [英] WPF Dynamically change resource file and theme

查看:52
本文介绍了WPF 动态更改资源文件和主题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目在整个项目中为所有 WPF 窗口使用 ProjectTheme.xaml 文件.ProjectTheme.xaml 文件引用了一个样式主题,如下

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

<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>

所有 WPF Windows 引用 WindowBase.xaml

All WPF Windows references WindowBase.xaml

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

WindowBase.xaml 引用自定义标题栏 Bar1.xaml

WindowBase.xaml references customized titlebar Bar1.xaml

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

Bar1.xaml 引用 ProjectTheme.xaml

Bar1.xaml references ProjectTheme.xaml

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

所以层次是

  • 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

我的问题是如果可以在运行时动态更新 ProjectTheme.xaml 文件以更改行来自

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

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

<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.

方式一

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

方式二

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

注意:在我的真实主题样式文件(Customized.xaml...)中,我使用了动态资源和静态资源的组合.这重要吗?

Note: In my real theme style files (Customized.xaml...) I used a combination of dynamic resource and static resource. Does that matters?

提前致谢.

推荐答案

这里有几件事情需要考虑.

There are a few things to consider here.

首先,使用 StaticResource 定义的任何内容都不会在更改时更新.如果您希望控件支持在运行时更改主题,则需要使用 DynamicResource 以便它知道查找更改.

First, anything defined with StaticResource will not get updated on a change. If you want a control to support changing the theme at runtime, you need to use DynamicResource so it knows to look for changes.

您更改主题的总体方法是正确的.完成此操作的最简单方法是使用 应用程序范围的资源词典,确保您的 ResourceDictionary 在您的 App.xaml 中定义.为了添加新资源,我使用了类似于以下内容的代码段:

Your overall approach to changing the theme is correct. The easiest way to accomplish this is using Application-scoped resource dictionaries, making sure your ResourceDictionary is defined in your App.xaml. For adding a new resource, I've used snippets similar to the following:

ResourceDictionary dict = new ResourceDictionary();
dict.Source = new Uri("MyResourceDictionary.xaml", UriKind.Relative);

Application.Current.Resources.MergedDictionaries.Add(dict);

您可能会混淆的部分是在基类中使用资源时.当您在类中定义资源时,该资源将是该类型实例的本地资源.想象一下 XAML 编译成它自己的 InitializeComponent() 方法在类上,这意味着您不能更改原始 XAML 并期望更改适用于所有实例.同样,更改类实例上的资源不会影响其他实例.

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.

由于您的问题确实包含两个独立的问题(应用程序主题化和更改控制资源),我将重点确保您的应用程序资源正确更新并使用 DynamicResource,希望我提供的信息足以理解为什么某些其他资源可能尚未更新.

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.

这篇关于WPF 动态更改资源文件和主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆