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

相关推荐
wuty00715 小时前
记录一下 WPF进程 SendMessage 发送窗口消息进行进程间通信,存在进程权限无法接受消息的问题
wpf·进程间通信·sendmessage·进程权限
c#上位机1 天前
wpf之ToggleButton控件
c#·wpf
浪扼飞舟1 天前
WPF用户控件和依赖属性
wpf
c#上位机2 天前
wpf之MVVM中只读属性更新界面
c#·wpf·mvvm
就是有点傻2 天前
WPF自定义控件之环形进度条
wpf
He BianGu2 天前
【笔记】WPF中如何的动态设置DataGridTextColumn是否显示
笔记·wpf
Pota-to成长日记2 天前
Redisson 看门狗机制深度解析:分布式锁的守护者
分布式·wpf
为java加瓦2 天前
分布式单例模式在微服务架构中的关键作用与实践
wpf
c#上位机2 天前
wpf之Ellipse控件
wpf