Check the following scenario (others may apply as well) [you can create the project just copy pasting the code here on the right file]:
a - Create a ResourceDictionary with basic stuff (Resources.xaml):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush Color="Red" x:Key="Test" />
<Style TargetType="{x:Type GroupBox}" x:Key="Test2" >
<Setter Property="Background" Value="Blue" />
</Style>
<Style TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="Green" />
</Style>
</ResourceDictionary>
b - Create a user control base where others will inherit containing basic resources (UserControlBase.cs):
using System.Windows.Controls;
using System;
using System.Windows;
namespace ResourceTest
{
public class UserControlBase : UserControl
{
public UserControlBase()
{
this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ResourceTest;component/Resources.xaml", UriKind.RelativeOrAbsolute) });
}
}
}
c - Create a UserControl inheriting from the base (UserControl1.xaml):
<ResourceTest:UserControlBase x:Class="ResourceTest.UserControl1"
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:ResourceTest="clr-namespace:ResourceTest"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300" >
<Grid>
<GroupBox BorderBrush="{StaticResource Test}" Margin="3" Header="Test" Style="{DynamicResource Test2}" >
<TextBlock Text="TESTTEST" />
</GroupBox>
</Grid>
</ResourceTest:UserControlBase>
Results: StaticResources are not resolved (and the Test BorderBrush is not loaded). DynamicResources are resolved (the background is blue) but the designer says that it cannot find the resource anyway (the first time works ok but when you open/close the designer the resource cannot be resolved). Non named resources like the TextBlock style work ok.
Is this a designer bug or am I doing something wrong? Is ok to have to declare the resources as dynamic in an scenario where the resources will never change?
Thanks in advance.
It appears the designer has trouble resolving MergedDictionaries
that are defined in the code-behind at design-time.
An even worse example can be seen by moving the ResourceDictionary
to before your Initialize.
public UserControl1()
{
this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("TempProject;component/Resources.xaml", UriKind.RelativeOrAbsolute) });
InitializeComponent();
}
In this case, the DynamicResource
even fails to resolve at design-time, indicating the design-time view is not necessarily calling the constructors as you may expect. I tested this with Visual Studio 2012, so this behavior has not changed since 2010.
in terms of your original test code, note that the StaticResource
does successfully bind as expected at run-time (the red border appears), regardless of the "error" thrown and lack of a red border by the design-time view.
I see two options:
Use DynamicResource
where necessary to resolve these at design-time. While you can use StaticResource
, the associated "errors" and lack of design-time view would clearly be a problem. Other answers seem to indicate there may not be much performance difference between the two now.
Simply instantiate the ResourceDictionary in your UserControl.Resources
, and don't inherit from a base class. While you're condensing a bit of code using a base class, you're not being any more efficient, since a new ResourceDictionary
instance is going to be created everytime. Since you can't (AFAIK) extend from a base class with a XAML front-end, you could potentially argue against having an unreferenced MergedDictionary
at this level of abstraction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With