Какие требования к данным для реализации двусторонней привязки в WPF
Что проверяют
Понимаете ли вы, что двусторонняя привязка ставит условия обеим сторонам: свойству элемента и объекту-источнику. Следом обычно спрашивают, почему значение из TextBox не доходит до модели, пока фокус не уйдёт с поля.
Как отвечать
Разберите требования по сторонам:
- цель: всегда
DependencyPropertyэлемента. У части свойств двусторонний режим включён по умолчанию через метаданные (TextBox.Text,IsChecked,SelectedItem), у остальныхModeпо умолчаниюOneWay, иTwoWayпишут явно; - источник: публичное свойство, не поле. Для
TwoWayнужен доступныйset, на свойстве только для чтения привязка броситInvalidOperationException; - уведомления: чтобы изменения из кода доходили до интерфейса, источник реализует
INotifyPropertyChangedи поднимаетPropertyChangedс именем свойства, удобно через[CallerMemberName]илиnameof. Либо источник самDependencyObjectс зависимыми свойствами; - коллекции:
ObservableCollection<T>реализуетINotifyCollectionChangedи сообщает только о добавлении, удалении и перемещении элементов. Изменения внутри элемента видны, лишь если элемент сам реализуетINotifyPropertyChanged; - момент записи:
UpdateSourceTriggerуTextBox.Textпо умолчаниюLostFocus, для записи на каждый символ нуженPropertyChanged; - конвертер: при
TwoWayуIValueConverterдолжен работатьConvertBack.
Для валидации назовите INotifyDataErrorInfo (асинхронная, несколько ошибок на свойство) и ValidationRule на самой привязке. Шаблонный код снимает CommunityToolkit.Mvvm: атрибут [ObservableProperty] генерирует свойство с уведомлением.
Где спотыкаются
Делают свойство модели полем или internal. Привязка молча не работает, ошибка видна только в окне Output или в окне ошибок привязки XAML.
Меняют ObservableCollection из фонового потока и получают исключение. Нужно вернуться в поток интерфейса через Dispatcher или включить BindingOperations.EnableCollectionSynchronization.
Поднимают PropertyChanged с опечаткой в строковом имени или забывают про вычисляемые свойства, зависящие от изменённого. Интерфейс тогда показывает устаревшее значение без всяких ошибок.