1
votes

I'm trying to do binding like this

<local:TempUserControl>
    <local:TempUserControl.Foo>
        <local:Foo Name2="{Binding Path=Name, RelativeSource={RelativeSource AncestorType={x:Type local:TempUserControl}}}"/>
    </local:TempUserControl.Foo>
</local:TempUserControl>

and getting error

Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='WpfApplication1.TempUserControl', AncestorLevel='1''. BindingExpression:Path=Name; DataItem=null; target element is 'Foo' (Name=''); target property is 'Name2' (type 'String')

Any idea please what is wrong?

2
I assume Foo is a custom dependency property in TempUserControl? How does TempUserControl use this property?Pieter Witvoet
Yes it is dependency property. TempUserControl doesn't use it at all as it is just sample class.user1121956
As far as I know, a relative binding uses the logical tree to search for the right ancestor. It looks like that Foo object isn't a logical child of that TempUserControl - it's just a property.Pieter Witvoet
That's what I was afraid of. Do you know perhaps how to make Foo a logical child? If you would put this in form of answer I could mark it as an answer.user1121956

2 Answers

2
votes

For this to work, that Foo object needs to be a logical child of TempUserControl. FrameworkElement (and FrameworkContentElement) provides two methods for this: AddLogicalChild and RemoveLogicalChild.

So, in TempUserControl, register a property-changed callback for the Foo dependency property. That callback can then pass the old and new value to an instance method, which calls RemoveLogicalChild with the old value and AddLogicalChild with the new value. Note that Foo must inherit from either FrameworkElement or FrameworkContentElement, otherwise it won't be included in the logical tree.

1
votes

I have found this not working in some cases too, I'm not 100% sure why (I have a guess). But you can solve it by giving your TempUserControl a x:Name and use ElementName instead of RelativeSource.