0

我的目标是在 Base 主题中定义样式,并能够通过使用ResourceDictionary. 由于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>

主题.cs:

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

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

但是,我的背景绑定到 DynamicResource 的网格PrimaryBackgroundColor没有从红色更改为蓝色。

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

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

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

编辑:

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

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

4

1 回答 1

3

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

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>
于 2013-10-17T14:15:22.997 回答