为什么数据绑定是 WPF 的灵魂
WPF 把界面和数据解耦的核心就是数据绑定。你不再写「把文本框内容读出来、再写回对象」的样板代码,而是声明「这个控件绑定到这个属性」,剩下的同步交给绑定引擎。理解绑定,就理解了 MVVM 为什么能成立。
绑定是声明式的:你只描述「绑什么」,同步方向和时机由引擎决定。
- Binding 源通常是 ViewModel 的属性。
- Binding 目标是控件的依赖属性。
- 绑定引擎负责两端同步。
绑定模式与 UpdateSourceTrigger
绑定有 OneWay、TwoWay、OneWayToSource 等模式。TwoWay 最常用,但它默认什么时候把改动写回源?由 UpdateSourceTrigger 决定。LostFocus 是默认值,PropertyChanged 才是实时同步——很多人界面不刷新,问题就出在这里。
<TextBox Text="{Binding UserName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
通知:INotifyPropertyChanged
TwoWay 从界面改到源很容易,但从源改到界面,需要源主动通知。ViewModel 实现 INotifyPropertyChanged,属性 setter 里抛 PropertyChanged 事件,绑定引擎收到后刷新界面。这是 MVVM 的地基。
private string _name;
public string Name {
get => _name;
set { _name = value; OnPropertyChanged(); }
}
命令与 CanExecute
按钮点击不写后台代码,而是绑定到一个 ICommand。命令有 Execute 和 CanExecute:CanExecute 返回 false 时按钮自动变灰。这样业务规则(「没填完不能提交」)就能直接驱动界面状态。
值转换器与相对绑定
源是布尔、界面要显示颜色,中间需要 IValueConverter。把 true 转成「绿 / 红」 Brush,一行转换器搞定,避免在 ViewModel 里塞界面类型。此外 RelativeSource 可以绑定到自身或上游控件的属性,做一些自引用样式很方便。
- Converter把业务值翻译成界面呈现。
- RelativeSource自引用或找上一级控件。
- 延迟绑定大批量数据优先用虚拟化。
MVVM 的常见坑
最常见的坑是:ViewModel 里偷偷 new 了具体控件,或者把 DataContext 扔给后台逻辑直接改 UI。一旦界面和逻辑纠缠,MVVM 的可测试性就没了。坚持「ViewModel 只持有状态和命令、不引用控件」这条线。
小结与延伸阅读
数据绑定是 WPF 的发动机,MVVM 是围绕它搭的架构。把绑定模式、通知、命令、转换器这四件事用熟,WPF 项目就能既清爽又好测。
- WPF 入门读《WPF 桌面应用实战:MVVM 架构》。
- 桌面新方向读《WinUI 3 桌面应用开发入门》。
- 性能优化读《.NET 性能优化与内存管理实战》。