2009-06-10 14 views
30

Mogę powiązać z nieruchomością, ale nie jest własnością w innej nieruchomości. Dlaczego nie? na przykładWPF: jak powiązać z właściwością zagnieżdżoną?

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

(Uwaga:.. Nie próbuję robić mistrzowskie szczegółów ani niczego Obie właściwości są standardowe właściwości CLR)

Aktualizacja: Problemem było to, że mój ParentProperty zależało na obiekcie w XAML bycia zainicjowany. Niestety ten obiekt został zdefiniowany później w pliku XAML niż powiązanie, więc obiekt był zerowy w momencie, gdy moja ParentProperty została odczytana przez powiązanie. Od rozmieszczanie plik XAML byłoby zepsuć układ, jedynym rozwiązaniem mogłem pomyśleć było określenie wiąże w opóźnieniem kodu:

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

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

Odpowiedz

22

Wszystko, co mogę myśleć o to, że ParentProperty ulega zmianie po Binding jest tworzony i nie obsługuje powiadomienia o zmianie. Każda nieruchomość w łańcuchu musi obsługiwać powiadomienia o zmianach, niezależnie od tego, czy są to: DependencyProperty, czy też implementacja INotifyPropertyChanged.

+0

Tak, to wydaje się być jakby powodem. ParentProperty jest tylko do odczytu, ale zależy od pewnej kontroli podczas inicjowania XAML. Ten obiekt jest zdefiniowany w pliku .xaml PO Powiązaniu, więc gdy wywołano ParentProperty, zarzucono wyjątek NullReferenceException. Nie zauważyłem, ponieważ WPF ją połknęła. Powinienem był sprawdzić okno wyjściowe! – Qwertie

+0

Teraz mam nową zagadkę - jak zdefiniować obiekty w odpowiedniej kolejności w XAML bez zmyślania układu. – Qwertie

+0

Czy mogę w jakiś sposób sprawić, aby wiązanie czekało, aż okno zostanie w pełni zainicjowane, zanim odczyta właściwość? Kiedy używam {Binding ElementName = xyz, ...}, działa to nawet wtedy, gdy xyz jest zdefiniowany później w pliku XAML. Dziwne, że moja ParentProperty (która używa elementu xyz) nie działa tylko dlatego, że xyz jest zdefiniowany później w pliku XAML. – Qwertie

3

Czy zarówno ParentProperty, jak i twoja klasa implementują 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

Można również ustawić DataContext dla TextBox w XAML (nie wiem, czy jest to optymalne rozwiązanie, ale przynajmniej nie musisz nic robić ręcznie w kodzie oprócz wdrożenia INotifyPropertyChanged). Gdy TextBox już DataContext (dziedziczone DataContext) piszesz kod tak:

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

Należy pamiętać, że do swojej DataContext dla TextBox nie jest gotowy wiążące dla Text nieruchomości nie będzie „założony” - można dodać FallbackValue='error' jako parametr wiązania - będzie to coś w rodzaju wskaźnika, który wskaże, czy powiązanie jest poprawne czy nie.

+4

+1 za wskazówkę na temat FallbackValue :) – Qwertie

Powiązane problemy