在 WPF 中,为啥 TemplateBinding 不能在 Binding 的地方工作?
Posted
技术标签:
【中文标题】在 WPF 中,为啥 TemplateBinding 不能在 Binding 的地方工作?【英文标题】:In WPF, why doesn't TemplateBinding work where Binding does?在 WPF 中,为什么 TemplateBinding 不能在 Binding 的地方工作? 【发布时间】:2011-08-20 06:26:45 【问题描述】:好吧...这让我摸不着头脑。我有两个 WPF 控件——一个是用户控件,另一个是自定义控件。我们称它们为 UserFoo 和 CustomFoo。在 CustomFoo 的控制模板中,我使用了一个 UserFoo 实例,它是一个命名部分,因此我可以在应用模板后访问它。效果很好。
现在 UserFoo 和 CustomFoo 都定义了一个 Text
属性(独立地,即不是使用 AddOwner 的共享 DP。别问...)都这样声明...
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(UserFoo), // The other is CustomFoo
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
null,
null,
true,
UpdateSourceTrigger.PropertyChanged
)
);
请注意,模式设置为 TwoWay,UpdateSourceTrigger 设置为 PropertyChanged,同样适用于两者。
所以在 CustomFoo 的样式模板中,我想将 CustomFoo 的 Text 属性作为源绑定到内部 UserFoo 的 Text 属性。通常,这很容易。您只需将 UserFoo 的 text 属性设置为“TemplateBinding Text”,但由于某种原因,它只是一种方式(即,UserFoo 是从 CustomFoo 正确设置的,但不是相反的),即使再一次,两个 DP 都设置为双向!但是,当使用相对源绑定而不是模板绑定时,效果很好!嗯……什么??
// This one works
Text="Binding Text, RelativeSource=RelativeSource AncestorType=local:CustomFoo, Mode=TwoWay"
// As does this too...
Text="Binding Text, RelativeSource=RelativeSource TemplatedParent, Mode=TwoWay"
// But not this one!
Text="TemplateBinding Text"
那是什么?我错过了什么?
【问题讨论】:
如果您使用可以指定模式的长版 TemplateBinding 会发生什么? IE:Text="Binding RelativeSource=RelativeSource TemplatedParent, Path=Text, Mode=TwoWay" - 这将告诉我们是模式问题还是 TemplateBinding 问题 如果你看上面,我说长版本工作得很好。 (为了清晰起见,我添加了一个使用 TemplatedParent 而不是显式设置控件类型的第二个实例。)再次,短版本确实设置了 UserFoo 的文本,因为它应该......它只是对 UserFoo 的更改不会反映回 CustomFoo . 如果您有具体问题,请发送至Meta Stack Overflow,并请阅读faq @Jeff... 什么?这不是元数据的问题。是为了这里。如果您是因举报而惩罚我的版主,询问我为什么因拒绝不良信息而失去声誉,那是因为在 SO Meta FAQ 的最顶部,它说“最重要的是,说实话。如果您看到错误信息,请投票向下。添加 cmets 来指出具体的错误。提供您自己的更好的答案。最重要的是 - 编辑和改进现有的问题和答案!”这正是我所做的,为什么我会受到惩罚? 【参考方案1】:在 MSDN 上找到此论坛帖子:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/
上面写着:
TemplateBinding 是针对模板场景的 Binding 优化形式,类似于用
构造的 BindingBinding RelativeSource=RelativeSource TemplatedParent
来自 OP 的注释:与文档中所说的相反,实际上,它应该是这个......
Binding RelativeSource=RelativeSource TemplatedParent, Mode=OneWay
我对文档提出了投诉,虽然他们现在确实添加了一句话,说明它们始终是单向的,但代码示例仍然没有列出模式,但我想总比没有好。)
TemplateBinding 将数据从模板化父级传输到模板绑定的属性。如果您需要反向或双向传输数据,请使用 TemplatedParent 的 RelativeSource 创建一个 Binding,并将 Mode 属性设置为 OneWayToSource 或 TwoWay。
更多内容:http://msdn.microsoft.com/en-us/library/ms742882.aspx
看起来 Mode=OneWay 是使用 TemplateBinding 的“优化”之一
【讨论】:
实际上,如果您查看 MSDN 链接,它并没有说明是 OneWay,只是"Binding RelativeSource=RelativeSource TemplatedParent"
我不是说这是错误的答案......我是说我不'看不到 MS 说它默认是 OneWay 的地方,但我确实相信它,因为这也是我所看到的。尽管如此,MS 应该(如果他们这样做的话更清楚)记录下来,而不是让我们相信这只是一个不错的捷径。
我同意 - 令人沮丧的是,您必须在他们论坛上的某个问题的回复中找到它。他们应该更新 MSDN 页面以反映这一点。
我将该页面标记为错误,解释了这个简单的遗漏如何花费我数天的研究时间,而如果拥有它本来可以保存所有内容。
我看到他们最终更新了文档,并评论说它是单向的,但他们仍然有代码语句本身错误,因为它没有显示模式。我再次标记了他们的文章,说明确实需要添加,因为评论还不够。他们所拥有的与他们声称的不相似。【参考方案2】:
TemplateBinding 不支持双向绑定,只有 Binding 支持。即使使用 BindsTwoWayBeDefault 选项,它也不支持双向绑定。
更多信息可以在here找到,但总结一下:
但是,一个 TemplateBinding 只能 单向传输数据:从 元素的模板化父级 与 TemplateBinding。如果你需要 以相反的方式传输数据 方向或双向,绑定与 TemplatedParent 的 RelativeSource 是 你唯一的选择。例如, 与 TextBox 或 Slider 的交互 在模板内只会更改 模板化父级的属性 if 你使用双向绑定。
【讨论】:
投票支持你,因为那里找到了其他信息,但这真的应该在 MSDN 文档中,而不仅仅是一些博客,不管是谁写的。人们期望文档是最终的、最重要的,而 MSDN 错过了那个很重要的“单向”位。 @MarqueIV - 是的,我同意。但是有很多你在文档中找不到的东西,或者描述得太简单以至于没有搜索引擎会找到它;-)以上是关于在 WPF 中,为啥 TemplateBinding 不能在 Binding 的地方工作?的主要内容,如果未能解决你的问题,请参考以下文章
为啥访问我的 Storyboard x:Name 在 Silverlight 中有效,但在 WPF 中无效?
为啥在 tabcontrol 内的 WPF 文本框中单击时,Windows 10 键盘会出现并立即消失?
为啥 WPF 样式在工具提示中显示验证错误适用于文本框但对组合框无效?
WPF:为啥我不应该在 ControlTemplate 中使用 TemplateBinding Margin - Margin 是不是仅适用于元素的容器?