[英]TemplatedParent is null when used inside a ControlTemplate's DataTrigger
Consider this (edited-down) Style
, designed for a Button
whose Content
is a String
:考虑这个(编辑过的)
Style
,它是为一个Button
设计的,它的Content
是一个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 .此示例中的意图是将按钮文本变为红色,如果它等于单词 "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.但它不起作用,因为触发器的
TemplatedParent
绑定解析为 null 而不是应用Style
的Button
。 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.但是,名为“demo”的
TextBlock
将按预期将其Text
设置为“System.Windows.Controls.Button: [ButtonText]”,这意味着TemplatedParent
在该级别正常工作。 Why doesn't it work inside the DataTrigger
?为什么它在
DataTrigger
?
TemplatedParent
in your ControlTemplate.Triggers
is not what you expect.您
ControlTemplate.Triggers
TemplatedParent
不是您所期望的。 Inside trigger it actually references Button.TemplatedParent
.在触发器内部,它实际上引用了
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:
现在考虑这个 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 .在这里,我重新模板
ContentControl
和内部模板我使用按钮与您的模板。 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.如果您运行此代码,您将看到红色的“虚拟”文本,因为
Button.TemplatedParent
现在是ContentControl
,并且它的Content
等于“Test”,这证实了我上面所说的。
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.现在回到您的问题:只需将
RelativeSource TemplatedParent
更改为RelativeSource Self
(无需将DataTrigger
更改为Trigger
)-这将引用您的按钮。
I think it might be a similar issue in .NET Core WPF.我认为这可能是 .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.我的
DataTrigger
没有用{Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}}
触发,而是当我将 RelativeSource 更改为Self
,绑定开始工作。 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
.也许值得一提的是,我的模板基于
MyView
(见下文),并且我绑定到了MyView
上的DependencyProperty
。
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>
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.
因此,在触发器中定义的字符串永远不会是真的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.