web-dev-qa-db-fra.com

WPF: comment lier à une propriété imbriquée?

Je peux me lier à une propriété, mais pas à une propriété dans une autre propriété. Pourquoi pas? par exemple.

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

(Remarque: je n'essaie pas de faire des détails principaux ou quoi que ce soit. Les deux propriétés sont des propriétés CLR standard.)

Mise à jour: le problème était que ma ParentProperty dépendait d'un objet en XAML en cours d'initialisation. Malheureusement, cet objet a été défini plus tard dans le fichier XAML que la liaison, donc l'objet était nul au moment où ma propriété parentale a été lue par la liaison. Étant donné que réorganiser le fichier XAML reviendrait à bousiller la disposition, la seule solution à laquelle je pouvais penser était de définir la liaison en code-behind:

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

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

Tout ce à quoi je peux penser, c'est que le ParentProperty est modifié après la création du Binding et qu'il ne prend pas en charge la notification de changement. Chaque propriété de la chaîne doit prendre en charge la notification des modifications, que ce soit en raison d'être DependencyProperty ou en implémentant INotifyPropertyChanged.

25
Kent Boogaart

Vous pouvez également définir DataContext pour TextBox en XAML (je ne sais pas si c'est la solution optimale, mais au moins vous n'avez rien à faire manuellement dans codeBehind sauf d'implémenter INotifyPropertyChanged). Lorsque votre TextBox a déjà DataContext (hérité DataContext), vous écrivez du code comme ceci:

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

N'oubliez pas que tant que votre DataContext pour TextBox n'est pas prête, la liaison pour Text ne sera pas 'établie' - vous pouvez ajouter FallbackValue='error' comme paramètre de liaison - ce sera quelque chose comme un indicateur qui vous montrera si la liaison est OK ou non.

44
ilektrik

Est-ce que ParentProperty et votre classe implémentent 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
    }
4
user112889