Pixel-in-Gene

Exploring Creativity with Design / Graphics / Technology

Huge Limitation of a MarkupExtension

MarkupExtensions are a Xaml-only way of providing extensions to the markup. It allows you to encapsulate procedural logic and provide value to attributes (DependencyProperties) inside of a Xaml document. To create a custom MarkupExtension you derive from the MarkupExtension class and override the ProvideValue() method. This method is called automatically by the framework when it needs the value for the DependencyProperty. Note that it is a one-time only call.

Its signature looks like so:

1
2
3
4
public override object ProvideValue(IServiceProvider serviceProvider)
{

}

The limitation

To get a handle at the target object and the associated DependencyProperty, you will have to probe into the IServiceProvider interface. This is done with the following statements:

1
2
3
4
5
var provideValueTarget = provider.GetService(typeof(IProvideValueTarget))
                                       as IProvideValueTarget;
var targetObject = provideValueTarget.TargetObject as DependencyObject;
var targetProperty = provideValueTarget.TargetProperty as DependencyProperty;
  

This is where you will hit the limitation. It is NOT necessary for the target object to be a DependencyObject (DO). A classic example is if you are using the MarkupExtension for a Setter.Value inside of a Style. In that case you would receive the Setter as the target object, which is certainly not a DO. The Setter target is not so useful unless you get a hold of the FrameworkElement on which the Style has been set. The association between the Style and the FrameworkElement happens at a much later time; unfortunately there is no way to know when that occurs.

How does the framework do it ?

What you could do at this stage is setup some kind of a placeholder value that stores the context of the MarkupExtension and return that placeholder from the MarkupExtension. The placeholder will get notified when the association with a FrameworkElement happens. In our case, this should happen when the Style is set on a FrameworkElement. At this time the placeholder re-evaluates itself by looking at its stored context and returns the expected value of the MarkupExtension.

Its no surprise that the MarkupExtensions that are provided as part of WPF, do exactly what I described above. Unfortunately this service is not available to custom MarkupExtensions.

I ran into this a few days back when I was building the PyBinding MarkupExtension. So, as it stands today, I cannot use {PyBinding} inside of Setters and for that matter any non-DependencyObject targets. Frankly, this is a Huge limitation of the MarkupExtension!

Comments