WPF绑定由简到繁深入笔记

一、什么是绑定(一句话理解)

  1. 最简单的绑定:把 TextBlock 绑定到 TextBox

  2. 绑定的核心组成(SourcePathTarget

  3. 绑定方向(Mode:OneWay / TwoWay / OneTime)

  4. 通知机制(INotifyPropertyChanged 是灵魂)

  5. 绑定到其他元素 / 相对资源(ElementNameRelativeSource

  6. 绑定集合:ListBox / DataGrid 绑定到 ObservableCollection<T>

  7. 值转换器(IValueConverter

WPF 绑定 = 让界面(View)和一个数据对象(ViewModel / Model)自动保持同步,不用写大量 xx.Text = yy 这样的代码。

  • 数据变了 → 界面自动变

  • 界面改了(比如 TextBox 输入) → 数据自动变

二、简单案例:

  • 一个 TextBox 输入名字

  • 一个 TextBlock 实时显示相同内容

cs 复制代码
<StackPanel Margin="20">
    <TextBox x:Name="NameInput" Width="200" Margin="5"/>
    <TextBlock Text="{Binding Text, ElementName=NameInput}" Margin="5"/>
</StackPanel>

效果

你往 TextBox 打字 → TextBlock 实时变化

解释

  • {Binding Text, ElementName=NameInput}

    • TextTextBox 的属性

    • ElementName:告诉绑定去界面上的哪个控件找

✅ 这是最简单的 控件→控件绑定

三、绑定的核心组成

角色 说明 例子
目标(Target) UI 控件属性 TextBlock.Text
源(Source) 数据来源 一个 C# 对象、另一个控件、静态资源
路径(Path) 源对象的具体属性 UserName
模式(Mode) 数据传输方向 TwoWay / OneWay
cs 复制代码
<TextBox Text="{Binding Path=UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

四、绑定方向(重要)

Mode 含义 场景
OneWay 数据→界面 只读展示
TwoWay 数据⇄界面 表单编辑
OneTime 只绑一次 静态标签
OneWayToSource 界面→数据 罕见

五、通知机制(INotifyPropertyChanged)

这是 WPF 绑定的灵魂。

场景

你用代码改了数据,界面不更新

👉 因为没有告诉界面"我变了"

错误写法(无通知)

cs 复制代码
public class Student
{
    public string Name { get; set; }
}

正确写法(支持通知)

cs 复制代码
using System.ComponentModel;

public class Student : INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            OnPropertyChanged(nameof(Name));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string prop) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}

界面使用(DataContext 是核心)

cs 复制代码
// 窗口构造函数中
public MainWindow()
{
    InitializeComponent();
    DataContext = new Student { Name = "张三" };
}
XML 复制代码
xml

<TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

✅ 现在 TextBox 输入

✅ C# 里 student.Name = "李四"

👉 界面都会同步

UpdateSourceTrigger=PropertyChanged

效果

你每敲一个字母 → TextBlock 立刻跟着变一个字

数据流向

你按 a → 界面立刻把 a 写回 ViewModel.UserNameTextBlock 收到变化通知 → 显示 a

默认值(LostFocus)→ 失去焦点才更新

UpdateSourceTrigger 比喻
PropertyChanged 微信实时聊天:你每打一个字,对方立刻看到
LostFocus(默认) 发邮件:你写好整封信,点击"发送"后才发出
什么时候更新数据源? 典型场景
PropertyChanged 属性每次变化(每按一个键、每动一下滑块) 实时搜索、实时计算、实时预览
LostFocus(默认) 控件失去焦点(按Tab、点别处) 表单提交、设置页面
Explicit 手动调用 BindingExpression.UpdateSource() 复杂验证、批量保存

六、绑定到其他元素 / 相对资源

1. 绑定到另一个控件(滑块→文字)

XML 复制代码
<Slider x:Name="VolumeSlider" Minimum="0" Maximum="100"/>
<TextBlock Text="{Binding Value, ElementName=VolumeSlider}"/>

2. 绑定到自身窗口属性

XML 复制代码
<TextBlock Text="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}"/>

3. 绑定到静态资源

XML 复制代码
<Window.Resources>
    <local:Student x:Key="DefaultStudent" Name="王五"/>
</Window.Resources>

<TextBlock Text="{Binding Name, Source={StaticResource DefaultStudent}}"/>

七、绑定集合(最常用)

场景

用户列表显示在 ListBox / DataGrid

增删改自动刷新界面

✅ 必须用 ObservableCollection<T>

cs 复制代码
public class MainViewModel
{
    public ObservableCollection<Student> Students { get; set; }
        = new ObservableCollection<Student>();

    public MainViewModel()
    {
        Students.Add(new Student { Name = "张三" });
        Students.Add(new Student { Name = "李四" });
    }
}

XAML

XML 复制代码
<ListBox ItemsSource="{Binding Students}" DisplayMemberPath="Name"/>
<DataGrid ItemsSource="{Binding Students}" AutoGenerateColumns="True"/>

✅ 增删改都会自动更新界面

八、值转换器(IValueConverter)

场景

  • 性别 0/1 → "男"/"女"

  • 金额 int → "¥100.00"

  • bool → Visibility

示例:bool → 是否显示红字

Converter 代码
cs 复制代码
public class BoolToRedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? "Red" : "Black";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
XAML 使用
XML 复制代码
<Window.Resources>
    <local:BoolToRedConverter x:Key="BoolToRed"/>
</Window.Resources>

<TextBlock Text="危险操作"
           Foreground="{Binding IsDangerous, Converter={StaticResource BoolToRed}}"/>
cs 复制代码
using System;
using System.Windows.Data;
using System.Windows.Media;

public class BoolToRedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // value 就是 Binding 传来的 IsDangerous 的值(true/false)
        bool isDangerous = (bool)value;
        
        if (isDangerous)
            return new SolidColorBrush(Colors.Red);  // 危险 → 红色
        else
            return new SolidColorBrush(Colors.Black); // 安全 → 黑色
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException(); // 这个例子不需要反向转换
    }
}
复制代码
<TextBlock Foreground="{Binding IsDangerous, Converter=...}" />
                ↑                ↑
                |                |
            目标属性          源属性(路径)

