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.
好吧……这让我百思不得其解。我有两个WPF控件——一个是用户控件,另一个是自定义控件。我们叫它们UserFoo和CustomFoo。在CustomFoo的控件模板中,我使用一个UserFoo实例,它是一个命名的部分,所以我可以在模板被应用后访问它。工作的很好。
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...
现在,UserFoo和CustomFoo都有一个文本属性定义在它们上(独立地,即不是使用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
)
);
Notice specifically that the mode is set to TwoWay and the UpdateSourceTrigger is set to PropertyChanged, again for both.
特别注意,模式设置为TwoWay, UpdateSourceTrigger设置为PropertyChanged,这对两者都是相同的。
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??
在CustomFoo的样式模板中,我想将CustomFoo的文本属性作为源绑定到内部UserFoo的文本属性。通常,这是很容易的。您只是将UserFoo的文本属性设置为“{TemplateBinding text}”,但是出于某种原因,它只向一个方向(例如,UserFoo从CustomFoo正确地设置为,但不是相反),尽管如此,两个DPs都设置为双向!但是,当使用相对的源绑定而不是模板绑定时,它非常有用!嗯…世界卫生大会? ?
// 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?
给什么?我缺少什么?
2 个解决方案
#1
44
Found this forum post on MSDN: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/
在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...
OP中的注释:与文档中所描述的相反,实际上,它应该是……
{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.
TemplateBinding将数据从模板父类传输到模板绑定的属性。如果需要以相反的方向或两种方式传输数据,可以使用TemplatedParent的RelativeSource创建绑定,并将Mode属性设置为OneWayToSource或TwoWay。
More in: http://msdn.microsoft.com/en-us/library/ms742882.aspx
更多:http://msdn.microsoft.com/en-us/library/ms742882.aspx
Looks like Mode=OneWay is one of the "Optimizations" of using a TemplateBinding
看起来Mode=OneWay是使用模板绑定的“优化”之一
#2
9
TemplateBinding does not support two-way binding, only Binding does that. Even with your BindsTwoWayBeDefault option, it won't support two-way binding.
TemplateBinding不支持双向绑定,只支持绑定。即使使用BindsTwoWayBeDefault选项,也不支持双向绑定。
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.
但是,TemplateBinding只能在一个方向上传输数据:从模板化的父元素到带有TemplateBinding的元素。如果您需要在相反的方向或双向传输数据,那么您惟一的选择就是与TemplatedParent的相对源绑定。例如,如果使用双向绑定,与模板中的文本框或滑块交互只会更改模板父类上的属性。
#1
44
Found this forum post on MSDN: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/
在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...
OP中的注释:与文档中所描述的相反,实际上,它应该是……
{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.
TemplateBinding将数据从模板父类传输到模板绑定的属性。如果需要以相反的方向或两种方式传输数据,可以使用TemplatedParent的RelativeSource创建绑定,并将Mode属性设置为OneWayToSource或TwoWay。
More in: http://msdn.microsoft.com/en-us/library/ms742882.aspx
更多:http://msdn.microsoft.com/en-us/library/ms742882.aspx
Looks like Mode=OneWay is one of the "Optimizations" of using a TemplateBinding
看起来Mode=OneWay是使用模板绑定的“优化”之一
#2
9
TemplateBinding does not support two-way binding, only Binding does that. Even with your BindsTwoWayBeDefault option, it won't support two-way binding.
TemplateBinding不支持双向绑定,只支持绑定。即使使用BindsTwoWayBeDefault选项,也不支持双向绑定。
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.
但是,TemplateBinding只能在一个方向上传输数据:从模板化的父元素到带有TemplateBinding的元素。如果您需要在相反的方向或双向传输数据,那么您惟一的选择就是与TemplatedParent的相对源绑定。例如,如果使用双向绑定,与模板中的文本框或滑块交互只会更改模板父类上的属性。