c# - RelativeSource 适用于(嵌套的)子属性,而 ElementName 不适用

标签 c# wpf xaml data-binding elementname

以下代码的问题是:绑定(bind)到 SomeClassProp.SubTextProp 不起作用(源属性未设置为文本框内容),而绑定(bind)到 TextProp 确实如此。

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>

和代码:

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; }
}

我是否遗漏了一些明显的东西?

请注意,我需要此绑定(bind)才能从目标(文本框)到源(类属性)。

更新:当我将绑定(bind)从 ElementName=wMain 更改为 RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}} - 两个绑定(bind)工作。所以问题特定于 ElementName 绑定(bind)属性。

最佳答案

好的,终于找到问题了!

在将 diag:PresentationTraceSources.TraceLevel=High 添加到绑定(bind) defs 之后(顺便说一句,非常有用的东西,在没有正常的 ol' 逐步调试的情况下),我在输出中看到以下内容:

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();
}

问题的答案 - 为什么它使用 RelativeSource 属性起作用 - 在于输出日志的这些行:

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

使用RelativeSource 进行数据上下文初始化需要树上下文,并延迟到构建Window 之后的某个时间点(到那时SomeClassProperty 已经初始化)。

关于c# - RelativeSource 适用于(嵌套的)子属性,而 ElementName 不适用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18419041/

相关文章:

c# - 如果用户控件的数据上下文是 View 模型,如何绑定(bind)到 xaml 代码隐藏中的属性?

c# - WPF Popup 作为用 xaml 编写的单独控件

c# - 如何知道文本框是粗体还是斜体?

c# - WCF:消息中没有名称为 '' 且命名空间为 '' 的 header

c# - BooleanToVisibilityConverter 带复选框

wpf - 如何在C#(代码隐藏)中旋转文本 block 中的文本~~

c# - 无法从我的 Windows Phone 8.1 应用程序中的 ListView 拖动项目

c# - Web 应用程序 - 解析器错误 - 无法加载类型

c# - 为 WPF 形状启用抗锯齿

c# - wpf 为命名元素创建样式