WPF绑定需显式设Mode=TwoWay且源属性实现INotifyPropertyChanged,否则UI与数据不同步;集合绑定须用ObservableCollection<T>并确保中间对象非null。

WPF 的 Binding 默认不是双向的,必须显式设 Mode=TwoWay,且绑定源属性得实现 INotifyPropertyChanged,否则 UI 改了,数据不更新,或者数据改了,UI 不刷新。
为什么改了属性值,界面没反应?
常见现象:给 TextBox.Text 绑定一个普通字段或自动属性(如 public string Name { get; set; }),在代码里改了 Name,UI 一点不动。
原因很简单:WPF 不知道这个属性“变了”。它只监听实现了 INotifyPropertyChanged 接口的对象发出的 PropertyChanged 事件。
- 必须让数据类实现
INotifyPropertyChanged - 属性 setter 里要手动触发
PropertyChanged事件(别漏掉OnPropertyChanged(nameof(Name))) - 如果用的是
record或只读属性,根本不会触发通知——它们天生不可变 - 直接改后台字段(比如
_name = "xxx")而没走 setter,也不会触发
TextBox 输入后,源属性还是旧值?
典型表现:用户在 TextBox 里输完内容,按按钮读 MyModel.Name,发现还是初始值。
这是因为 TextBox.Text 的默认 Binding.Mode 是 OneWay(从数据到 UI),不是 TwoWay。WPF 不会主动把输入结果写回源属性。
- 必须显式写
Mode=TwoWay:{Binding Name, Mode=TwoWay} - 某些控件(如
CheckBox.IsChecked)默认是TwoWay,但TextBox.Text、TextBlock.Text都不是 - 如果源属性 setter 抛异常(比如验证失败),绑定会静默失败,UI 看不出问题,但值没更新成功
- 更新时机默认是
LostFocus,想输一个字就更新,得加UpdateSourceTrigger=PropertyChanged
用 ObservableCollection<T> 绑定列表,增删项 UI 却不更新?
现象:往 ItemsSource 绑定的 List<string> 里 Add() 一项,界面毫无反应;换成 ObservableCollection<string> 就好了。
关键点不在“集合类型”,而在“是否通知变更”。ObservableCollection<T> 内部实现了 INotifyCollectionChanged,WPF 的 ItemsControl(如 ListBox)只认这个接口。
-
List<T>、T[]、IEnumerable<T>都不行,它们不发集合变更通知 - 即使用了
ObservableCollection<T>,如果直接替换整个集合(如Items = new ObservableCollection<string>();),旧引用断了,UI 也收不到通知——得用Clear()+AddRange()或重用同一实例 - 集合里存的对象,如果自身属性要响应式更新,还得各自实现
INotifyPropertyChanged
最容易被忽略的是:绑定路径里的中间对象如果是 null,整个绑定就静默失效,既不报错也不更新。调试时先确认 DataContext 和每级属性都不为 null,再查通知逻辑和模式设置。


















