[WPF] 是否能在ControlTemplate中的Setter使用TemplateBinding?

1,059 阅读1分钟

为建立中文知识库加块砖        ——中科大胡不归

问题描述

如何在ControlTemplate中的Setter使用TemplateBinding?比如像这样:

<ControlTemplate.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsChecked" Value="true" />
            <Condition Property="IsMouseOver" Value="true" />
        </MultiTrigger.Conditions>
        <Setter TargetName="MyLabel" Property="Background" Value="#FFF" />
        <Setter TargetName="MyOutline" Property="BorderBrush" Value="DarkBlue" />
        <Setter TargetName="MyIcon" Property="Padding" Value="{TemplateBinding Padding}" />
    </MultiTrigger>
    ...
</ControlTemplate.Triggers>

当然像上面这么用,你会得到'Padding' member is not valid because it does not have a qualifying type name.这样的错误警告。所以我们不能直接在Setter中使用TemplateBinding 来获得根样式的某个预设属性。

解决办法

但我们仍然可以通过使用如下的格式实现相同的效果:

Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding}"

代码示例: 自定义控件的style中

<Style.Triggers>
    <Trigger Property="Mode" Value="IconText">
        <Setter Property="Cursor" Value="Hand" />
        <Setter Property="Foreground" Value="#555" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type control:MyCheckBox}">
                    <Border x:Name="MyOutline" BorderThickness="1,1,1,1">
                        <Label x:Name="MyLabel" Style="{x:Null}" Padding="{TemplateBinding Padding}"
                               Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                            <Label.Content>
                                <Image x:Name="MyIcon" Source="{TemplateBinding Icon}" Margin="2"
                                           VerticalAlignment="Center" HorizontalAlignment="Center" />
                            </Label.Content>
                        </Label>
                    </Border>
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsChecked" Value="true" />
                                <Condition Property="IsMouseOver" Value="true" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="MyLabel" Property="Background" Value="#FFF" />
                            <Setter TargetName="MyOutline" Property="BorderBrush" Value="DarkBlue" />
                            <Setter TargetName="MyIcon" Property="Source" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconSelected}" />
                        </MultiTrigger>
                        ...
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Trigger>
</Style.Triggers>

可以看到我们在ControlTemplate中的Setter使用了根样式预设的自定义属性IconSelected替换了Image的Source属性。

参考文章

  1. Can my WPF Style Setter use a TemplateBinding?