Lork
Lork

Reputation: 133

Why am I getting the error "Cannot find source for binding with reference"?

My WPF controls are not rendering as I expect. Specifically, when I assign a value to a dependency property of a user control, then that user control tries to use the value on one if its child controls, something goes wrong and the child control does not render as it should.

I've distilled the problem down to a simple example, presented below. I have created a RedBox user control, which displays its content inside a red border, and a BlueBox user control, which is supposed to display bound text in a TextBlock inside a RedBox. That last part fails. I suspect the trouble is on Line 35 of BlueBox.xaml, but that's just a guess.

RedBox.xaml

<UserControl
        x:Class="WpfApplication1.RedBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        mc:Ignorable="d">
    <ContentControl.Template>
        <ControlTemplate TargetType="UserControl">
            <Border BorderBrush="Red" BorderThickness="4" Padding="4">
                <ContentPresenter Margin="3,0,0,0" Content="{TemplateBinding Content}" VerticalAlignment="Center" />
            </Border>
        </ControlTemplate>
    </ContentControl.Template>
</UserControl>

RedBox.xaml.cs

namespace WpfApplication1
{
    public partial class RedBox
    {
        public RedBox()
        {
            InitializeComponent();
        }
    }
}

BlueBox.xaml

<UserControl x:Class="WpfApplication1.BlueBox"
             x:Name="UserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:wpfApplication1="clr-namespace:WpfApplication1"
             mc:Ignorable="d">

    <Border BorderBrush="Blue" BorderThickness="4" Padding="4">

        <Grid>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <TextBlock Grid.Row="0" Grid.Column="0" Text="Show the BlueBox's Text property value:" />
            <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=UserControl, Path=Text}" />

            <TextBlock Grid.Row="1" Grid.Column="0" Text="Show static text within a RedBox:" />
            <wpfApplication1:RedBox Grid.Row="1" Grid.Column="1">
                <TextBlock Text="Static Text" />
            </wpfApplication1:RedBox>

            <TextBlock Grid.Row="2" Grid.Column="0" Text="Show the BlueBox's Text property value within a RedBox:" />
            <wpfApplication1:RedBox Grid.Row="2" Grid.Column="1">
                <TextBlock Text="{Binding ElementName=UserControl, Path=Text}" />
            </wpfApplication1:RedBox>

        </Grid>

    </Border>
</UserControl>

BlueBox.xaml.cs

using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    public partial class BlueBox
    {
        public BlueBox()
        {
            InitializeComponent();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            name: "Text",
            propertyType: typeof(string),
            ownerType: typeof(BlueBox),
            typeMetadata: new PropertyMetadata());
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <wpfApplication1:BlueBox Text="Hi!" />
</Window>

If I could post a screenshot of the runtime MainWindow, you'd see that all dependency properties are wired-up correctly, but where there should be a red box with "Hi!" in it, there simply isn't one. The Output window gives me this error:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=UserControl'. BindingExpression:Path=Text; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

In researching the error "Cannot find source for binding with reference" I've found that a frequent cause of the error is that people try to bind to something that isn't in the visual tree of the object they're binding to. But I don't think that's my problem here because the BlueBox is within the visual tree of its own TextBlock control, isn't it?

What, then, is going on?

Update:

I have discovered that if I replace line 35 of BlueBox.xaml with the following, it works:

            <TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type wpfApplication1:BlueBox}}, Path=Text}" />

This solves my problem. I'm still baffled why the ElementName syntax didn't work, though. I'd appreciate any insight into that.

Upvotes: 0

Views: 2800

Answers (1)

Avestura
Avestura

Reputation: 1557

Your dependency property Text is type of String. But you registered its default value as PropertyMetadata() of an unspecific type. Either don't provide a type metadata, or give it a proper one, like: new PropertyMetadata("default value")

Change this part of your code:

public static readonly DependencyProperty TextProperty = 
       DependencyProperty.Register(
             name: "Text",
             propertyType: typeof(string),
             ownerType: typeof(BlueBox),
             typeMetadata: new PropertyMetadata());

To this:

public static readonly DependencyProperty TextProperty = 
       DependencyProperty.Register(
             name: "Text",
             propertyType: typeof(string),
             ownerType: typeof(BlueBox));

This might resolve your problem.

Upvotes: 3

Related Questions