Problem mit WPF Daten in Code definiert Bindung nicht aktualisiert UI-Elemente
-
03-07-2019 - |
Frage
Ich muss neue UI-Elemente sowie Daten definieren in Code verbindlich, da sie nach der Laufzeit implementiert werden wird. Hier ist eine vereinfachte Version von dem, was ich zu tun versuchen.
Datenmodell:
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));
}
}
}
in der Code-Bindung:
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
Wenn die Daten zuerst gebunden ist, wird der Textblock mit der richtigen Hausnummer aktualisiert. Dann später, wenn ich die Hausnummer in Code zu ändern, das Property-Ereignis ausgelöst Buch, aber der Textblock nicht aktualisiert. Kann mir jemand sagen, warum?
Danke, Ben
Lösung
Die Wurzel war es, dass die Zeichenfolge ich PropertyChangedEventArgs gab GENAU nicht den Namen der Eigenschaft entsprechen. Ich hatte so etwas wie folgt aus:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNum"); }
}
Wo sollte es sein:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); }
}
Huch! Danke für den Schub in der richtigen Richtung.
Andere Tipps
Stellen Sie sicher, dass Sie die AddressBook
Referenz sind die Aktualisierung, die in der Bindung verwendet wurde, und nicht eine andere AddressBook
Referenz.
Ich habe folgendes mit dem Addressbook-Code arbeiten Sie gab.
<StackPanel>
<Button Click="Button_Click">Random</Button>
<Grid x:Name="myGrid">
</Grid>
</StackPanel>
-Code hinter:
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();
}
}
Beachten Sie die gleiche Referenz wird in dem Update-Code verwendet wird.
Sie benötigen den Bindungsmodus programmatisch setzen? Es kann zu OneTime werden säumige.
Ich habe gerade geschnitten + eingefügt Code (und fügte ein wenig), und es funktioniert gut für mich:
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++;
}
Zeigt 456 beim Start auf die Schaltfläche klicken macht die Zahl im Textblock Zuwachs gut.
Vielleicht sind Sie an der falschen Stelle für die Ursache des Problems suchen?
Sind Sie sicher, dass Sie das gleiche Objekt sind zu aktualisieren, wie Sie in der Bindung verwendet haben? Auf den ersten Blick nichts sieht falsch, so überprüfen Sie die einfachen Dinge. :)
Hat jeder Code die Eigenschaft zu umgehen, Einstellen des Feldes (_houseNumber
) direkt?