2009-06-10 6 views
30

Je peux lier à une propriété, mais pas à une propriété dans une autre propriété. Pourquoi pas? par exemple.WPF: Comment lier à une propriété imbriquée?

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

(Note:.. Je ne cherche pas à faire maître-détails ou quoi que ce soit deux propriétés sont des propriétés CLR standards)

Mise à jour: le problème était que mon parentProperty dépendait d'un objet en XAML étant initialisé. Malheureusement cet objet a été défini plus tard dans le fichier XAML que la liaison, donc l'objet était nul au moment où mon ParentProperty a été lu par la liaison. Depuis réorganisant le fichier XAML visserait la mise en page, la seule solution que je pouvais penser était de définir la liaison dans le code-behind:

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

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

Répondre

22

Tout ce que je peux penser est que le ParentProperty est changé après la Binding est créé et ne prend pas en charge la notification de modification. Chaque propriété de la chaîne doit prendre en charge la notification de modification, que ce soit en vertu de DependencyProperty ou en mettant en œuvre INotifyPropertyChanged.

+0

Oui, cela semble être la raison. ParentProperty est en lecture seule mais dépend d'un certain contrôle dans XAML en cours d'initialisation. Cet objet est défini dans le fichier .xaml APRÈS la liaison, alors quand ParentProperty a été appelé, il a jeté NullReferenceException. Je n'ai pas remarqué parce que WPF l'a avalé. J'aurais dû vérifier la fenêtre de sortie! – Qwertie

+0

Maintenant, j'ai un nouveau puzzle - comment définir les objets dans le bon ordre dans XAML sans gâcher la mise en page. – Qwertie

+0

Ou puis-je faire en sorte que la liaison attende que la fenêtre soit entièrement initialisée avant de lire la propriété? Lorsque j'utilise {Binding ElementName = xyz, ...}, cela fonctionne même si xyz est défini plus tard dans le fichier XAML. Étrange alors que mon ParentProperty (qui utilise l'élément xyz) ne fonctionne pas simplement parce que xyz est défini plus tard dans le fichier XAML. – Qwertie

3

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

Vous pouvez également définir DataContext pour TextBox en XAML (je ne sais pas si c'est la solution optimale, mais au moins vous ne devez pas faire quoi que ce soit manuellement dans CodeBehind sauf la mise en œuvre 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"/> 

Soyez conscient que jusqu'à ce que votre DataContext pour TextBox n'est pas prêt obligatoire pour Text la propriété ne sera pas « établie » - vous pouvez ajouter FallbackValue='error' en tant que paramètre de liaison - ce sera quelque chose comme indicateur qui vous montrera si la liaison est OK ou non.

+4

+1 pour le conseil sur FallbackValue :) – Qwertie

Questions connexes