WPF:如何绑定到嵌套属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/978473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:33:09  来源:igfitidea点击:

WPF: How to bind to a nested property?

wpfbindingpropertiesnested

提问by Qwertie

I can bind to a property, but not a property within another property. Why not? e.g.

我可以绑定到一个属性,但不能绑定到另一个属性中的一个属性。为什么不?例如

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}"...>
...
    <!--Doesn't work-->
    <TextBox Text="{Binding Path=ParentProperty.ChildProperty,Mode=TwoWay}" 
             Width="30"/>

(Note: I'm not trying to do master-details or anything. Both properties are standard CLR properties.)

(注意:我不想做主细节或任何事情。这两个属性都是标准的 CLR 属性。)

Update: the problem was that my ParentProperty depended on an object in XAML being initialized. Unfortunately that object was defined later in the XAML file than the Binding, so the object was null at the time when my ParentProperty was read by the Binding. Since rearranging the XAML file would screw up the layout, the only solution I could think of was to define the Binding in code-behind:

更新:问题是我的 ParentProperty 依赖于正在初始化的 XAML 中的对象。不幸的是,该对象在 XAML 文件中的定义晚于 Binding,因此在 Binding 读取我的 ParentProperty 时,该对象为 null。由于重新排列 XAML 文件会破坏布局,我能想到的唯一解决方案是在代码隐藏中定义绑定:

<TextBox x:Name="txt" Width="30"/>

// after calling InitializeComponent()
txt.SetBinding(TextBox.TextProperty, "ParentProperty.ChildProperty");

采纳答案by Kent Boogaart

All I can think of is that the ParentPropertyis being changed after the Bindingis created, and it does not support change notification. Every property in the chain must support change notification, whether it be by virtue of being a DependencyProperty, or by implementing INotifyPropertyChanged.

我能想到的是,在创建ParentProperty后正在更改Binding,并且它不支持更改通知。链中的每个属性都必须支持更改通知,无论是通过成为DependencyProperty还是通过实现INotifyPropertyChanged

回答by ilektrik

You can also set DataContextfor TextBoxin XAML (I don't know if it's optimal solution, but at least you don't have to do anything manually in codeBehind except of implementing INotifyPropertyChanged). When your TextBoxhas already DataContext(inherited DataContext) you write code like this:

您也可以在 XAML 中设置DataContextfor TextBox(我不知道它是否是最佳解决方案,但至少除了实现 之外,您不必在 codeBehind 中手动执行任何操作INotifyPropertyChanged)。当你TextBox已经DataContext(继承DataContext)你写这样的代码:

<TextBox 
   DataContext="{Binding Path=ParentProperty}"
   Text="{Binding Path=ChildProperty, Mode=TwoWay}" 
   Width="30"/>

Be aware that until your DataContextfor TextBoxisn't ready binding for Textproperty will not be 'established' - you can add FallbackValue='error'as Binding parameter - it will be something like indicator which will show you if binding is OK or not.

请注意,在您的DataContextforTextBox尚未准备好之前,不会Text“建立”属性绑定- 您可以添加FallbackValue='error'为 Binding 参数 - 它将类似于指示符,它将向您显示绑定是否正常。

回答by user112889

Do both the ParentProperty and your class implement INotifyPropertyChanged?

ParentProperty 和您的类是否都实现了 INotifyPropertyChanged?

    public class ParentProperty : INotifyPropertyChanged
    {
        private string m_ChildProperty;

        public string ChildProperty
        {
            get
            {
                return this.m_ChildProperty;
            }

            set
            {
                if (value != this.m_ChildProperty)
                {
                    this.m_ChildProperty = value;
                    NotifyPropertyChanged("ChildProperty");
                }
            }
        }

        #region INotifyPropertyChanged Members

        #endregion
    }

    public partial class TestClass : INotifyPropertyChanged
    {
        private ParentProperty m_ParentProperty;

        public ParentProperty ParentProperty
        {
            get
            {
                return this.m_ParentProperty;
            }

            set
            {
                if (value != this.m_ParentProperty)
                {
                    this.m_ParentProperty = value;
                    NotifyPropertyChanged("ParentProperty");
                }
            }
        }
}
    public TestClass()

    {
        InitializeComponent();
        DataContext = this;
        ParentProperty = new ParentProperty();
        ParentProperty.ChildProperty = new ChildProperty();

        #region INotifyPropertyChanged Members
        #endregion
    }