代码之家  ›  专栏  ›  技术社区  ›  dlf

在ControlTemplate的DataTrigger中使用时,TemplatedParent为null

  •  6
  • dlf  · 技术社区  · 10 年前

    考虑一下这个(编辑下来) 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>
    

    本例中的意图是,如果按钮文本等于单词“Test”,则将其变为红色 1. 但它不起作用,因为触发器 TemplatedParent 绑定解析为null,而不是 按钮 这个 风格 应用于。但是 TextBlock 名为“demo”的 Text 按预期设置为“System.Windows.Controls.Button:[ButtonText]”,这意味着 模板化父级 在该级别正确工作。为什么它在 DataTrigger ?


    1. 我知道还有其他方法可以实现这一点,但我正在试图理解为什么绑定没有按我期望的方式工作。
    3 回复  |  直到 10 年前
        1
  •  10
  •   Evk    10 年前

    TemplatedParent 在您的 ControlTemplate.Triggers 不是你所期望的。在触发器内部,它实际上引用了 Button.TemplatedParent 因此,如果您创建 按钮 模板内部。您并没有在模板中创建按钮,所以在您的情况下它是空的。现在考虑这个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 和我使用的模板内部 按钮和模板 。如果运行此代码,您将看到红色的“dummy”文本,因为 按钮.模板父级 现在是 内容控制 ,它有它的 Content 等于“测试”,这证实了我上面所说的。

    现在回到你的问题:只要改变 RelativeSource TemplatedParent RelativeSource Self (无需更改 DataTrigger Trigger )-这个会引用你的按钮。

        2
  •  0
  •   mihails.kuzmins    6 年前

    我认为这可能是.NETCoreWPF中的一个类似问题。 我的 DataTrigger 没有使用 {Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}} 但当我将RelativeSource更改为 Self 绑定开始工作。我不确定这是黑客还是解决方案,但它确实有效。

    也许值得一提的是,我的模板基于 MyView (见下文),我绑定到 DependencyProperty 在…上 我的视图 .

    所以我的最终代码如下:

    <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>
    
        3
  •  -1
  •   Bass Guru    10 年前

    我不太确定,但我认为触发器等于referenc,因为Content返回一个Object。因此,对于在触发器中定义的字符串,它永远不会是真的。

    推荐文章