A StaticResource with a Path property
Suppose you have a resource (say
MyResource
) which has some member (say
MyMember
) which you want to access in an XAML file. Since the
StaticResource
markup extension has no
Path
property, this is not directly possible, if one cannot use a binding. Here I give an extension,
StaticResourceEx
, which is the same as
StaticResource
, but with a
Path
property.
Usage:
<my:StaticResourceEx ResourceKey="MyResource" Path="MyMember"/>
The code for StaticResourceEx looks as follows:
class StaticResourceEx : StaticResourceExtension
{
public PropertyPath Path { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
object o = base.ProvideValue(serviceProvider);
return (Path==null ? o : PathEvaluator.Eval(o, Path));
}
class PathEvaluator : DependencyObject
{
private static readonly DependencyProperty DummyProperty =
DependencyProperty.Register("Dummy", typeof(object),
typeof(PathEvaluator), new UIPropertyMetadata(null));
public static object Eval(object source, PropertyPath path)
{
PathEvaluator d = new PathEvaluator();
BindingOperations.SetBinding(d, DummyProperty,
new Binding(path.Path) { Source=source } );
return d.GetValue(DummyProperty);
}
}
}
The Motivating Example
I recently wanted to handle some commands in a non-UI component, which exists as a static resource of the main window. One solution is as follows:
- Let the non-UI component expose the
CommandBinding
. - Add this binding to the main window's
CommandBindings
.
The code for the second step in my example looks as follows:
<Window.CommandBindings>
<my:StaticResourceEx ResourceKey="FindReplaceComponent" Path="FindBinding"/>
<my:StaticResourceEx ResourceKey="FindReplaceComponent" Path="ReplaceBinding"/>
<my:StaticResourceEx ResourceKey="FindReplaceComponent" Path="FindNextBinding"/>
</Window.CommandBindings>
Note that you cannot directly use a binding in this situation.
Limitations, and when not to use it
The first thing to say is that if you can use a binding, i.e., if you want to assign a dependency property, you should definitely do so. Also it is important that the resource's member you reference is available on startup, since the value is only queried once. Finally, in the command binding example above, the Visual Studio designer sometimes whines that
StaticResourceEx
is not a
CommandBinding
. However, just recompiling removes this error. (If anyone knows how to remedy this, I'd be happy to know.)