We have an inheriting attached property which stores an object. Further down the visual tree, we want to bind to a property on that object from code.
Normally we construct the Path portion of a binding like so...
var someBinding = new Binding()
{
Path = new PropertyPath(AttachedPropertyOwner.SomeAttachedProperty),
RelativeSource = new RelativeSource(RelativeSourceMode.Self)
};
That works, but we now want a property of the object stored in SomeAttachedProperty
. I take it we're supposed to use the string representation?
Also, while researching this, I found this on MSDN: Property Path Syntax
The concerning part is down under the heading 'PropertyPathInCode'
If you construct a PropertyPath from a DependencyProperty, that PropertyPath is not usable as a Binding.Path, it is only usable for animation targeting. The Path value for the constructed PropertyPath from a DependencyProperty is the string value (0), which is a sentinel value used by the binding engine for an invalid path.
...which doesn't make sense to me since it appears to work fine. Am I missing something? Have we been doing all of our code bindings wrong?
Reading the MSDN documentation comment (which I missed was Silverlight, but I don't think matters in this case), it says you can't use a Dependency Property. However, it says you can use a DependencyProperty identifier, the identifier being what's returned from the Register methods.
In other words, I think what they're saying is what we're doing is valid...
var someBinding = new Binding()
{
Path = new PropertyPath(CarClass.WheelCountProperty)
};
...but this is not.
var someBinding = new Binding()
{
Path = new PropertyPath(MyCarInstance.WheelCount)
};
Seemingly confirming this, under the hood, Reflector shows it's essentially just doing this...
public PropertyPath(object value)
: this("(0)", new [] { value })
{
....
}
...so I think that scare was a red herring.
I think that also means I can do what I'm after like this...
Path = new PropertyPath("(0).(1)",
SomeClass.SomeAttachedProperty,
SomeOtherClass.SomeOtherAttachedProperty)
...which gets the value of the second attached property from the object stored in the first attached property.
I just confirmed my earlier suspicion was correct. Here's all you have to do to bind to an attached property on the value stored in another attached property...
Path = new PropertyPath("(0).(1)",
SomeClass.SomeAttachedProperty,
SomeOtherClass.SomeOtherAttachedProperty)
As stated in the update, for simple properties, this is also valid.
Path = new PropertyPath(SomeClass.SomeAttachedProperty)
...which essentially is the equivalent of this...
Path = new PropertyPath("(0)",
SomeClass.SomeAttachedProperty)