Search code examples
wpf

why custom control binding cause an error?


The code is as follows

1.MainWindow.cs

    <StackPanel>
        <Button x:Name="HelloButton" Width="100">Hello</Button>
        <lib:TestControl Width="100" TestValue="{Binding ElementName=HelloButton,Path=Width}">
            <lib:TestControl.Some>
                <lib:SomePropertyClass Inner="{Binding ElementName=HelloButton,Path=Width}"/>
            </lib:TestControl.Some>
        </lib:TestControl>
    </StackPanel>

2.TestControl.cs

public class TestControl : Control
{
    static TestControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(TestControl), new FrameworkPropertyMetadata(typeof(TestControl)));
    }

    public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register("TestValue", typeof(int), typeof(TestControl));
    public int TestValue
    {
        get => (int)GetValue(TestValueProperty);
        set => SetValue(TestValueProperty, value);
    }

    public static readonly DependencyProperty SomeProperty = DependencyProperty.Register("Some", typeof(SomePropertyClass), typeof(TestControl));
    public SomePropertyClass Some
    {
        get => (SomePropertyClass)GetValue(SomeProperty);
        set => SetValue(SomeProperty, value);
    }
}

public class SomePropertyClass : DependencyObject
{
    public static readonly DependencyProperty InnerProperty = DependencyProperty.Register("Inner", typeof(int), typeof(SomePropertyClass));
    public int Inner
    {
        get => (int)GetValue(InnerProperty);
        set => SetValue(InnerProperty, value);
    }
}

3.TestControl.xaml

    <Style TargetType="{x:Type local:TestControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:TestControl}">
                    <StackPanel>
                        <Button Content="{TemplateBinding TestValue}"/>
                        <Button Content="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Some.Inner}"/>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

'TestValue' property binding is expected,but why the 'Inner' property Binding cause an error?

'System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Width; DataItem=null; target element is 'SomePropertyClass' (HashCode=63183526); target property is 'Inner' (type 'Int32')'


Solution

  • why the 'Inner' property Binding cause an error?

    Because the element HelloButton cannot be found by the search algorithm. x:Reference should work:

    <lib:SomePropertyClass Inner="{Binding Path=Width,Source={x:Reference HelloButton}}"/>
    

    SomePropertyClass is not in the same namescope as HelloButton but TestControl is.

    What is the difference between x:Reference and ElementName?