You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过静态成员获取ResourceDictionary并实现设计时支持?

问题描述

核心需求是在DLL中存放ResourceDictionary,通过ResourceDictionary.MergedDictionaries在另一个WPF项目中引用,但不想在引用项目的XAML里硬编码URI,希望通过静态成员提供URI。

当前实现运行正常,但设计时会报错且无IntelliSense支持(示例中所有内容在同一程序集内,未使用独立DLL)。

资源字典文件 Dic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <SolidColorBrush Color="Blue" x:Key="BlueBrush"/>
</ResourceDictionary>

存放URI的静态成员模块

VB.NET版本

Public Module Foo
    '[VBTest]为程序集名称
    Public ReadOnly Property URI As New Uri("pack://application:,,,/VBTest;component/Dic.xaml")
End Module

C#版本

public static class Foo
{
    //[VBTest]为程序集名称
    public static Uri URI { get; } = new Uri("pack://application:,,,/VBTest;component/Dic.xaml");
}

引用资源字典的XAML代码

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:VBTest">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="{x:Static local:Foo.URI}"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Border Width="100" Height="100" Background="{StaticResource BlueBrush}"/>
</Window>

设计时错误信息

XDG0062 An error occurred while finding the resource dictionary ""."
XDG0062 The resource "BlueBrush" could not be resolved.

项目可正常构建运行,能显示预期的蓝色方块,请问如何让该实现支持设计时?


解决方案

方法1:改用字符串常量替代Uri实例

问题根源是设计时WPF解析器无法正确识别静态属性返回的Uri对象,将静态成员改为返回字符串类型的URI即可解决:

C#修改后

public static class Foo
{
    public const string URIString = "pack://application:,,,/VBTest;component/Dic.xaml";
    public static Uri URI => new Uri(URIString);
}

VB.NET修改后

Public Module Foo
    Public Const URIString As String = "pack://application:,,,/VBTest;component/Dic.xaml"
    Public ReadOnly Property URI As New Uri(URIString)
End Module

然后在XAML中直接引用字符串常量:

<ResourceDictionary Source="{x:Static local:Foo.URIString}"/>

这种方式下,设计时XAML解析器能直接识别字符串格式的URI,正常加载资源字典,同时不影响运行时逻辑。

方法2:添加设计时专用的URI转换器

实现一个标记扩展转换器,在设计时返回硬编码的URI,运行时使用静态成员的URI:

C#转换器代码

public class DesignTimeUriConverter : MarkupExtension, IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
        {
            return new Uri((string)values[1], UriKind.RelativeOrAbsolute);
        }
        return values[0];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

VB.NET转换器代码

Public Class DesignTimeUriConverter
    Inherits MarkupExtension
    Implements IMultiValueConverter

    Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert
        If DesignerProperties.GetIsInDesignMode(New DependencyObject()) Then
            Return New Uri(CStr(values(1)), UriKind.RelativeOrAbsolute)
        End If
        Return values(0)
    End Function

    Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function

    Public Overrides Function ProvideValue(serviceProvider As IServiceProvider) As Object
        Return Me
    End Function
End Class

XAML中使用转换器

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary>
                <ResourceDictionary.Source>
                    <MultiBinding Converter="{local:DesignTimeUriConverter}">
                        <Binding Source="{x:Static local:Foo.URI}"/>
                        <Binding Source="pack://application:,,,/VBTest;component/Dic.xaml"/>
                    </MultiBinding>
                </ResourceDictionary.Source>
            </ResourceDictionary>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

方法3:跨DLL场景使用ComponentResourceKey

如果最终要在独立DLL中存放资源字典,可直接给资源定义ComponentResourceKey,无需手动合并字典:

  1. 在DLL的资源字典中配置资源:
<SolidColorBrush Color="Blue" 
                 x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:Foo}, ResourceId=BlueBrush}" 
                 x:Shared="false"/>
  1. 在引用项目中直接引用资源:
<Border Background="{DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type local:Foo}, ResourceId=BlueBrush}}"/>

这种方式设计时能直接识别资源,同时避免硬编码字典URI。


内容的提问来源于stack exchange,提问作者Keith Stein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:10:46