I'm trying to create a custom markup extension using IMarkupExtension<T>
that has some DependencyProperties for binding. However, I am struggling to resolve the problem of the markup extension being resolved at XAML parse time, and the bindings only later. I don't seem to ever get something through the bindings: they're always null and never call their change callback.
The docs mention something about returning the instance of the markup extension (under "Returning the Current Markup Extensions Instance"), but that seems to make stuff explode because it's the wrong type for the target. This SL5 MultiBinding seems to return a proxy binding to an internal source object, but I can't manage to get that working: my bindings still don't ever set.
I can't seem to find any solid information how how to actually implement markup extensions with DependencyProperties (even though it seemed like something a lot of people were excited about with SL5...). Can anyone offer any guidance or tutorials?
Specifically, what I'm trying to do is create a markup extension that can dynamically construct a path to do a binding to a list, like so:
{my:ListLookup ListPath='List' Index={Binding Index}}
I'm wanting it to basically output a Binding that would look like {Binding List[Index]}
, where Index is dynamic. The purpose of doing this over, say, a MultiBinding on the list and index, is so that we are binding directly to the object and get change notifications. (If there's a better way of doing this...)
I've fiddled with this a lot more and I've found the solution. It's based on the implementation of the SL5 MultiBinding that I linked to in the question.
The trick is that a Binding on a MarkupExtension will never be evaluated because it doesn't have a DataContext or something, but if you take the BindingExpression from it and throw it into a proxy Attached Property (attached to the target object) then you can get the Binding to resolve.
Below is a simple MarkupExtension that demonstrates this. All it's doing is taking a single Binding and outputting its value (obeying changes appropriately), but it shows how it holds together. This can be extended to solve the dictionary issue I was talking about, along with this problem in general.
Usage:
As mentioned, this example will produce the same result as just saying
Text="{Binding Text}"
, but shows the solution.