【问题标题】:Getting the top parent template custom DP in WPF?在 WPF 中获取顶级父模板自定义 DP?
【发布时间】:2018-02-22 13:32:12
【问题描述】:

我有一个自定义的控件,它有一个自定义的 DP,这个控件的样式定义了ControlTemplates 的多层:

                <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>

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

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。

我将借此机会寻求资源,详细解释 Binding 表达式的整个主题:TemplateBindingRelativeSource 等以及此类属性的奇怪使用(这是 Binding 主题的一部分吗? ):

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

【问题讨论】:

标签: wpf xaml


【解决方案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,你的 sn-p 会执行以下操作:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • @MohamedAhmed,在您的问题中&lt;!--I want to use the custom DP here--&gt;&lt;TextBlock Text="{TemplateBinding Tag}"/&gt;。你没有说你有哪个自定义 DP。写Path=CustomDPname
    • 抱歉给您带来了困惑,您能编辑一下您的问题,以便我取消投票吗?(可以将Tag 更改为SubTitle
    • 值得一提的是使用自定义控件名称,而不是基本控件,所以local:MyControl而不是CheckBox
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 2015-10-04
    • 1970-01-01
    相关资源
    最近更新 更多