2009-06-10 27 views
30

Puedo vincularme a una propiedad, pero no a una propiedad dentro de otra. Por qué no? p.ej.WPF: ¿Cómo enlazar a una propiedad anidada?

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

(Nota:.. No estoy tratando de hacer magistrales detalles o nada Ambas propiedades son propiedades estándar CLR)

Actualización: el problema es que mi ParentProperty dependía de un objeto en XAML siendo inicializado Lamentablemente, ese objeto se definió más tarde en el archivo XAML que en el Enlace, por lo que el objeto era nulo en el momento en que mi ParentProperty fue leído por el Enlace. Desde reordenar el archivo XAML sería arruinar el diseño, la única solución que se me ocurrió fue definir la unión de código subyacente:

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

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

Respuesta

22

Todo lo que puedo pensar es que el ParentProperty está siendo cambiado después de la Binding se crea y no admite la notificación de cambio. Todas las propiedades de la cadena deben admitir la notificación de cambio, ya sea en virtud de DependencyProperty o implementando INotifyPropertyChanged.

+0

Sí, parece ser una especie de razón. ParentProperty es de solo lectura, pero depende de un control determinado en XAML que se está inicializando. Este objeto se define en el archivo .xaml DESPUÉS de la vinculación, por lo que cuando se llamó a ParentProperty, arrojó NullReferenceException. No me di cuenta porque WPF se lo tragó. Debería haber revisado la ventana de salida! – Qwertie

+0

Ahora tengo un nuevo rompecabezas: cómo definir los objetos en el orden correcto en XAML sin estropear el diseño. – Qwertie

+0

¿O puedo de alguna manera hacer que la vinculación espere hasta que la ventana esté completamente inicializada antes de leer la propiedad? Cuando uso {Binding ElementName = xyz, ...}, funciona incluso si xyz se define más adelante en el archivo XAML. Es extraño entonces que mi ParentProperty (que usa el elemento xyz) no funcione solo porque xyz se define más adelante en el archivo XAML. – Qwertie

3

¿Tanto ParentProperty como su clase implementan 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

También puede configurar para DataContextTextBox en XAML (no sé si se trata de una solución óptima, pero al menos no tengo que hacer nada manualmente en el código subyacente, excepto de implementar INotifyPropertyChanged). Cuando su TextBox tiene ya DataContext (heredado DataContext) que escribir código como este:

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

Tenga en cuenta que hasta que su DataContext para TextBox no está listo para la unión Text propiedad no será 'establecido' - se puede añadir FallbackValue='error' como parámetro de enlace, será algo así como un indicador que le mostrará si el enlace está bien o no.

+4

+1 para la sugerencia sobre FallbackValue :) – Qwertie

Cuestiones relacionadas