在 WPF 中,为什么 TemplateBinding 不能在 Binding 的地方工作? [英] In WPF, why doesn't TemplateBinding work where Binding does?

查看:18
本文介绍了在 WPF 中,为什么 TemplateBinding 不能在 Binding 的地方工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧……这让我摸不着头脑.我有两个 WPF 控件——一个是用户控件,另一个是自定义控件.我们称它们为 UserFoo 和 CustomFoo.在 CustomFoo 的控制模板中,我使用了 UserFoo 的一个实例,它是一个命名部分,因此我可以在应用模板后访问它.效果很好.

现在 UserFoo 和 CustomFoo 都定义了一个 Text 属性(独立地,即不是使用 AddOwner 的共享 DP.不要问......),它们都像这样声明......

public static readonly DependencyProperty TextProperty = DependencyProperty.Register(文本",类型(字符串),typeof(UserFoo),//另一个是CustomFoo新的 FrameworkPropertyMetadata(空值,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,空值,空值,真的,UpdateSourceTrigger.PropertyChanged));

请特别注意,模式设置为 TwoWay,UpdateSourceTrigger 设置为 PropertyChanged,同样适用于两者.

所以在CustomFoo的样式模板中,我想将CustomFoo的Text属性作为源绑定到内部UserFoo的Text属性上.通常,这很容易.您只需将 UserFoo 的文本属性设置为{TemplateBinding Text}",但由于某种原因,它只能以一种方式运行(即 UserFoo 是从 CustomFoo 正确设置的,但不是相反),尽管同样,两个 DP 都设置为双向!但是,当使用相对源绑定而不是模板绑定时,效果很好!嗯……什么??

//这个有效Text="{Binding Text, RelativeSource={RelativeSource AncestorType={local:CustomFoo}}, Mode=TwoWay}"//这也是...Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"//但不是这个!文本="{模板绑定文本}"

那是什么?我错过了什么?

解决方案

在 MSDN 上找到此论坛帖子:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb3

它是这样写的:

TemplateBinding 是针对模板场景的 Binding 的优化形式,类似于使用

构造的 Binding

{Binding 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 是使用模板绑定的优化"之一

Ok... this is leaving me scratching my head. I have two WPF controls--one's a user control and the other's a custom control. Let's call them UserFoo and CustomFoo. In the control template for CustomFoo, I use an instance of UserFoo which is a named part so I can get to it after the template is applied. That works fine.

Now both UserFoo and CustomFoo have a Text property defined on them (independently, i.e. not a shared DP using AddOwner. Don't ask...) that are both declared like this...

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

Notice specifically that the mode is set to TwoWay and the UpdateSourceTrigger is set to PropertyChanged, again for both.

So in the style template for CustomFoo, I want to bind CustomFoo's Text property as the source to the internal UserFoo's Text property. Normally, this is easy. You just set UserFoo's text property to "{TemplateBinding Text}" but for some reason it's only going one way (i.e. UserFoo is properly set from CustomFoo, but not the reverse), even though again, both DPs are set for two-way! However, when using a relative source binding instead of a template binding, it works great! Um... wha??

// 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}"

So what gives? What am I missing?

解决方案

Found this forum post on MSDN: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/

It says this:

A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with

{Binding RelativeSource={RelativeSource TemplatedParent}}

Note from OP: Contrary to what it says in the documentation, in actuality, it should be this...

{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}

I filed a complaint against the docs, and while they did add a sentence now stating they are always one-way, the code example still doesn't list the mode, but I guess it's better than nothing.)

The TemplateBinding transfers data from the templated parent to the property that is template bound. If you need to transfer data in the opposite direction or both ways, create a Binding with RelativeSource of TemplatedParent with the Mode property set to OneWayToSource or TwoWay.

More in: http://msdn.microsoft.com/en-us/library/ms742882.aspx

Looks like Mode=OneWay is one of the "Optimizations" of using a TemplateBinding

这篇关于在 WPF 中,为什么 TemplateBinding 不能在 Binding 的地方工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