添加一个静态的ResourceDictionary到用户控件的XAML解析之前,控件、静态、用户、XAML

2023-09-03 20:48:50 作者:海水不比泪咸

我有一个WPF控件,我想在我的WinForms应用程序使用(使用ElementHost的)在几个地方(=>多个这种控制的情况下)。

I have one WPF control that I want to use in my WinForms application (using an ElementHost) in several places (=> multiple instances of this control).

此外,我想我的用户的所有实例共享一个ResourceDictionary中的一个单独的实例。

Furthermore I want all instances of my UserControl to share one single Instance of a ResourceDictionary.

在WPF应用程序我会做到这一点通过合并我的ResourceDictionary中的应用程序资源。

In WPF applications I would achieve that by merging my ResourceDictionary in the Application Resources.

不过,我不希望在我的WinForms应用程序创建一个WPF应用程序实例。 相反,我正在寻找另一种方式。

However, I don't want to create an WPF Application Instance in my WinForms application. Instead I am looking for another way.

我找到了一个解决办法,但我希望你知道更好的方法,不需要任何的背后code:

I found one solution but I am hoping you know a better way that does not require any code behind:

    public static class StaticRDProvider
{
    static ResourceDictionary rd;
    static StaticRDProvider()
    {
        var uri = new Uri("WpfControls;Component/GlobalResourceDictionary.xaml", UriKind.Relative);
        rd = (ResourceDictionary) Application.LoadComponent(uri);
    }

    public static ResourceDictionary GetDictionary
    {
        get { return rd; }
    }
}

UserControl.xaml.cs:

UserControl.xaml.cs:

    public partial class MyCustomUserControl : UserControl
{
    public MyCustomUserControl()
    {
        Resources.MergedDictionaries.Add(StaticRDProvider.GetDictionary);

        InitializeComponent();
    }
}

这是工作。但我preFER一个解决方案,只适用于XAML。另外,我希望能够用StaticResources。因此,添加静态的ResourceDictionary到Controls MergedDictionaries初始化之后的控制不是一个选项。

That works. But I prefer a solution that only works with XAML. Plus I want to be able to use StaticResources. Therefore adding the static ResourceDictionary to the Controls MergedDictionaries after the control was initialized is not an option.

我尝试以下,但它抛出一个奇怪的栈是空的例外:

I tried the following, but it throws a strange "stack is empty" exception:

<UserControl x:Class="WpfControls.MyCustomUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:WpfControls="clr-namespace:WpfControls" mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>                
            <x:Static Member="WpfControls:StaticRDProvider.GetDictionary"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

</UserControl.Resources>
<Grid>
</Grid>

也许有人知道一个更好的办法。

Maybe someone knows a better approach.

谢谢, TwinHabit

Thanks, TwinHabit

推荐答案

你尝试加载您的用户控件内部的RD你会做它的应用程序类相同的?

Did you try loading the RD inside your UserControl the same you would do it with the Application class?

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>                
            <ResourceDictionary Source="WpfControls;Component/GlobalResourceDictionary.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

此方式,您只需指定的URI在用户的控制,避免了静态成员共费尽口舌

This way you just specify the URI in your user control, and avoid the static members hassle altogether.

顺便说一句,请务必使用正确的URI语法如果RD是不是在同一个组件设置为用户控件。例如:包://应用:,,, / YourAssembly;组件/子文件夹/ YourResourceFile.xaml 的(的更多关于包的URI信息)

BTW, make sure to use the correct URI syntax if the RD is not in the same assembly as the UserControl. For example: pack://application:,,,/YourAssembly;component/Subfolder/YourResourceFile.xaml (more info on pack URIs)