In solving a problem around dynamic resources tonight, I ended up with a solution that relied on the ability of a Behavior
class to participate in the resource hierarchy of it's associated framework element. For instance, consider the following
<Application>
<Application.Resources>
<system:String x:Key="TestString">In App Resources</system:String>
</Application.Resources>
</Application>
<Window>
<Window.Resources>
<system:String x:Key="TestString">In Window Resources/system:String>
</Window.Resources>
<Border>
<Border.Resources>
<system:String x:Key="TestString">In Border Resources</system:String>
</Border.Resources>
<TextBlock Text="{DynamicResource TestString}" />
</Border>
</Window>
The TextBlock will show the resource from the border. However, if I do this...
public void Test()
{
var frameworkElement = new FrameworkElement();
var testString = (string)frameworkElement.FindResource("TestString");
}
...it finds the one from the application because it is not part of the visual tree.
That said, if I instead do this...
public class MyBehavior : Behavior<FrameworkElement>
{
public string Value... // Implement this as a DependencyProperty
}
Then add it to the TextBlock like this...
<TextBlock Text="{DynamicResource TestString}">
<i:Interaction.Behaviors>
<local:MyBehavior Value="{DynamicResource TestString}" />
</i:Interaction.Behaviors>
</TextBlock>
The behavior does get the value of the resource and will track it dynamically. But how?
A Behavior is not a FrameworkElement so you can't call SetResourceReference on it, nor is it part of the Visual Tree so even if you could call SetResourceReference, it still wouldn't find resources local to the FrameworkElement. Yet that's exactly what a Behavior does. How?
Put another way, if we wanted to write our own class that also exhibited those same behaviors (no pun intended), how would one insert itself into the resource hierarchy of the visual tree?