考虑这个(已编辑过的)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>
:
TemplatedParent
此示例中的意图是将按钮文本变为红色,如果它等于单词&#34; Test&#34; 1 。但它不起作用,因为触发器的Button
绑定解析为null而不是Style
TextBlock
应用于Text
。但是,TemplatedParent
名为&#34; demo&#34;将DataTrigger
设置为&#34; System.Windows.Controls.Button:[ButtonText]&#34;正如预期的那样,这意味着{{1}}在该级别上正常工作。为什么它在{{1}}内无效?
答案 0 :(得分:6)
TemplatedParent
中的{p> ControlTemplate.Triggers
不符合您的预期。内部触发器实际上引用了Button.TemplatedParent
。因此,如果您在模板中创建按钮,它将仅为非null。您没有在模板中创建按钮,因此在您的情况下它是null。现在考虑这个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>
在这里,我重新模仿ContentControl
,在模板内部,我使用按钮和模板。如果您运行此代码,您将看到&#34; dummy&#34;文字为红色,因为Button.TemplatedParent
现在为ContentControl
,并且它有Content
等于&#34;测试&#34;,这证实了我上面所说的内容。
现在回到你的问题:只需将RelativeSource TemplatedParent
更改为RelativeSource Self
(无需将DataTrigger
更改为Trigger
) - 这个会引用你的按钮。
答案 1 :(得分:0)
我不太确定,但我认为触发器等于referenc,因为Content返回一个Object。因此,在触发器中定义的字符串永远不会成为现实。
答案 2 :(得分:0)
我认为这可能是.NET Core WPF中的类似问题。
我的DataTrigger
不是用{Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}}
触发的,而是当我将RelativeSource更改为Self
时,绑定开始起作用。我不确定这是黑客还是解决方案,但它确实有效。
也许值得一提的是,我的模板基于MyView
(见下文),并且我绑定到DependencyProperty
上的MyView
。
所以我的最终代码如下:
<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>