简体   繁体   English

为什么我添加到ResourceDictionary 后还是找不到资源?

[英]Why still can't find the resource after I add it into ResourceDictionary?

I want to achieve themes in my WPF program.我想在我的 WPF 程序中实现主题。

I stored the color in the database and then load it into MergedDictionaries .我将颜色存储在数据库中,然后将其加载到MergedDictionaries

Here are my codes:这是我的代码:

<Application x:Class="Test"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Test"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <ResourceDictionary.MergedDictionaries>
                    </ResourceDictionary.MergedDictionaries>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>            
        </ResourceDictionary>
    </Application.Resources>
</Application>

And here are code-behind:这里是代码隐藏:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Resources;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Resources;

namespace Test
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            ChangeTheme("Dark");
        }
        public ResourceDictionary ThemeDictionary
        {
            get { return Resources.MergedDictionaries[0]; }
        }
       
        public void ChangeTheme(string ThemeName)
        {
            Resources.MergedDictionaries.Clear();
            Resources.MergedDictionaries.Add(new ResourceDictionary());
            ///some logic to load color from database
            ThemeDictionary.Add("NormalBackground",new SolidColorBrush(Colors.Red));            
        }
    }
}

And here are sample of front-end:这是前端示例:

<Window x:Class="Test"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Test"
        mc:Ignorable="d"
        Height="450" Width="800">
    <Grid Background="{StaticResource NormalBackground}">
        
    </Grid>
</Window>

After the program ran.程序运行后。 VS reports error that cannot find StaticResource "NormalBackground". VS 报告找不到 StaticResource“NormalBackground”的错误。

Whereas, if I add an exist ResourceDictionary into the MergedDictionaries, all works well.然而,如果我将现有的 ResourceDictionary 添加到 MergedDictionaries 中,则一切正常。

What's wrong with my code?我的代码有什么问题? Thank you.谢谢你。

You are calling "ChangeTheme("Dark")" too early.您过早地调用“ChangeTheme("Dark")"。 It should be called from within OnStartup in App.xaml.cs.它应该从 App.xaml.cs 的 OnStartup 中调用。 I guess that the resource dictionaries defined in the xaml (which is empty in your case) will overwrite everything you put in there by code in your constructor.我猜 xaml 中定义的资源字典(在您的情况下为空)将覆盖您在构造函数中通过代码放入其中的所有内容。

public App()
{
  
}

protected override void OnStartup(StartupEventArgs e)
{
  base.OnStartup(e);

  ChangeTheme("Dark");
}

Also, you can remove the inner part of your MergedDictionaries from you App.xaml此外,您可以从 App.xaml 中删除 MergedDictionaries 的内部部分

<ResourceDictionary>
  <ResourceDictionary.MergedDictionaries>
  </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

According to the logic of work in the current implementation, you first set your dictionary in the App constructor.根据当前实现中的工作逻辑,首先在 App 构造函数中设置字典。 After that, the XAML is initialized.之后初始化XAML。 Upon XAML initialization, the <ResourceDictionary> tag creates a new dictionary and stores it in App.Resources.在 XAML 初始化时, <ResourceDictionary>标记创建一个新字典并将其存储在 App.Resources 中。 This action removes the instance you created in the constructor.此操作删除您在构造函数中创建的实例。 Therefore, when the UserControl is called, the App only has an empty dictionary in which your resource does not exist.因此,当调用 UserControl 时,应用程序只有一个空字典,其中不存在您的资源。

For your implementation to work properly, you should remove the <Application.Resources> section entirely from the XAML.为了使您的实施正常工作,您应该从 XAML 中完全删除<Application.Resources>部分。

<Application x:Class="Test"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:Test"
             StartupUri="MainWindow.xaml">
<!--    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <ResourceDictionary.MergedDictionaries>
                    </ResourceDictionary.MergedDictionaries>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>            
        </ResourceDictionary>
    </Application.Resources>-->
</Application>

As others have suggested, replacing StaticResource with DynamicResource is not a solution, as there is no resource itself with the specified key.正如其他人所建议的那样,用 DynamicResource 替换 StaticResource 不是解决方案,因为没有资源本身具有指定的键。 DynamicResource can help if you replace the resource pointed to by DynamicResource or the dictionary with this resource at runtime.如果您在运行时用此资源替换 DynamicResource 指向的资源或字典,DynamicResource 会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM