binding - Wpf dependency property fails to initially bind, then works correctly after window displayed - Stack Overflow

admin2025-04-19  0

I have a user control that shows a logo, which has a triggered animation. It has a couple of dependency properties for border and background brushes, and it all works well.

In the control's xaml, there's a line:

<GeometryDrawing Brush="{Binding Path=LogoBackgroundBrush, RelativeSource={RelativeSource AncestorType=local:Logo}, FallbackValue=Transparent}">

(and a similar line for the border)

I consume it in a form:

<Controls:Logo Height="70" LogoBackgroundBrush="Transparent" LogoBorderBrush="Transparent" />

This works to allow me to override the background brush, but when I run the app I get an initial failure to bind in the XAML Binding Failures window:

Cannot find source: RelativeSource FindAncestor, AncestorType='MyNameSpace.Wpf.Ui.Controls.Logo', AncestorLevel='1'.

(and a similar error for the border brush)

If I clear the error and keep working, it doesn't reappear; the control draws with the correct values, and changing the two dependency properties works correctly. For context, the window where it is consumed is created using (other services removed for brevity):

var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<MainWindow>();
ServiceProvider = serviceCollection.BuildServiceProvider();
var startupForm = ServiceProvider.GetRequiredService<MainWindow>();
startupForm.Show();

The XAML structure looks like

<ResourceDictionary>
  <Style>
    <Setter.Value>
      <ControlTemplate>
        <Image>
          <Image.Source>
             <DrawingImage>
               <DrawingGroup>
                 <DrawingGroup.Children>
                   <GeometryDrawing Brush="{Binding ...}">

How do I diagnose the reason for the initial error? It doesn't seem to cause any other issues, other than bothering my OCD.

I have a user control that shows a logo, which has a triggered animation. It has a couple of dependency properties for border and background brushes, and it all works well.

In the control's xaml, there's a line:

<GeometryDrawing Brush="{Binding Path=LogoBackgroundBrush, RelativeSource={RelativeSource AncestorType=local:Logo}, FallbackValue=Transparent}">

(and a similar line for the border)

I consume it in a form:

<Controls:Logo Height="70" LogoBackgroundBrush="Transparent" LogoBorderBrush="Transparent" />

This works to allow me to override the background brush, but when I run the app I get an initial failure to bind in the XAML Binding Failures window:

Cannot find source: RelativeSource FindAncestor, AncestorType='MyNameSpace.Wpf.Ui.Controls.Logo', AncestorLevel='1'.

(and a similar error for the border brush)

If I clear the error and keep working, it doesn't reappear; the control draws with the correct values, and changing the two dependency properties works correctly. For context, the window where it is consumed is created using (other services removed for brevity):

var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<MainWindow>();
ServiceProvider = serviceCollection.BuildServiceProvider();
var startupForm = ServiceProvider.GetRequiredService<MainWindow>();
startupForm.Show();

The XAML structure looks like

<ResourceDictionary>
  <Style>
    <Setter.Value>
      <ControlTemplate>
        <Image>
          <Image.Source>
             <DrawingImage>
               <DrawingGroup>
                 <DrawingGroup.Children>
                   <GeometryDrawing Brush="{Binding ...}">

How do I diagnose the reason for the initial error? It doesn't seem to cause any other issues, other than bothering my OCD.

Share Improve this question edited Mar 6 at 19:30 Geoff asked Mar 6 at 0:33 GeoffGeoff 8,8881 gold badge45 silver badges52 bronze badges 3
  • The visual tree might not yet be established when the Binding is evaluated. Try ElementName instead of RelativeSource. – Clemens Commented Mar 6 at 6:58
  • Thanks @Clemens - any suggestion on which element I pin the name to? I added the xaml nesting structure to the question. Or maybe I'm misunderstanding your suggestion. (also hoping that the xaml structure helps with whoever voted to close because of lack of debugging info) – Geoff Commented Mar 6 at 19:30
  • The Logo control. – Clemens Commented Mar 6 at 20:18
Add a comment  | 

1 Answer 1

Reset to default 0

I found the solution to this, from this answer. Adding a name to the GeometryDrawing was enough:

<GeometryDrawing Brush="{...\>

becomes

<GeometryDrawing x:Name="logo" Brush="{...\>

I'm guessing the reason stems from what is pointed to in Clemens' comment to the original question; the visual tree isn't fully established.

From what I can tell, a partial explanation is that the name property being added causes the element to be added to the logical tree (so the element can be searched for by name presumably).

This (old) post states:

Templates are effectively late-binding; the necessary template is not attached to the control in question until the control is ready for layout. And the control is not ready for layout until it is attached to a logical tree that connects to a rendering surface at the root. It is that root-level element that initiates the rendering of all of its child elements as defined in the logical tree.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745001349a279246.html

最新回复(0)