DataContext 指向的对象

找到 IsDangerous 属性

取出值(true / false)

传给 Converter(BoolToRedConverter)

Converter 返回 Brush(红色/黑色)

赋值给 TextBlock.Foreground

九、常见坑与调试技巧(必看)

🔥 坑1:DataContext 没设置

  • 界面没有任何数据

  • 检查this.DataContext = new XXX()

🔥 坑2:属性是字段

csharp

复制代码
// ❌ 不行
public string Name;

🔥 坑3:集合变了但没刷新

  • List<T> → 改成 ObservableCollection<T>

🔥 坑4:对象内部属性变了界面不变

  • 类必须实现 INotifyPropertyChanged

🔥 坑5:绑定路径写错(大小写)

  • Path 区分大小写

最后总结一句话

WPF 绑定 = 搞清楚三件事:数据源是谁、目标控件是谁、数据变化怎么通知。

你不需要一次记住所有细节,但下面 4 个点是必须反复写才能理解的:

  1. DataContext

  2. INotifyPropertyChanged

  3. ObservableCollection<T>

  4. ModeUpdateSourceTrigger

复制代码
相关推荐
问心无愧05131 小时前
ctf show web 入门46
android·前端·笔记
栈溢出了1 小时前
GNN 学习笔记:edge_index 与 W 参数矩阵
人工智能·笔记·神经网络·学习
九思十安1 小时前
HNU2026-计算机系统-笔记 7 浮点数
笔记
九思十安1 小时前
HNU2026-计算机系统-笔记 4 汇编初步
汇编·笔记
FakeEnd2 小时前
Unity开发笔记6
笔记·unity·游戏引擎
东方.既白2 小时前
WPF炫酷界面DEMO
wpf
海盗12342 小时前
WPF中OxyPlot不同图表的使用
wpf
Hello_Embed2 小时前
libmodbus 源码分析
笔记·stm32·单片机·嵌入式·ai编程
05候补工程师2 小时前
【408考研】数据结构核心笔记:单链表与栈操作精髓总结
数据结构·笔记·考研·链表·c#