AncestorType must be specified for RelativeSource in FindAncestor mode

Everything started when I tried to draw horizontal line inside a border element and I wanted line length to be same as the border width. Binding coordinates by using RelativeSource was the first thing I wanted to try (it was way before I found out that Stretch property is the simplest way to go).  After checking MSDN on RelativeSource, first version looked like this:

<Border Height="30" BorderBrush="Black" BorderThickness="1">
    <Line X1="0" Y1="5"
          X2="{Binding RelativeSource={RelativeSource 
                                       AncestorType={x:Type Border}, 
          Stroke="#000fff" StrokeThickness="1" />

Mysterious error

When I finished typing, VS2008 XAML editor did not like it. Binding expression had red squiggly underline and when I put mouse over it displayed hint: “Mode must be specified for RelativeSource”.
OK, I checked syntax, looked fine.  I found example in the help file where “Mode”  keyword was omitted, so I tried that:

     RelativeSource={RelativeSource FindAncestor, 
                     AncestorType={x:Type Border}, 

Something changed. Error message now says: “AncestorType must be specified for RelativeSource in FindAncestor mode”.
Aha moment: there must be something wrong with the syntax, maybe I missed comma or braces, maybe order of arguments. But everything looked fine. I tried following:

  • moved Path before RelativeSource
  • removed comma between Path and RelativeSource
  • removed Path keyword

Nothing worked. Time for Google. Search returned number of pages and I started reading. Some claimed that binding mode must be specified(OneWay, TwoWay, …). Most of them have link to WPF wiki page: Q5.3 – Source vs. RelativeSource vs. ElementName

I copied examples from that article, but got the same error. That was fishy. I copied code from two places and they didn’t work.

Simple fix for error that is not an error, but bug

Then I found comment on StackOverflow question Setting WPF nested control properties from the parent control where somebody wrote that this is VS 2008 bug and that simple rebuild solution will clear falsely reported error.
Clicked on “Rebuild Solution”, everything went fine and squiggly underline disappeared. Arrrgh. Half an hour lost just because I didn’t try to build project. And I usually do that very often.

Solution for wrong problem

After all this fun, it turned out that the above code was correct. Unfortunately, it did not work as expected. Border element that contains line does not have width specified, so X2 is equal to null. If I specify width on Border element, then Border does not expand to parent area. I tried with Width=”Auto”, both on Border and Line, but that did not work either – line was zero length. Last thing I tried was to bind X2 to ActualWidth of Border element. That was fun. XAML designer was confused – it drew border, then line inside. But border must contain line inside, so it redraw border two pixels wider. That changed ActualWidth property, so it forced line to redraw. This went on for few seconds and then it stopped. There was horizontal scroll bar, but it had no scroller, so I could not see how wide border and line are.

Finally, after few fun hours, I stumbled on Stretch property that all shapes have. It defines how  shape will fill its container. With this property, you can force shape to expand and fill container in all directions. Here is final XAML code for border that contains horizontal line that is stretched across border:

<Border Grid.Row="0"  Height="30"  BorderBrush="Black" BorderThickness="1">
    <Line X1="0" Y1="5" 
          X2="5" Y2="5"  
          Stroke="#000fff" StrokeThickness="1" />

I tried to remove X2, but then it does not stretch. Also, X1 and X2 must different, does not matter which one is greater. If they are equal, line is not drawn.

5 Replies to “AncestorType must be specified for RelativeSource in FindAncestor mode”

Leave a Reply

Your email address will not be published. Required fields are marked *