Reputation: 9403
Consider this (edited-down) Style
, designed for a Button
whose Content
is a String
:
<Style x:Key="Test" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Content}" />
<TextBlock x:Name="demo" Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="test" Property="Foreground" Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The intention in this example is to turn the button text red if it equals the word "Test"1. But it doesn't work, because the trigger's TemplatedParent
binding resolves to null instead of to the Button
the Style
is applied to. However, the TextBlock
named "demo" will have its Text
set to "System.Windows.Controls.Button: [ButtonText]" as expected, which means TemplatedParent
works correctly at that level. Why doesn't it work inside the DataTrigger
?
Upvotes: 7
Views: 2220
Reputation: 1440
I think it might be a similar issue in .NET Core WPF.
My DataTrigger
was not firing with {Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}}
, but instead when I changed the RelativeSource to Self
the binding started to work. I'm not sure whether it's a hack or a solution, but it worked.
Maybe it's worth mentioning that my template was based on MyView
(see below) and I was binding to a DependencyProperty
on MyView
.
So my final code looked like this:
<ControlTemplate x:Key="Template" TargetType="{x:Type ns:MyView}">
<!-- Some template -->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding MyProp, RelativeSource={RelativeSource Self}, Converter={StaticResource Convert}}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Upvotes: 1
Reputation: 101613
TemplatedParent
in your ControlTemplate.Triggers
is not what you expect. Inside trigger it actually references Button.TemplatedParent
. As such, it will only be non-null if your create that button inside template. You don't create button inside template, so it is null in your case. Now consider this xaml:
<Window.Resources>
<Style x:Key="Test"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text"
Text="dummy" />
<TextBlock x:Name="demo"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="text"
Property="Foreground"
Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Test2" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Button Style="{StaticResource Test}"></Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<!--<Button Content="Test" Style="{StaticResource Test}"/>-->
<ContentControl Style="{StaticResource Test2}" Content="Test" />
</Grid>
Here I retemplate ContentControl
and inside template I use button with your template. If you run this code, you will see "dummy" text in red, because Button.TemplatedParent
is now ContentControl
, and it has it's Content
equals "Test", which confirms what I said above.
Now back to your problem: just change RelativeSource TemplatedParent
to RelativeSource Self
(no need to change DataTrigger
to Trigger
) - this one would reference your Button.
Upvotes: 13
Reputation: 26
I'm not quite sure, but I think the trigger equals by referenc, because Content returns an Object. So it will never be true with your string defined within the trigger.
Upvotes: -1