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 通知代码,减少样板代码。

相关推荐
武藤一雄15 小时前
.NET 中常见计时器大全
microsoft·微软·c#·.net·wpf·.netcore
MarkHD19 小时前
车辆TBOX科普 第70次 AUTOSAR Adaptive、容器化与云原生的融合革命
云原生·wpf
极客智造19 小时前
WPF Behavior 实战:自定义 InvokeCommandAction 实现事件与命令解耦
wpf
L、21820 小时前
Flutter 与 OpenHarmony 深度集成:构建分布式多端协同应用
分布式·flutter·wpf
布伦鸽20 小时前
C# WPF -MaterialDesignTheme 找不到资源“xxx“问题记录
开发语言·c#·wpf
小二·1 天前
MyBatis基础入门《十五》分布式事务实战:Seata + MyBatis 实现跨服务数据一致性
分布式·wpf·mybatis
helloworddm2 天前
UnregisterManyAsync
wpf
军训猫猫头2 天前
3.NModbus4 长距离多设备超时 C# + WPF 完整示例
c#·.net·wpf·modbus
Aevget2 天前
DevExpress WPF中文教程:Data Grid - 如何绑定到有限制的自定义服务(一)?
ui·.net·wpf·devexpress·ui开发·wpf界面控件
Macbethad2 天前
半导体设备工厂自动化软件技术方案
wpf·智能硬件