Question

The problem with the code below is: the binding to SomeClassProp.SubTextProp doesn't work (the source property is not being set to textbox content), while to TextProp it does.

XAML:

<Window x:Class="TestWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Name="wMain"
        SizeToContent="WidthAndHeight">
    <StackPanel>
        <TextBox Text="{Binding ElementName=wMain, Path=SomeClassProp.SubTextProp}" Width="120" Height="23" />
        <TextBox Text="{Binding ElementName=wMain, Path=TextProp}" Width="120" Height="23" />
    </StackPanel>
</Window>

and the code:

public partial class MainWindow : Window
{
    public SomeClass SomeClassProp { get; set; }
    public string TextProp { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        SomeClassProp = new SomeClass();
    }
}

public class SomeClass
{
    public string SubTextProp { get; set; }
}

Am I missing something obvious here?

Note that I need this binding to work from target (textbox) to source (class property).

UPDATE: When I change the binding from ElementName=wMain to RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} - BOTH bindings work. So the problem is specific to ElementName binding property.

Was it helpful?

Solution

Ok, finally, I found the problem!

After adding diag:PresentationTraceSources.TraceLevel=High to binding defs (very useful thing btw, in the absence of normal ol' step-by-step debugging), I saw the following in the output:

System.Windows.Data Warning: 108 : BindingExpression (hash=54116930):   At level 0 - for MainWindow.SomeClassProp found accessor RuntimePropertyInfo(SomeClassProp)
System.Windows.Data Warning: 104 : BindingExpression (hash=54116930): Replace item at level 0 with MainWindow (hash=47283970), using accessor RuntimePropertyInfo(SomeClassProp)
System.Windows.Data Warning: 101 : BindingExpression (hash=54116930): GetValue at level 0 from MainWindow (hash=47283970) using RuntimePropertyInfo(SomeClassProp): 
System.Windows.Data Warning: 106 : BindingExpression (hash=54116930):   Item at level 1 is null - no accessor
System.Windows.Data Warning: 80 : BindingExpression (hash=54116930): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=54116930): TransferValue - using fallback/default value ''
System.Windows.Data Warning: 89 : BindingExpression (hash=54116930): TransferValue - using final value ''

The problem was in the order of MainWindow initialization!

So at the moment when the binding was constructed, my level 0 property (SomeClassProp) was not yet initialized, which resulted in binding failing completely (without issuing a normal-level binging warning for some reason).

Long story short - moving SomeClassProp intitialization before the InitializeComponent() in MainWindow constructor did the trick, binding started to work with ElementName too:

public MainWindow()
{
    SomeClassProp = new SomeClass();
    InitializeComponent();
}

The answer to question - why it worked using RelativeSource property - lies in these lines of the output log:

System.Windows.Data Warning: 66 : BindingExpression (hash=28713467): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 65 : BindingExpression (hash=28713467): Resolve source deferred

Data context initialization with RelativeSource requires tree context, and is deferred to some point in time after construction of the Window (by that time SomeClassProperty was already initialized).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top