WPF Binding 绑定 超详细详解

WPF Binding(数据绑定) 是 MVVM 模式的核心,也是 WPF 最强大的功能之一。它的作用是:把 UI 控件的属性 和 数据源(变量 / 对象)自动关联,一方变化,另一方自动同步,不用手动写代码赋值。

我会用最通俗、最完整、可直接上手的方式给你讲透,包含:原理、语法、模式、转换器、通知、命令、常见问题。


一、Binding 到底是什么?

一句话:Binding = 桥梁 连接 目标(Target:UI 控件属性) ←→ 源(Source:后台数据)

例如:TextBox.Text ← Binding → string Name

你改界面,后台自动变;你改后台,界面自动变。


二、Binding 四大核心组成

任何一个绑定都必须包含这 4 部分:

  1. Binding Target(绑定目标) 必须是 **依赖属性(Dependency Property)**如:Text、Width、IsChecked、ItemsSource、Visibility 等

  2. **Binding Source(绑定源)**可以是:普通变量、类实例、集合、父控件、自身、资源

  3. Binding Path(绑定路径) 要绑定源的哪个属性

  4. **Binding Mode(绑定模式)**数据流向:单向 / 双向 / 只读一次等


三、最基础的绑定语法(XAML)

1. 标准写法

复制代码
<TextBox Text="{Binding 路径, Mode=模式, ...}" />

单向绑定

复制代码
<CheckBox x:Name="chb_inspectAll" Margin="20,0,0,0" Content="inspect all" IsChecked="{Binding SelectRecipe.IsFullInspect, Mode=OneWay}" />

2. 最简单示例

复制代码
<TextBox Text="{Binding UserName}" />

表示:Text 属性绑定到当前数据源的 UserName 属性。


四、绑定模式(Binding Mode)必考 / 必用

这是 WPF 面试高频题,也是开发必须懂的。

模式 说明 常用控件
TwoWay(默认) 双向同步:UI 变→数据源变,数据源变→UI 变 TextBox、CheckBox
OneWay 单向:数据源变→UI 变 TextBlock、ProgressBar
OneWayToSource 反向:UI 变→数据源变 极少用
OneTime 只初始化一次,之后不同步 一次性显示数据
Default 根据控件自动决定 文本框双向,文本块单向

最常用:TwoWay / OneWay


五、数据源来源(Source)6 种最常用写法

1. 绑定到自身(RelativeSource Self)

控件自己的属性绑定给自己的另一个属性:

复制代码
<Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}" />

2. 绑定到父控件(AncestorType)

复制代码
Text="{Binding DataContext.Title, RelativeSource={RelativeSource AncestorType=Window}}"

3. 绑定到元素名(ElementName)

复制代码
<TextBox x:Name="input" />
<TextBlock Text="{Binding Text, ElementName=input}" />

4. 绑定到静态资源(StaticResource)

复制代码
Text="{Binding Name, Source={StaticResource MyViewModel}}"

5. 绑定到静态属性(x:Static)

复制代码
Text="{Binding Source={x:Static sys:DateTime.Now}}"

6. 绑定到 DataContext(最常用!MVVM 标配)

复制代码
Text="{Binding UserName}"

DataContext 是传递性的,子控件自动继承父控件数据源。


六、必须实现:数据源变化通知 INotifyPropertyChanged

如果不实现这个接口,数据源变了,UI 不会自动更新!

这是 MVVM 最基础的基类:

复制代码
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

使用:

复制代码
public class MainViewModel : ViewModelBase
{
    private string _userName;
    public string UserName
    {
        get => _userName;
        set => SetProperty(ref _userName, value);
    }
}

七、集合绑定:ObservableCollection

普通 List<T> 增删数据 UI 不更新,必须用:

复制代码
public ObservableCollection<string> Items { get; set; } = new ObservableCollection<string>();

八、值转换器(IValueConverter)

当数据源类型和 UI 属性类型不匹配时使用,例如:

  • bool ↔ Visibility
  • string ↔ 颜色
  • 数字 ↔ 格式化文本

