首页 > 解决方案 > 在运行时修改 WPF 资源,其中资源在共享 dll 的资源字典中定义

问题描述

我的 WPF 项目引用了另一个项目。在引用的项目中,我定义了一些颜色和画笔。

共享 dll 的资源:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    <Color x:Key="FooColor">#FF00FF00</Color>
    <SolidColorBrush x:Key="FooColorBrush" Color="{DynamicResource FooColor}" />
</ResourceDictionary>

主项目的 App.xaml:

<Application x:Class="MyProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             ShutdownMode="OnExplicitShutdown">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Shared;component/UI/Resources.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

如何在运行时修改共享 dll 资源的颜色/画笔?

在我的 App.xaml.cs 中,我尝试了:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        //base.OnStartup(e)
        
        // Didn't work - tried modifying the color from this.Resources
        this.Resources.Remove("FooColor");
        this.Resources.Add("FooColor", Color.FromArgb(255, 255, 255, 0));

        // Didn't work - tried modifying the color from the Merged Dictionary
        ResourceDictionary sharedResources = this.Resources.MergedDictionaries.First(x => x.Source.OriginalString.Contains("/Shared;component/UI/Resources.xaml"));
        sharedResources.Remove("FooColor");
        sharedResources.Add("FooColor", Color.FromArgb(255, 255, 255, 0));
    }
}

如果我试图修改的资源是在当前项目的 App.xaml 中定义的,那么这很好用:

this.Resources.Remove(resourceKey);
this.Resources.Add(resourceKey, newValue);

为了测试它,在我的 MainWindow.xaml 中我有:

<Window x:Class="MyProject.MainWindow"
        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"

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Shared;component/UI/Resources.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <TextBlock Foreground="{DynamicResource FooColorBrush}" Text="Hello world" />
</Window>

期望前景色将更改为我在运行时在我的 App.xaml.cs () 中设置的值,而不是在共享资源 xaml 文件 ( )Color.FromArgb(255, 255, 255, 0)中定义的颜色<Color x:Key="FooColor">#FF00FF00</Color>

标签: c#wpfxamlresourcedictionaryapp.xaml

解决方案


弄清楚了。我所要做的就是从我的 MainWindow.xaml 中删除 MergedDictionaries。我的 App.xaml.cs 代码正在修改 App.xaml 的 MergedDictionary,但由于我还在 MainWindow.xaml 上定义了 MergedDictionary,因此 MainWindow.xaml 正在获取另一个未被覆盖的资源副本,并优先于来自 App.xaml 的已编辑版本。

改变了这个:

<Window x:Class="MyProject.MainWindow"
        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"

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Shared;component/UI/Resources.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <TextBlock Foreground="{DynamicResource FooColorBrush}" Text="Hello world" />
</Window>

对此:

<Window x:Class="MyProject.MainWindow"
        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"
    <TextBlock Foreground="{DynamicResource FooColorBrush}" Text="Hello world" />
</Window>

或者,我可以添加将资源更改为 MainWindow.xaml.cs 的逻辑:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.Resources.Remove("FooColor");
        this.Resources.Add("FooColor", Color.FromArgb(255, 255, 255, 0));
    }
}

推荐阅读