Home > Blockchain >  Get ResourceDictionary source from static member with design-time support
Get ResourceDictionary source from static member with design-time support

Time:10-29

My basic goal is to have a ResourceDictionary in a dll which I can use in another WPF project via ResourceDictionary.MergedDictionaries. But I don't want to reference the ResourceDictionary by hard-coding the URI in the XAML of the referencing application, I want to instead reference some static member which will provide the URI.

I have some simplified code which is "working", but only at runtime. At design-time it throws errors and I get no IntelliSense support. For this simplified example, everything is in one assembly (no separate dll).

Dic.xaml (the resource dictionary I want to reference):

<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>

Foo (the module to hold the static member with the URI):
(VB.NET version)

Public Module Foo
    '[VBTest] is the name of assembly
    Public ReadOnly Property URI As New Uri("pack://application:,,,/VBTest;component/Dic.xaml")
End Module

(C# version)

public static class Foo
{
    //[VBTest] is the name of assembly
    public static Uri URI { get; } = new Uri("pack://application:,,,/VBTest;component/Dic.xaml");
}

And then finally, the place in the application where I want to reference the ResourceDictionary:

<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>

At design-time, I get two errors:

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

However, the project will build and run just fine. And will show the intended blue square.

The question is, how can I get this to work at design-time?

CodePudding user response:

I found a thankfully easy workaround. Maybe not the prettiest, but it is elegant. I took inspiration from this answer to a somewhat related question.

By creating my own class inheriting from ResourceDictionary, I can better control the loading behavior. That sounds like it would be complicated, but really all I had to do was set Source as part of the constructor and everything just worked.

The below is added to the code file (outsite of Module/static class Foo):

Public Class StylesResourceDictionary
    Inherits ResourceDictionary

    Public Sub New()
        MyBase.New()
        Source = URI
    End Sub
End Class

Note that Source = URI is referencing Foo.URI from the question code.

And then the XAML file becomes:

<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>
                <local:StylesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

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

And bam, full design-time support without hard-coding the URI into the referencing application. Control of the ResourceDictionary and its URI is now in the domain of the dll, and can be referenced in a (kinda) static fashion using the dedicated class.

  • Related