Проблема с привязкой данных WPF, Определенной в коде, Не Обновляющем элементы пользовательского интерфейса
-
03-07-2019 - |
Вопрос
Мне нужно определить новые элементы пользовательского интерфейса, а также привязку данных в коде, потому что они будут реализованы после выполнения.Вот упрощенная версия того, что я пытаюсь сделать.
Модель данных:
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));
}
}
}
Привязка в коде:
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
При первой привязке данных текстовый блок обновляется правильным номером дома.Затем, если я позже изменю номер дома в коде, сработает событие PropertyChanged для книги, но текстовый блок не будет обновлен.Кто-нибудь может сказать мне, почему?
Спасибо, Бен
Решение
Суть этого заключалась в том, что строка, которую я передал PropertyChangedEventArgs, не СОВСЕМ соответствовала имени свойства.У меня было что-то вроде этого:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNum"); }
}
Где это должно быть вот так:
public int HouseNumber
{
get { return _houseNumber; }
set { _houseNumber = value; NotifyPropertyChanged("HouseNumber"); }
}
Фу!Спасибо за толчок в правильном направлении.
Другие советы
Убедитесь, что вы обновляете AddressBook
ссылка, которая была использована в привязке, а не какая-то другая AddressBook
ссылка.
Я получил следующее для работы с кодом адресной книги, который вы дали.
<StackPanel>
<Button Click="Button_Click">Random</Button>
<Grid x:Name="myGrid">
</Grid>
</StackPanel>
Код, стоящий за:
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();
}
}
Обратите внимание, что та же ссылка используется в коде обновления.
Вам нужно программно установить режим привязки?Возможно, по умолчанию используется значение On TIME.
Я только что вырезал + вставил ваш код (и немного добавил), и у меня все работает нормально:
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++;
}
Отображает 456 при запуске, нажатие кнопки увеличивает число в текстовом блоке просто отлично.
Возможно, вы ищете причину проблемы не в том месте?
Вы уверены, что обновляете тот же объект, который вы использовали в привязке?На первый взгляд ничего не кажется неправильным, поэтому проверьте простые вещи.:)
Какой-либо код обходит свойство, устанавливая поле (_houseNumber
) непосредственно?