Locke
Locke

Reputation: 1165

WPF Styling from External Libraries and Static Resources

I'm writing several C# controls in a library that will be accessed throughout an entire application. My structure looks like this:

Solution

-App 1

-App 2

-App 3

-Control Library (with WPF Control's)

Everything works mostly well -- but the thing is that I also have some resources in my code that are trying to be accessed from that Control Library.

The Control Library has a StyleLoader, which will execute the following (and is executed prior to loading each App):

    public static void IncludeVisualStyles(Control control)
    {
        control.Resources.MergedDictionaries.Add(
            new ResourceDictionary
            {
                Source = new Uri("pack://application:,,,/my.app.UI;component/Styles/generic.xaml",
                                  UriKind.RelativeOrAbsolute)
            });
    }

Each app calls this StyleLoader.IncludeVisualStyles(x) on it's root Window.

Now, if my Window/View's use an item in this library, i.e. MyAppColor, it cannot find it, if I were to use the following line (in App1):

<TextBlock>

<TextBlock.Foreground>

<SolidColorBrush Color="{StaticResource MyAppColor}">

</TextBlock.Foreground>

</TextBlock>

It will throw a XamlParseException, claiming it cannot find the MyAppColor. If I manually link in the Resource at the top of the UserControl in App1 (not the Window) with the XAML equivalent of the StyleLoader.IncludeVisualStyles (creating a Merged Dictionary in the UserControl.Resources) it works fine. But I don't want to have to do this manually, and instead, to link the resources with code.

I'm contemplating going the route of creating a static styling library and just using x:Static Library.MyAppColor, but this seems like a workaround that might confuse other WPF developers.

Any thoughts on how to fix this or what might be happening? Any further consideration with how resources and styles work would be immensely appreciated.

EDIT: Might I also add that if I make the StaticResource's DynamicResource's, they SOMETIMES work. For example, if I have ControlA and ControlB, ControlA will not receive the styling/color correctly, while ControlB will -- and this is on base controls for WPF, like a Border, TextBlock, CheckBox, etc.

EDIT 2: The application's are not "true" applications -- they contain a logical bootstrapper that creates Windows. They exist as plugins to VSTO's, which has no concept of an application. My thoughts were to link in the resources to the Window, and hope that when searching for the resource, it would search up the tree to THAT merged dictionary, but no such luck.

Upvotes: 1

Views: 2333

Answers (1)

vesan
vesan

Reputation: 3369

Now I'm not sure what exactly your project structure looks like, but the following works for me:

Create a WPF Control Library project, add a Resource Dictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="testBrush" Color="Red"></SolidColorBrush>
</ResourceDictionary>

Create a WPF application, add a Startup event to App.xaml with the following code (pretty much what you did):

private void Application_Startup(object sender, StartupEventArgs e)
{
    Resources.MergedDictionaries.Add(
        new ResourceDictionary()
        {
            Source = new Uri("pack://application:,,,/WpfControlLibrary1;component/Dictionary1.xaml")
        });
}

Reference the resource in my Window:

<Window x:Class="WpfApplication1.MainWindow"
        ...        
        Background="{StaticResource testBrush}">

With Styles, it works the same.

If you want to add your resources later that this, you need to use DynamicResource instead. My guess is that you're calling your IncludeVisualStyles method too late. What exactly does it mean "prior to loading each app"? If you're doing it in Application_Startup, like I did, the Window is not created yet, unless you're creating it manually.

Of course, as HighCore remarked, unless you really have a good reason to not do it, just link it in App.xaml's Application.Resources.

Upvotes: 2

Related Questions