2009-01-02 12 views
8

Necesito definir nuevos elementos de la interfaz de usuario así como el enlace de datos en el código porque se implementarán después del tiempo de ejecución. Aquí hay una versión simplificada de lo que estoy tratando de hacer.Problema con la vinculación de datos WPF definida en el código No actualizar elementos de la interfaz de usuario

Modelo de datos:

public class AddressBook : INotifyPropertyChanged 
{ 
    private int _houseNumber; 
    public int HouseNumber 
    { 
     get { return _houseNumber; } 
     set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void NotifyPropertyChanged(string sProp) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(sProp)); 
     } 
    } 
} 

Encuadernación en Código:

AddressBook book = new AddressBook(); 
book.HouseNumber = 123; 
TextBlock tb = new TextBlock(); 
Binding bind = new Binding("HouseNumber"); 
bind.Source = book; 
bind.Mode = BindingMode.OneWay; 
tb.SetBinding(TextBlock.TextProperty, bind); // Text block displays "123" 
myGrid.Children.Add(tb); 
book.HouseNumber = 456; // Text block displays "123" but PropertyChanged event fires 

Cuando los datos se une primero, el bloque de texto se actualiza con el número de la casa correcta. Luego, si cambio el número de la casa en el código más tarde, se activa el evento PropertyChanged del libro, pero el bloque de texto no se actualiza. puede alguien decirme por que?

Gracias, Ben

+0

¿Ha intentado establecer puntos de interrupción para ver si se golpean cuando establece la propiedad? – John

+0

Sí, tengo un cuadro de mensaje emergente cuando se activa el evento PropertyChanged del libro, que ocurre en cada actualización de datos. –

+0

La [respuesta más interesante] (http: // stackoverflow.com/a/406595/200449), IMO, es por @StevenRobbins, aunque está infravalorado y luego enterrado dentro de otras respuestas –

Respuesta

10

La raíz de esto era que la cadena que pasé a PropertyChangedEventArgs no coincidía EXACTAMENTE con el nombre de la propiedad. Tenía algo como esto:

public int HouseNumber 
{ 
    get { return _houseNumber; } 
    set { _houseNumber = value; NotifyPropertyChanged("HouseNum"); } 
} 

donde debe estar presente:

public int HouseNumber 
{ 
    get { return _houseNumber; } 
    set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); } 
} 

Huy! Gracias por el empuje en la dirección correcta.

+0

Aha .. He hecho lo mismo cuando cambié el nombre de una propiedad :) ¿El código que pegaste era correcto? –

+0

Cambié los nombres de las propiedades reales que estaba usando para proteger a los inocentes :) –

+0

Estaba a punto de sugerir esto como un problema común. INotifyPropertyChanged es tan frágil. Ojalá no fuéramos forzados a usar ese tipo de basura. –

2

¿Necesita para establecer el modo de unión mediante programación? Puede estar predeterminado en OneTime.

+0

Gracias por la sugerencia, pero agregando: bind.Mode = BindingMode.OneWay; No tiene ningún efecto. –

+0

Es posible que esté malinterpretando, pero suena como Beepcake significa intentar configurar el BindingMode en BindingMode.TwoWay. TextBlocks son OneWay por defecto. – Jab

+0

El código en cuestión realmente funciona sin configurar 'BindingMode' –

1

¿Estás seguro de que estás actualizando el mismo objeto que has utilizado en el enlace? A primera vista, nada parece estar mal, así que revise las cosas simples. :)

+0

Esa iba a ser mi próxima sugerencia :) –

+0

Creé una instancia de objeto completamente única llamada" testing "y la actualicé una vez antes del enlace y una vez después del enlace y el bloque de texto se mantuvo en el valor antes de vincularse aunque se activó el evento PropertyChanged para "probar". –

0

¿Hay algún código que omita la propiedad, estableciendo el campo (_houseNumber) directamente?

+0

PropertyChanged woudln't fire then would would it? –

+0

Cierto, cierto ... solo trato de pensar por qué el bloque de texto no se está actualizando ... –

+0

Solo asegúrate de que no estuviese tenue :) Mi dinero está en el código actualizando una instancia diferente de AddressBook :) –

3

Asegúrese de estar actualizando la referencia AddressBook que se utilizó en el enlace, y no alguna otra referencia AddressBook.

Obtuve lo siguiente para trabajar con el código AddressBook que me diste.

Código
<StackPanel> 
    <Button Click="Button_Click">Random</Button> 
    <Grid x:Name="myGrid"> 
    </Grid> 
</StackPanel> 

atrás:

public partial class Window1 : Window 
{ 
    private AddressBook book; 

    public Window1() 
    { 
     InitializeComponent(); 

     book = new AddressBook(); 
     book.HouseNumber = 13; 

     TextBlock tb = new TextBlock(); 
     Binding bind = new Binding("HouseNumber"); 
     bind.Source = book; 
     tb.SetBinding(TextBlock.TextProperty, bind); 
     myGrid.Children.Add(tb); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Random rnd = new Random(); 
     book.HouseNumber = rnd.Next(); 
    } 
} 

Nota la misma referencia se utiliza en el código de actualización.

2

que acabo de cortar + pegar el código (y añade un poco), y funciona bien para mí:

public Window1() 
    { 
     InitializeComponent(); 

     AddressBook book = new AddressBook(); 
     book.HouseNumber = 123; 
     TextBlock tb = new TextBlock(); 
     Binding bind = new Binding("HouseNumber"); 
     bind.Source = book; 
     bind.Mode = BindingMode.OneWay; 
     tb.SetBinding(TextBlock.TextProperty, bind); // Text block displays "123" 
     myGrid.Children.Add(tb); 
     book.HouseNumber = 456; 
    } 

    private void TestButton_Click(object sender, RoutedEventArgs e) 
    { 
     AddressBook book = 
      (AddressBook(TextBlock) 
       myGrid.Children[0]) 
       .GetBindingExpression(TextBlock.TextProperty) 
       .DataItem; 

     book.HouseNumber++; 
    } 

Muestra 456 en el arranque, al hacer clic en el botón hace que el número en el incremento TextBlock solo multa.

¿Quizás esté buscando en el lugar equivocado la causa del problema?

+0

+1 Esto es muy enriquecedor para ver cómo obtener obj de datos del elemento GUI (hijo) ... aunque podría obtenerlo de forma más simple como en [respuesta de Cameron MacFarland] (http://stackoverflow.com/a/406555/200449) –

Cuestiones relacionadas