WPF 之数据绑定一(Data Binding)

在 WPF 中,绑定目标跟随绑定源变化的机制主要依赖于 ​​数据绑定(Data Binding)​ ​ 和 ​​INotifyPropertyChanged 接口​ ​ 或 ​​依赖属性(Dependency Property)​​ 的特性。下面详细解释这一机制的实现方式:


一、绑定基础

在 WPF 中,数据绑定通常是将一个 UI 控件的某个属性(称为 ​​绑定目标,Target​ ​,如 TextBox.Text)与某个数据对象的某个属性(称为 ​​绑定源,Source​ ​,如 ViewModel 中的 UserName属性)关联起来。

绑定是通过 XAML 或代码中设置 Binding对象来完成的,例如:

复制代码
<TextBox Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

这里的绑定目标属性 是 TextBox.Text,绑定源属性是 ViewModel 中的 UserName。

二、绑定模式(Binding Mode)

绑定模式决定了数据流动的方向,常用的有:

  • ​​OneWay​​:源 → 目标(默认)。源变化会更新目标,但目标变化不会影响源。

  • ​​TwoWay​​:源 ↔ 目标。源和目标任意一方变化都会同步到另一方。

  • ​​OneWayToSource​​:目标 → 源。

  • ​​OneTime​​:仅在绑定初始化时更新一次。

要实现"绑定目标跟随绑定源变化",通常需要使用 ​​TwoWay 或 OneWay 模式​​。

三、绑定源如何通知目标其值已改变?

这是关键点:​​WPF 绑定系统要能感知到绑定源的数据发生了变化,才能自动更新目标 UI。​​

方法 1:绑定源实现 INotifyPropertyChanged 接口(推荐)

如果你的绑定源是一个 ​​CLR 对象(非依赖对象)​ ​,比如 ViewModel,那么它需要实现 INotifyPropertyChanged接口,并在属性 setter 中触发 PropertyChanged事件,以通知绑定系统该属性的值已经改变。

示例代码:
复制代码
using System.ComponentModel;

public class ViewModel : INotifyPropertyChanged
{
    private string _userName;
    public string UserName
    {
        get => _userName;
        set
        {
            if (_userName != value)
            {
                _userName = value;
                OnPropertyChanged(nameof(UserName)); // 通知绑定系统属性已更改
            }
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

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

然后在 XAML 中绑定:

复制代码
<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>

<TextBox Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{Binding UserName, Mode=OneWay}" />

这样当 ViewModel 中的 UserName发生变化时,所有绑定了该属性的 UI 元素(如 TextBox、Label)都会 ​​自动更新显示​​。

方法 2:绑定源是 DependencyObject,且绑定属性是 DependencyProperty

如果绑定源本身是一个 ​​WPF 控件或者继承自 DependencyObject 的自定义类​ ​,并且你要绑定的属性是 ​​DependencyProperty​ ​,那么 WPF 本身就内置了属性变更通知机制,无需手动实现 INotifyPropertyChanged。

例如,TextBox.Text就是一个 DependencyProperty,当它的值发生变化时,绑定系统会自动捕获并更新目标。

四、UpdateSourceTrigger

此属性控制 ​​源属性何时从目标更新​​,常用值有:

  • ​​Default​​:通常为 LostFocus(如 TextBox.Text)

  • ​​PropertyChanged​​:每当目标属性变化就更新源(如实时搜索)

  • ​​LostFocus​​:失去焦点时更新

  • ​​Explicit​​:需手动调用 UpdateSource()

例如,如果你希望用户在输入时实时更新 ViewModel 中的属性,可以设置:

复制代码
Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

五、总结:绑定目标如何跟随绑定源变化?

条件 是否自动更新目标
绑定模式为 TwoWay / OneWay ✅ 是
绑定源是 CLR 对象(非 DependencyObject) 必须实现 INotifyPropertyChanged,并在属性更改时触发 PropertyChanged事件 ✅
绑定源是 DependencyObject,绑定属性是 DependencyProperty ✅ 自动支持变更通知
没有实现 INotifyPropertyChanged 或不是依赖属性 ❌ 不会自动更新,UI 不会反映源的变化

六、附加建议

  • 尽量使用 MVVM 模式,将业务逻辑和状态放在 ViewModel 中,通过绑定与 View 交互。

  • 使用 INotifyPropertyChanged是实现响应式 UI 的关键。

  • 可使用工具如 Fody.PropertyChanged自动为属性添加 PropertyChanged 通知代码,减少样板代码。

相关推荐
samble5 小时前
从零搭建灌装监控系统(十三):报警系统设计,生命周期与通知
c#·wpf·mvvm·modbus·工业控制
samble1 天前
从零搭建灌装监控系统(十二):配置系统,原子写入与容错
c#·wpf·mvvm·modbus·工业控制
蜗牛互联网3 天前
OLMo-core 3的token gerrymandering提醒:MoE路由要按时间窗验收
java·人工智能·wpf
LateFrames4 天前
WPF 升级选型:用 .NET 8 还是 .NET 10
.net·wpf·.net8·.net10
samble4 天前
从零搭建灌装监控系统(十):生产追溯,条码触发自动记录
c#·wpf·mvvm·modbus·工业控制
SamChan906 天前
PDF页面旋转与CropBox陷阱:译文回填位置总是错位的根因实测
python·ai·pdf·wpf
SamChan907 天前
PDF翻译时页眉页脚总在捣乱?跨页重复文本块的检测与过滤实测
人工智能·python·ai·pdf·wpf
samble14 天前
从零搭建灌装监控系统(四):深色主题与样式系统,ResourceDictionary 统一管理
c#·wpf·mvvm·样式·工业控制
_Jonas14 天前
.net framework开发环境正式环境配置文件的切换
.net·wpf
dalong1016 天前
WPF:Modbus 状态监控
wpf·modbus