示例:Bool 转 Visibility

复制代码
public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, ...)
    {
        return (bool)value ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, ...)
    {
        return (Visibility)value == Visibility.Visible;
    }
}

使用:

复制代码
<Button Visibility="{Binding IsShow, Converter={StaticResource BoolToVis}}" />

九、绑定校验(ValidationRules)

输入不符合规则时显示红框并提示:

复制代码
<TextBox>
    <TextBox.Text>
        <Binding Path="Age">
            <Binding.ValidationRules>
                <ExceptionValidationRule/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

十、字符串格式化(StringFormat)

复制代码
Text="{Binding Price, StringFormat={}{0:C}}"  <!-- 货币格式 -->
Text="{Binding Date, StringFormat=yyyy-MM-dd}"
Text="{Binding Name, StringFormat=欢迎, {0}}"

十一、常用高级特性

1. FallBackValue

绑定失败时显示的默认值

复制代码
Text="{Binding Age, FallbackValue=未知}"

2. TargetNullValue

数据源为 null 时显示的值

复制代码
Text="{Binding Description, TargetNullValue=暂无描述}"

3. UpdateSourceTrigger

什么时候把 UI 的值同步回数据源:

  • PropertyChanged:输入一个字符同步一次

  • LostFocus:失去焦点同步

  • Explicit:手动调用 UpdateSource ()

    Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"


十二、MVVM 标准完整示例(可直接复制运行)

1. MainWindow.xaml

复制代码
<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Binding Demo" Height="300" Width="500">
    <StackPanel Margin="20">
        <TextBox Text="{Binding UserName, Mode=TwoWay}" FontSize="20"/>
        <TextBlock Text="{Binding UserName}" FontSize="20" Margin="0 10"/>
        <Button Content="测试修改" Click="Button_Click"/>
    </StackPanel>
</Window>

2. MainWindow.xaml.cs

复制代码
public MainWindow()
{
    InitializeComponent();
    DataContext = new MainViewModel(); // 设置数据源
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    var vm = DataContext as MainViewModel;
    vm.UserName = "来自后台修改:" + DateTime.Now.Second;
}

3. MainViewModel.cs

复制代码
public class MainViewModel : ViewModelBase
{
    private string _userName = "初始值";
    public string UserName
    {
        get => _userName;
        set => SetProperty(ref _userName, value);
    }
}

运行后你会发现:

  • 输入框修改 → 文本块自动同步
  • 点击按钮后台修改 → 输入框和文本块都自动变

这就是 Binding 的魔力!


总结(最重要的 6 条)

  1. Binding = UI ↔ 数据 自动同步桥梁
  2. 目标必须是依赖属性
  3. 源必须实现 INotifyPropertyChanged 才能通知更新
  4. 集合必须用 ObservableCollection<T>
  5. 常用模式:TwoWay / OneWay
  6. 类型不匹配用 IValueConverter 转换器
相关推荐
时光追逐者1 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 68 期(2026年3.01-3.08)
c#·.net·.netcore
格林威2 小时前
工业相机图像高速存储(C#版):内存映射文件方法,附海康相机C#实战代码!
开发语言·人工智能·数码相机·opencv·计算机视觉·c#·工业相机
郭逍遥3 小时前
[Godot] 沃罗诺伊图生成算法
算法·c#·游戏引擎·godot
格林威3 小时前
工业相机图像高速存储(C#版):先存内存,后批量转存方法,附 Basler 相机实战代码!
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
少控科技3 小时前
C#基础学习 - 中国民族编码资源代码
开发语言·c#
数据知道3 小时前
MongoDB心跳检测与故障转移:自动主从切换的全过程解析
数据库·mongodb·wpf
VAllen4 小时前
ConcurrentNativeQueue<T>:一个使用 .NET 实现的零 GC 压力的无锁 MPSC 原生队列
c#·.net·性能测试·.net core·dotnet·csharp