在运行时更改DynamicResource颜色值

时间:2013-10-17 12:55:37

标签: c# wpf

我的目标是在Base主题中定义样式,并且可以使用ResourceDictionary通过将它们添加到彼此之上来覆盖Custom主题中的某些值。我已经能够使用某些属性而不是其他属性,显然是由于Freezable Objects,颜色是不起作用的。我认为更改ResourceDictionary中的Color值会起作用但不是:

MainWindow.xaml:

<Grid Background="{DynamicResource PrimaryBackgroundColor}">

基础\ Base.xaml:

<SolidColorBrush x:Key="PrimaryBackgroundColor" Color="{DynamicResource Color_Base}"/>

基础\ Colors.xaml:

<Color x:Key="Color_Base">Red</Color>

定制\ Colors.xaml:

<Color x:Key="Color_Base">Blue</Color>

Theme.cs:

foreach (ResourceDictEntry rde in changeList)
{
    Application.Current.Resources
               .MergedDictionaries
               .ElementAt(rde.dicIndex)[rde.key] = rde.value;
}

当我单步执行时,代码似乎正常工作我看到Color_Base的MergedDictionary条目已从红色#FFFF0000更改为蓝色#FF0000FF

但是,我的Grid的背景绑定到DynamicResource PrimaryBackgroundColor并没有从Red更改为Blue。

Snoop中没有显示错误; Grid.Background值将PrimaryBackgroundColor显示为红色(#FFFF0000)。

我错过了什么?如何在运行时更改我的颜色值?

对于完整代码,这里有一个要点:https://gist.github.com/dirte/773e6baf9a678e7632e6

编辑:

这看起来是最相关的:https://stackoverflow.com/a/17791735/1992193但我认为样式的全部意义在于将它定义在一个地方并让一切都使用它而不必修改后面的每个xaml /代码?什么是最好的解决方案?

我知道一个解决方案是简单地将整个基本主题复制到自定义主题中,并且只加载您想要的主题,但是它需要在每个不需要的主题文件中管理每个属性。

1 个答案:

答案 0 :(得分:2)

我能够通过简单地将所有资源字典文件组合成代码中的单个资源字典并应用最终的组合资源字典来制定解决方案。

public static void ChangeTheme(string themeName)
{
    string desiredTheme = themeName;    
    Uri uri;
    ResourceDictionary resourceDict;
    ResourceDictionary finalDict = new ResourceDictionary();

    // Clear then load Base theme
    Application.Current.Resources.MergedDictionaries.Clear();
    themeName = "Base";
    foreach (var themeFile in Util.GetDirectoryInfo(Path.Combine(ThemeFolder, themeName)).GetFiles())
    {
        uri = new Uri(Util.GetPath(Path.Combine(ThemeFolder, themeName + @"\" + themeFile.Name)));
        resourceDict = new ResourceDictionary { Source = uri };
        foreach (DictionaryEntry de in resourceDict)
        {
            finalDict.Add(de.Key, de.Value);
        }
    }
    // If all you want is Base, we are done
    if (desiredTheme == "Base")
    {
        Application.Current.Resources.MergedDictionaries.Add(finalDict);
        return;
    }

    // Now load desired custom theme, replacing keys found in Base theme with new values, and adding new key/values that didn't exist before
    themeName = desiredTheme;
    bool found;
    foreach (var themeFile in Util.GetDirectoryInfo(Path.Combine(ThemeFolder, themeName)).GetFiles())
    {
        uri = new Uri(Util.GetPath(Path.Combine(ThemeFolder, themeName + @"\" + themeFile.Name)));
        resourceDict = new ResourceDictionary { Source = uri };
        foreach (DictionaryEntry x in resourceDict)
        {
            found = false;
            // Replace existing values
            foreach (DictionaryEntry z in finalDict)
            {
                if (x.Key.ToString() == z.Key.ToString())
                {
                    finalDict[x.Key] = x.Value;
                    found = true;
                    break;
                }
            }

            // Otherwise add new values
            if (!found)
            {
                finalDict.Add(x.Key, x.Value);
            }
        }
    }

    // Apply final dictionary
    Application.Current.Resources.MergedDictionaries.Add(finalDict);
}

MainWindow.xaml:

<Grid Background="{DynamicResource PrimaryBackgroundColor}">

Base.xaml:

<SolidColorBrush x:Key="PrimaryBackgroundColor" Color="{DynamicResource Color_Base}"/>

基础\ Colors.xaml:

<Color x:Key="Color_Base">Red</Color>

定制\ Colors.xaml:

<Color x:Key="Color_Base">Blue</Color>