Problema com WPF vinculação de dados definidos no Código Não Atualizando Elementos UI
-
03-07-2019 - |
Pergunta
Eu preciso definir novos elementos de interface do usuário, bem como a ligação de dados em código, porque eles vão ser implementada após run-time. Aqui está uma versão simplificada do que estou tentando fazer.
Modelo de Dados:
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));
}
}
}
Binding no 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
Quando os dados são primeiro limite, o bloco de texto é atualizado com o número da casa correta. Então, se eu mudar o número da casa no código mais tarde, incêndios PropertyChanged evento do livro, mas o bloco de texto não é atualizado. Alguém pode me dizer por quê?
Obrigado, Ben
Solução
A raiz de tudo é que a string I passado para PropertyChangedEventArgs não corresponder exatamente ao nome da propriedade. Eu tinha algo como isto:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNum"); }
}
Onde deve ser esta:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); }
}
Caramba! Agradecimentos para o impulso na direção certa.
Outras dicas
Certifique-se de que você está atualizando a referência AddressBook
que foi usado na ligação, e não alguma outra referência AddressBook
.
Eu tenho o seguinte para o trabalho com o código AddressBook que você deu.
<StackPanel>
<Button Click="Button_Click">Random</Button>
<Grid x:Name="myGrid">
</Grid>
</StackPanel>
código por trá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();
}
}
Observe a mesma referência é usado no código de atualização.
Você precisa definir o modo de ligação através de programação? Pode ser falta para OneTime.
Acabei de cortar + colou seu código (e acrescentou um pouco), e ele funciona muito bem para mim:
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++;
}
Exibe 456 no arranque, clicando no botão faz com que o número no incremento TextBlock muito bem.
Talvez você esteja procurando no lugar errado para a causa do problema?
Você tem certeza de que você está atualizando o mesmo objeto que você usou na ligação? À primeira vista, nada parece errado, de modo a verificar as coisas simples. :)
Será que algum código de bypass da propriedade, definindo o campo (_houseNumber
) diretamente?