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?
In One Way binding, source control updates the target control, which means if you change the value of the source control, it will update the value of the target control. So, in our example, if we change the value of the slider control, it will update the textbox value, as shown below.
Two way binding is used when we want to update some controls property when some other related controls property change and when source property change the actual control also updates its property.
A template binding is a special type of data binding that allows you to reference the parent control, read its properties and apply their values. In some cases, you can use the values directly. In other situations you may need to apply value converters or additional formatting.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With