数据绑定基础笔记

数据绑定是 WPF 里和传统 WinForms 差别最大的地方。WinForms 习惯是在事件里手动给控件赋值,WPF 则是把控件属性和数据对象的属性关联起来,数据变了界面自动更新。

1. 最基本的写法

<TextBox Text="{Binding UserName}" />

这里 UserName 是从当前元素的 DataContext 上找的属性。DataContext 会沿着可视树向下继承,所以通常在窗口或某个容器上设置一次即可:

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainViewModel();
}

2. 绑定模式

  • OneWay:数据 → 界面,只读展示用,例如 TextBlock。
  • TwoWay:数据 ↔ 界面,输入控件用,例如 TextBox、CheckBox。
  • OneTime:只在初始化时取一次值,之后不再更新。
  • OneWayToSource:界面 → 数据,用得比较少。

大部分控件都有合理的默认模式,TextBox.Text 默认就是 TwoWayTextBlock.Text 默认是 OneWay,一般不需要显式写。

3. 界面不刷新,先查 INotifyPropertyChanged

这是我遇到最多的一个问题:给属性赋了新值,但界面没有任何变化。原因是绑定的数据对象没有通知界面“我变了”。数据类需要实现 INotifyPropertyChanged

public class MainViewModel : INotifyPropertyChanged
{
    private string _userName;

    public string UserName
    {
        get => _userName;
        set
        {
            if (_userName == value) return;
            _userName = value;
            OnPropertyChanged(nameof(UserName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

注意:属性必须是 public 属性,字段和私有属性都绑不上。另外集合发生增删时,要用 ObservableCollection<T> 而不是 List<T>,否则列表界面同样不会更新。

4. 几个常用的绑定参数

  • StringFormat:格式化显示,例如 {Binding Price, StringFormat=C} 按货币格式输出。
  • Converter:需要类型转换或条件判断时,实现 IValueConverter
  • UpdateSourceTrigger=PropertyChanged:让 TextBox 每次按键都回写数据,默认是失去焦点时才回写。
  • ElementName / RelativeSource:绑定到另一个控件或父级元素,而不是 DataContext。

5. 调试技巧

绑定写错时不会抛异常,只是界面上什么都不显示,比较难查。两个办法:一是看 Visual Studio 的“输出”窗口,绑定失败会打印 System.Windows.Data Error 的提示,里面会写清楚在哪个对象上找不到哪个属性;二是给绑定加上 PresentationTraceSources.TraceLevel=High,输出更详细的过程。

« 返回笔记列表