如何使资源更改传播到整个应用程序(包括 ValueConverters)?
我有一个应用程序,允许用户根据外部 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果没有看到所有代码,很难说,但检查
Resources
属性不会自动检查合并的字典。 另外,如果您在Window
级别合并主题资源,那么它们根本不会在应用程序级别。 为了保持一致性,您最好让转换器掌握要转换的元素并使用FindResource
:使用
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 theWindow
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 usingFindResource
: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.