如何使资源更改传播到整个应用程序(包括 ValueConverters)?

发布于 2024-07-24 08:35:46 字数 1110 浏览 9 评论 0原文

我有一个应用程序,允许用户根据外部 xaml 文件更改配色方案。 当用户单击包含主题名称的 MenuItem 时,将执行以下代码:

MenuItem mi = sender as MenuItem;
string executingDirectory = Assembly.GetExecutingAssembly().Location.Substring(0, Assembly.GetExecutingAssembly().Location.LastIndexOf("\\"));
string path = System.IO.Path.Combine(executingDirectory + "\\Themes", mi.Header.ToString() + ".xaml");

if (File.Exists(path))
{
    using (FileStream fs = new FileStream(path, FileMode.Open))
    {
        ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
        Resources.MergedDictionaries.Clear();
        Resources.MergedDictionaries.Add(dic);
    }
}

这适用于大多数应用程序 – 我的所有资源画笔都会发生变化 – 但有一个例外。 我有一个子控件,其背景颜色由使用转换器的值绑定确定。 不过,我没有将颜色硬编码到转换器中,而是让转换器使用字符串常量作为画笔名称,然后从 App.Current.Resources 返回颜色:

Brush ret = Application.Current.Resources[brushToReturn] as Brush;

这里似乎发生的是 Application.Current.Resources 不是“ t 持有与窗口相同的资源集。 我尝试将主题加载到 Application.Current.Resources 中并从转换器中读取主题,但这似乎也不起作用。 谁能告诉我我在这里缺少什么? 有没有办法改变,比如说,Application.Current.Resources 并让它影响打开的窗口?

谢谢!

I have an application that allows the user to change color schemes based on an external xaml file. When the user clicks on a MenuItem that contains the name of a theme, the following code executes:

MenuItem mi = sender as MenuItem;
string executingDirectory = Assembly.GetExecutingAssembly().Location.Substring(0, Assembly.GetExecutingAssembly().Location.LastIndexOf("\\"));
string path = System.IO.Path.Combine(executingDirectory + "\\Themes", mi.Header.ToString() + ".xaml");

if (File.Exists(path))
{
    using (FileStream fs = new FileStream(path, FileMode.Open))
    {
        ResourceDictionary dic = (ResourceDictionary)XamlReader.Load(fs);
        Resources.MergedDictionaries.Clear();
        Resources.MergedDictionaries.Add(dic);
    }
}

This works for most of the application – all of my resource brushes change – with one exception. I have a subcontrol whose background color is determined by a value binding using a converter. Rather than hard-code the colors into the converter, though, I had the converter use string constants for brush names and then return the color from App.Current.Resources:

Brush ret = Application.Current.Resources[brushToReturn] as Brush;

What seems to be happening here is that Application.Current.Resources isn’t holding the same set of resources as the window. I have tried loading the theme into Application.Current.Resources and reading from that in the converter, but that doesn’t seem to work either. Can anyone tell me what I’m missing here? Is there a way to change, say, Application.Current.Resources and have it affect the opened windows?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冬天旳寂寞 2024-07-31 08:35:46

如果没有看到所有代码,很难说,但检查 Resources 属性不会自动检查合并的字典。 另外,如果您在Window级别合并主题资源,那么它们根本不会在应用程序级别。 为了保持一致性,您最好让转换器掌握要转换的元素并使用 FindResource

var frameworkElement = values[0] as FrameworkElement;
var resource = frameworkElement.FindResource("SomeKey") as Brush;

使用 IMultiValueConverter 可能是您的最佳选择。 或者,如果这变得太混乱,您可能会考虑编写一个满足您需要的标记扩展。

It's hard to say without seeing all your code, but checking the Resources property does not automatically check merged dictionaries. Also, if you're merging the theme resources at the Window level then they won't be at the application level at all. For consistency sake, you're best off having your converter get a hold of the element it is converting for and using FindResource:

var frameworkElement = values[0] as FrameworkElement;
var resource = frameworkElement.FindResource("SomeKey") as Brush;

Using an IMultiValueConverter might be your best option. Alternatively, if that gets too messy, you might look into writing a markup extension that does what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文