RelativeSource works on (nested) sub-property, while ElementName does not

不羁岁月 提交于 2019-12-11 03:39:45

问题


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.


回答1:


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).



来源:https://stackoverflow.com/questions/18419041/relativesource-works-on-nested-sub-property-while-elementname-does-not

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!