Introduction
This is a little trick I use to bind XAML stuff with code behind properties. This tip/trick will allow you to easily achieve such a binding.
Background
There are a number of ways using which you can bind code-behind properties. For e.g., assigning a name to the code-behind object and then using ElementName
in the data binding expression, using relative source with condition on ancestor type, etc. This text does not cover these ways.
Without going into the goodness or badness of the above methods, I would like to point out that I sometimes find these methods unpredictable/cumbersome. For e.g., I was recently hit with the issue described here: MSDN Link.
Using element name also does not work sometimes due to the same reason as described in the above MSDN link.
Long story short, using the above methods is not always applicable. Also given that bindings don't 'error out' (read exceptions), it can become notoriously hard to detect the root cause of the problem.
Solution
If we can obtain a reference to the current code-behind object, our job becomes easy. All we have to do is either set DataContext
for the binding to the obtained reference or directly use the obtained reference as source of the binding. Also, the mechanism to obtain this reference should be usable from XAML.
Initially, I tried with attached properties, as attached properties get a reference to the object to which it is attached. All I had to do was, retain a reference to the object it is attached to and then return it through a read-only property (this solution is not presented here).
However, later I discovered that all this was quite unnecessary. I could have easily used a nice little Markup Extension. Nothing fancy, but just a few lines of code.
public class RootExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
IRootObjectProvider provider = serviceProvider.GetService
(typeof(IRootObjectProvider)) as IRootObjectProvider;
if (provider != null)
{
return provider.RootObject;
}
return null;
}
}
How Does It Work
Markup Extensions are evaluated in the context of the XAML document they are used in. The above extension simply finds and returns the root object of current XAML document or in other words, the code-behind object.
How To Use It
Example:
<DataGridTemplateColumn Width="{Binding Source={local:Root},
Path=ColumnOneWidth}" CellTemplate="{Binding Source={local:Root}, Path=ColumnOneTemplate}"/>
where ColumnOneWidth
and ColumnOneTemplate
are properties defined in the code-behind of the user control above XAML fragment forms part of.