在 WPF 中,为什么 TemplateBinding 不能像 Binding 一样工作?

发布于 2024-11-05 16:02:37 字数 1286 浏览 6 评论 0原文

好吧……这让我摸不着头脑。我有两个 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 的文本属性设置为“{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}"

那么什么给出呢?我缺少什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

李白 2024-11-12 16:02:37

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

它说:

A TemplateBinding是针对模板场景的 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是使用TemplateBinding的“优化”之一

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

打小就很酷 2024-11-12 16:02:37

TemplateBinding 不支持双向绑定,只有 Binding 可以支持。即使使用 BindsTwoWayBeDefault 选项,它也不支持双向绑定。

更多信息可以在此处找到,但总结一下:

但是,TemplateBinding 只能
单向传输数据:从
元素的模板化父元素
与模板绑定。如果您需要
反向传输数据
方向或双向,绑定
TemplatedParent 的相对源是
你唯一的选择。例如,
与文本框或滑块交互
在模板内只会改变一个
模板化父级的属性如果
您使用双向绑定。

TemplateBinding does not support two-way binding, only Binding does that. Even with your BindsTwoWayBeDefault option, it won't support two-way binding.

More info can be found here, but to summarize:

However, a TemplateBinding can only
transfer data in one direction: from
the templated parent to the element
with the TemplateBinding. If you need
to transfer data in the opposite
direction or both ways, a Binding with
RelativeSource of TemplatedParent is
your only option. For example,
interaction with a TextBox or Slider
within a template will only change a
property on the templated parent if
you use a two-way Binding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文