如何更改资源以在整个应用程序中传播,包括在ValueConverters中?

时间:2009-06-12 07:06:08

标签: c# wpf resources app-themes

我有一个应用程序,允许用户根据外部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没有与窗口保持相同的资源集。我已经尝试将主题加载到Application.Current.Resources并从转换器中读取,但这似乎也不起作用。谁能告诉我我在这里缺少什么?有没有办法改变,例如,Application.Current.Resources并让它影响打开的窗口?

谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

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