Обновление всех привязок WPF после изменения источника ⇐ C#
-
Anonymous
Обновление всех привязок WPF после изменения источника
В моем приложении есть класс под названием Study, который содержит свойство — структуру данных Data, которая имеет глубокую структуру различных других свойств. Исследование также содержит метод сброса данных или загрузки их из XML-файла. Реализация:
публичный класс Study, INotifyPropertyChanged { публичное событие PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged (имя строки [CallerMemberName] = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } частные StudyData _data = new(); общедоступные данные StudyData { получить {вернуться _data; } набор { _данные = значение; OnPropertyChanged(имя(Данные)); } публичная недействительность ResetData() { Данные = новые(); } общественная пустота LoadData (строка xmlPath) { Данные = LoadFromXML(xmlPath); //.... } } Во время запуска приложения экземпляр Study передается окну WPF MainWindow:
MainWindow mainWindow = new(study); MainWindow сохраняет эту ссылку в своих общедоступных переменных, передает ее другим страницам WPF, и где-то в дальнейшем определенный элемент управления привязывается к некоторому подмножеству Data, для пример:
selectedItemsListBox.ItemsSource = Study.Data.UserInputsData.SelectedItems.Values; (Обратите внимание, что Data, UserInputsData и SelectedItems определены как свойства, и каждый из них имеет IPropertyChanged реализовано на них)
Проблема в том, что когда я вызываю ResetData или LoadData, которые заменяют Data, привязки не обновляются, а MainWindow отображает старые данные.
Может кто-нибудь сказать мне, что я здесь делаю не так?
РЕДАКТИРОВАТЬ: я обнаружил, что если я создам новое свойство в своем MainWindow, вот так:
Значения
public ObservableCollection { получать { вернуть исследование.Data.UserInputsData.SelectedItems.Values; } } И привязывайтесь в XAML, а не в коде:
Затем он обновляется, когда я вызываю ResetData или LoadData. Однако я хочу выполнить привязку кода программной части и не объявлять эти дополнительные свойства в MainWindow, например это свойство Values, которое я объявляю для тестирования. Сможет ли кто-нибудь мне помочь, имея эту обновленную информацию?
РЕДАКТИРОВАТЬ 2:
Я решил эту проблему, реализовав эти две функции:
public static void SetBinding(элемент ItemsControl, выражение Expression) { строковый путь = GetFullReferencePath(выражение); Привязка привязка = новый Binding () {Путь = новый PropertyPath (путь) }; item.SetBinding(ItemsControl.ItemsSourceProperty, привязка); } общедоступная статическая строка GetFullReferencePath(выражение Expression) { варmemberExpression = (MemberExpression)expression.Body; вар стек = новый стек(); в то время как (memberExpression!= ноль) { stack.Push(memberExpression.Member.Name); Выражение-члена = Выражение-члена.Выражение как Выражение-члена; } return string.Join(".", стек); } А затем привязываем мой SelectedItemsListBox следующим образом:
SetBinding(SelectedItemsListBox, () => Study.Data.UserInputsData.SelectedItems.Values); Хотя это работает, это решение кажется очень странным, и я не могу поверить, что мне следует это делать. Может ли кто-нибудь предложить более простой способ?
В моем приложении есть класс под названием Study, который содержит свойство — структуру данных Data, которая имеет глубокую структуру различных других свойств. Исследование также содержит метод сброса данных или загрузки их из XML-файла. Реализация:
публичный класс Study, INotifyPropertyChanged { публичное событие PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged (имя строки [CallerMemberName] = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } частные StudyData _data = new(); общедоступные данные StudyData { получить {вернуться _data; } набор { _данные = значение; OnPropertyChanged(имя(Данные)); } публичная недействительность ResetData() { Данные = новые(); } общественная пустота LoadData (строка xmlPath) { Данные = LoadFromXML(xmlPath); //.... } } Во время запуска приложения экземпляр Study передается окну WPF MainWindow:
MainWindow mainWindow = new(study); MainWindow сохраняет эту ссылку в своих общедоступных переменных, передает ее другим страницам WPF, и где-то в дальнейшем определенный элемент управления привязывается к некоторому подмножеству Data, для пример:
selectedItemsListBox.ItemsSource = Study.Data.UserInputsData.SelectedItems.Values; (Обратите внимание, что Data, UserInputsData и SelectedItems определены как свойства, и каждый из них имеет IPropertyChanged реализовано на них)
Проблема в том, что когда я вызываю ResetData или LoadData, которые заменяют Data, привязки не обновляются, а MainWindow отображает старые данные.
Может кто-нибудь сказать мне, что я здесь делаю не так?
РЕДАКТИРОВАТЬ: я обнаружил, что если я создам новое свойство в своем MainWindow, вот так:
Значения
public ObservableCollection { получать { вернуть исследование.Data.UserInputsData.SelectedItems.Values; } } И привязывайтесь в XAML, а не в коде:
Затем он обновляется, когда я вызываю ResetData или LoadData. Однако я хочу выполнить привязку кода программной части и не объявлять эти дополнительные свойства в MainWindow, например это свойство Values, которое я объявляю для тестирования. Сможет ли кто-нибудь мне помочь, имея эту обновленную информацию?
РЕДАКТИРОВАТЬ 2:
Я решил эту проблему, реализовав эти две функции:
public static void SetBinding(элемент ItemsControl, выражение Expression) { строковый путь = GetFullReferencePath(выражение); Привязка привязка = новый Binding () {Путь = новый PropertyPath (путь) }; item.SetBinding(ItemsControl.ItemsSourceProperty, привязка); } общедоступная статическая строка GetFullReferencePath(выражение Expression) { варmemberExpression = (MemberExpression)expression.Body; вар стек = новый стек(); в то время как (memberExpression!= ноль) { stack.Push(memberExpression.Member.Name); Выражение-члена = Выражение-члена.Выражение как Выражение-члена; } return string.Join(".", стек); } А затем привязываем мой SelectedItemsListBox следующим образом:
SetBinding(SelectedItemsListBox, () => Study.Data.UserInputsData.SelectedItems.Values); Хотя это работает, это решение кажется очень странным, и я не могу поверить, что мне следует это делать. Может ли кто-нибудь предложить более простой способ?
Мобильная версия