WPF模板绑定与相对源TemplatedParent

181
这两个绑定之间的区别是什么?
<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{TemplateBinding Property=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>
"并且"
<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>

?


18
如果需要双向绑定,你必须使用第二个选项。 - Joachim Kerschbaumer
6个回答

216

TemplateBinding和Binding不完全相同。MSDN文档通常是由需要向单音节的软件开发工程师询问软件功能的人编写,因此细微差别并不正确。

TemplateBindings在编译时针对控件模板中指定的类型进行评估。这允许更快地实例化已编译的模板。只需在templatebinding中错拼名称,编译器就会标记它。

绑定标记在运行时解析。虽然执行速度较慢,但绑定将解析模板声明的类型中不可见的属性名称。相对而言,它的速度有点慢,因为绑定操作占用应用程序的CPU很少。如果您以高速发送控件模板,则可能会注意到它。

作为一种实践方法,尽可能使用TemplateBinding,但不要害怕Binding。


18
所以要记住的主要是:编译时与运行时。如果在运行时尝试更改 TemplateBinding,它将无法工作。对吗? - theSpyCry
3
请注意,使用 Binding 而不是 TemplateBinding 可能会对您在设计时看到的内容产生影响。在某些配置中,使用 {Binding RelativeSource...} 绑定的属性在设计器中不会出现(但在运行时仍会显示),但如果您切换到使用 {TemplateBinding...},这些属性将在设计时计算并显示。 - lfalin
1
我要补充一点,以便于未来的访问者能够理解:由于TemplateBinding在编译时被评估,因此您不能使用TemplateBinding绑定到用户定义的附加属性。对于用户定义的附加属性,您必须使用"{Binding RelativeSource={RelativeSource TemplatedParent} ... }"。 - MNB

38

TemplateBinding - 比使用常规绑定更加限制

  • 比绑定更高效,但功能较少
  • 仅可在控件模板的可视树中使用
  • 不能与Freezable上的属性一起使用
  • 不能在控件模板的触发器内部使用
  • 在设置属性时提供了快捷方式(不需要写那么多),例如{TemplateBinding targetProperty}

常规绑定 - 不具备TemplateBinding的以上限制

  • 尊重父级属性
  • 重置目标值以清除任何显式设置的值
  • 示例:<Ellipse Fill="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}"/>

24

还有一件事——模板绑定不允许值转换。它们不允许您传递一个 Converter,也不会自动将 int 转换为 string(这在绑定中是正常的)。


1
谢谢Miroslav,这就是我遇到的问题,转而使用TemplatedParent解决了问题。 - MikeKulls

17

TemplateBinding是使用TemplatedParent的Binding的简写,但它并没有暴露Binding类的所有功能,例如你无法通过TemplateBinding来控制Binding.Mode。


1

我认为TemplateBinding不支持Freezable类型(包括画笔对象)。为了解决这个问题,可以利用TemplatedParent。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接