All you really need to make this work is to use RelativeSource
in your binding. Since you are setting the attached property on the Button
, in your style trigger, you can just bind to the attached property on self:
<Style TargetType="Button" x:Key="BtnTest">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="Content"
Value="{Binding Path=(lcl:TestClass.String), RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
One cool thing about using your approach, since Button
is a ContentControl
, you're attached property can be any object, not just strings.
And to clarify what went wrong in your previous approach -
- As others have said,
TemplateBinding
only works inControlTemplates
. It also only works when theDependencyProperty
is defined on the class you are creating the template for (so you can never do aTemplateBinding
toGrid.Row
for example) - When binding to an attached property, the whole thing needs to be in parentheses, otherwise WPF will try to bind to a property of a property. Otherwise your
RelativeSource
binding was close! - I think if you want to have a
Label
inside theButton
as the content, it may work (I didn't test that), but it doesn't seem like the best idea, as yourButton
can host any object you want.
EDIT for more complex example
So, if you need to display more than one dynamic property, I would recommend using a DataTemplate
:
<Style TargetType="Button" x:Key="BtnTest">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Label Content="{Binding Path=(lcl:TestClass.String), RelativeSource={RelativeSource AncestorType={x:Type Button}}}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Also, I want to point out that a DataTemplateSelector
might be more applicable if you have multiple different criteria for changing the look of the content.