Friday, November 13, 2009

Friday Quickie: The *other* TemplateBinding syntax

Setting up the template for a new custom control in Silverlight is fraught at the best of times – the Silverlight runtime invariably swallows any error in the template and gives just a cryptic exception.

But stranger still is a limitation on how the {TemplateBinding ...} syntax can be used and the exception that is thrown when in error.

The {TemplateBinding ...} syntax provides a quick and simple way to bind properties within a control’s template to the properties of the control itself. According to the MSDN documentation, it’s a shortcut to the more full-featured {Binding ...} syntax. But what’s not clear from the documentation is that {TemplateBinding ...} can only bind a control property to a DependencyProperty on the control class.

If you try and use {TemplateBinding ...} against a normal property on the control, you get the strange exception shown right – confusing because the target control (WizardActionButton in the example) absolutely does have a State property.

The solution is to use the {Binding ...} syntax where the source property isn’t a DependencyProperty, and to use the {RelativeSource ...} syntax to specify that you’re actually binding to the control within its template.

Wrong:

<i4tControls:WizardActionButton x:Name="RetreatButtonPart"

Style="{StaticResource ActionButtonStyle}"

State="{TemplateBinding CanRetreat}"

Content="{TemplateBinding RetreatButtonContent}"

ContentTemplate="{TemplateBinding RetreatButtonContentTemplate}"

/>

Correct:

<i4tControls:WizardActionButton x:Name="RetreatButtonPart"

Style="{StaticResource ActionButtonStyle}"

State="{Binding Path=CanRetreat,RelativeSource={RelativeSource TemplatedParent}}"

Content="{TemplateBinding RetreatButtonContent}"

ContentTemplate="{TemplateBinding RetreatButtonContentTemplate}"

/>