在WPF中获取顶级父模板自定义DP?

时间:2018-02-21 07:45:26

标签: wpf xaml

我有一个具有自定义DP的自定义控件,此控件的样式定义了多个ControlTemplate s层:

                <ControlTemplate>
                   <Button>
                     <Button.Template>
                      <ControlTemplate>
                        <!--I want to use the custom DP here-->
                        <TextBlock Text="{Binding ElementName=myCtrl, Path=SubTitle}"/>
                      </ControlTemplate>
                     </Button.Template>
                   </Button>
                </ControlTemplate>

在按钮的控件模板中我想使用自定义DP SubTitle,在当前实现中我使用控件名称,但这并不能帮助抽象控件样式,和可重用性: 不幸的是我无法使用:

Text="{TemplateBinding SubTitle}"

我发现了answer

它很好,但只有上升一级,即它可以在按钮内使用 - 基本控制模板的直接子项,我这样做是为了解决:

                    <ControlTemplate>
                       <Button Tag="{Binding SubTitle, RelativeSource={RelativeSource TemplatedParent}}">
                         <Button.Template>
                          <ControlTemplate>
                            <!--I want to use the custom DP here-->
                            <TextBlock Text="{TemplateBinding Tag}"/>
                          </ControlTemplate>
                         </Button.Template>
                       </Button>
                    </ControlTemplate>

但效率不高,无法处理多个DP。 那么是否有更有效的方法在其孙子孙女中使用基本控制的自定义DP。

我将借此机会请求资源详细解释绑定表达式的整个主题:TemplateBindingRelativeSource等,以及像这样的属性的奇怪用法(这是Binding主题?):

Storyboard.TargetProperty="(Panel.Background).
                    (GradientBrush.GradientStops)[1].(GradientStop.Color)"

2 个答案:

答案 0 :(得分:1)

而不是RelativeSource TemplatedParent使用具有AncestorType的RelativeSource来查找可视树中更高的特定类型({x:Type ...})的元素。在嵌套的ControlTemplates的情况下,它应该是外部ControlTemplate的目标类型

<TextBlock Text="{Binding Path=SubTitle, 
                          RelativeSource={RelativeSource AncestorType={x:Type local:MyControl}, AncestorLevel=1}}"/>

答案 1 :(得分:1)

这就是你要找的东西:

<ControlTemplate TargetType=MyCustomControlType>
  <Button>
    <Button.Template>
      <ControlTemplate TargetType=Button>

        <!--I want to use the custom DP here-->
        <TextBlock Text="{Binding Path=SubTitle, RelativeSource={RelativeSource FindAncestor, AncestorType=MyCustomControlType}}"/>
      </ControlTemplate>
    </Button.Template>
  </Button>
</ControlTemplate>
  

{Binding Path = SubTitle,RelativeSource = {RelativeSource FindAncestor,AncestorType = MyCustomControlType }}

将使绑定表达式通过遍历可视树从子节点到父节点(或从节点到根节点)来查找绑定目标,直到第一个元素与“AncestorType”参数定义的类型匹配。在此类型上,XAML解析器将尝试解析绑定路径。

第二个问题的答案:

Storyboard.TargetProperty="(Panel.Background).
                (GradientBrush.GradientStops)[1].

此标记告诉您的动画要设置动画的属性。由于属性是嵌套的,因此您始终必须通过解析其属性路径来引用目标属性。 然后,在沿着类型的属性路径向下走时,使用括号进行类型转换。

假设故事板的目标是扩展 Panel ,例如 Grid ,您的代码段会执行以下操作:

  1. (Panel.Background) - 将'Grid'向下转换为'Panel'并引用Background属性
  2. (GradientBrush.GradientStops) - 将背景(声明为“刷子”)投射到“GradientBrush”并引用“GradientStops”属性,该属性是“GradientStopCollection”类型的集合。
  3. [1] - 此索引器引用第2步中引用的'GradienStopCollection'中的第二个元素。此元素的类型为'object'。
  4. (GradientStop.Color) - 将从第3步返回的元素从object转换为'GradientStop'以引用'Color'属性