WPF-绑定

1. 概述

数据绑定是 WPF 中一种强大的机制,用于在数据源和 UI 元素之间建立连接,使得数据的变化能够自动反映在 UI 上,反之亦然。数据绑定简化了 UI 和数据层之间的交互,提高了代码的可维护性和可读性。

2. 绑定类型

WPF 支持多种类型的绑定,主要包括:

  • 单向绑定 (One-Way Binding)
  • 双向绑定 (Two-Way Binding)
  • 单向到源绑定 (One-Way to Source Binding)
  • 一次绑定 (One-Time Binding)
  • 默认绑定
2.1 单向绑定 (One-Way Binding)
  • 描述:数据从数据源流向目标(UI 元素),但不会反向流动。
  • 使用场景:适用于数据源变化需要更新 UI 的情况。
  • 语法:Mode=OneWay
2.2 双向绑定 (Two-Way Binding)
  • 描述:数据可以在数据源和目标之间双向流动。
  • 使用场景:适用于需要双向同步数据的情况,如表单输入。
  • 语法:Mode=TwoWay
2.3 单向到源绑定 (One-Way to Source Binding)
  • 描述:数据从目标流向数据源,但不会反向流动。
  • 使用场景:适用于 UI 元素的变化需要更新数据源的情况。
  • 语法:Mode=OneWayToSource
2.4 一次绑定 (One-Time Binding)
  • 描述:数据从数据源流向目标一次,之后不再更新。
  • 使用场景:适用于初始化时需要设置 UI 元素的值,且不需要后续更新的情况。
  • 语法:Mode=OneTime
2.5 默认绑定
  • 描述:根据目标属性的 DefaultUpdateMode 属性决定绑定模式。
  • 语法:省略 Mode 属性

3. 实现步骤

3.1 创建数据源

数据源可以是任何实现了 INotifyPropertyChanged 接口的对象,以便在属性变化时通知绑定系统。

复制代码
csharp

using System.ComponentModel;

public class Person : INotifyPropertyChanged
{
    private string name;

    public string Name
    {
        get { return name; }
        set
        {
            if (name != value)
            {
                name = value;
                OnPropertyChanged(nameof(Name));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

在 XAML 或代码中设置 DataContext,将数据源与 UI 关联起来。

复制代码
csharp

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new Person { Name = "John Doe" };
    }
}
3.3 创建绑定

在 XAML 中使用 Binding 标记扩展来创建绑定。

复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="200" Margin="0,0,0,10"/>
        <TextBlock Text="{Binding Path=Name}" Width="200"/>
    </StackPanel>
</Window>

4. 示例

4.1 单向绑定示例
复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBlock Text="{Binding Path=Name, Mode=OneWay}" Width="200"/>
    </StackPanel>
</Window>
4.2 双向绑定示例
复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="200" Margin="0,0,0,10"/>
        <TextBlock Text="{Binding Path=Name}" Width="200"/>
    </StackPanel>
</Window>
4.3 单向到源绑定示例
复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBox Text="{Binding Path=Name, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" Width="200" Margin="0,0,0,10"/>
        <TextBlock Text="Type in the TextBox above" Width="200"/>
    </StackPanel>
</Window>
4.4 一次绑定示例
复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBlock Text="{Binding Path=Name, Mode=OneTime}" Width="200"/>
    </StackPanel>
</Window>

5. 高级用法

5.1 转换器 (Converters)

转换器用于在数据绑定过程中转换数据。

复制代码
csharp

using System;
using System.Globalization;
using System.Windows.Data;

public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在 XAML 中使用转换器:

复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resources>
        <local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
    </Window.Resources>
    <StackPanel Margin="10">
        <CheckBox x:Name="chkShowText" Content="Show Text"/>
        <TextBlock Text="This text is visible based on checkbox state" 
                   Visibility="{Binding ElementName=chkShowText, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}"/>
    </StackPanel>
</Window>
5.2 多绑定 (MultiBinding)

多绑定允许将多个源绑定到一个目标属性,并使用转换器处理这些源的值。

复制代码
csharp

using System;
using System.Globalization;
using System.Windows.Data;

public class ConcatenateConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null || values.Length < 2)
            return string.Empty;

        return $"{values[0]} {values[1]}";
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

在 XAML 中使用多绑定:

复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resources>
        <local:ConcatenateConverter x:Key="ConcatenateConverter"/>
    </Window.Resources>
    <StackPanel Margin="10">
        <TextBox x:Name="txtFirstName" Width="200" Margin="0,0,0,10"/>
        <TextBox x:Name="txtLastName" Width="200" Margin="0,0,0,10"/>
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding Converter="{StaticResource ConcatenateConverter}">
                    <Binding ElementName="txtFirstName" Path="Text"/>
                    <Binding ElementName="txtLastName" Path="Text"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </StackPanel>
</Window>
5.3 相对源绑定 (RelativeSource Binding)

相对源绑定允许绑定到相对于当前绑定目标的位置的元素。

复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBox x:Name="txtInput" Width="200" Margin="0,0,0,10"/>
        <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=TextBox}, Path=Text}"/>
    </StackPanel>
</Window>
5.4 元素绑定 (Element Binding)

元素绑定允许绑定到同一窗口或其他容器中的另一个元素。

复制代码
xml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBox x:Name="txtInput" Width="200" Margin="0,0,0,10"/>
        <TextBlock Text="{Binding ElementName=txtInput, Path=Text}"/>
    </StackPanel>
</Window>

6. 总结

  • 单向绑定:数据从数据源流向目标。
  • 双向绑定:数据在数据源和目标之间双向流动。
  • 单向到源绑定:数据从目标流向数据源。
  • 一次绑定:数据从数据源流向目标一次。
  • 默认绑定:根据目标属性的 DefaultUpdateMode 决定绑定模式。
相关推荐
神仙别闹3 分钟前
基于C#+MySQL实现(WinForm)企业设备使用信息管理系统
开发语言·mysql·c#
czhaii15 分钟前
PLC脉冲位置 单片机跟踪读取记录显示
开发语言·c#
溪饱鱼1 小时前
第6章: SEO与交互指标
服务器·前端·microsoft
神仙别闹2 小时前
基于C#+SQL Server开发(WinForm)租房管理系统
数据库·oracle·c#
焚 城3 小时前
.NET8关于ORM的一次思考
后端·.net
bicijinlian3 小时前
.Net HttpClient 管理客户端(初始化与生命周期管理)
c#·.net·httpclient·.net httpclient·c# http
一个人的博客@你3 小时前
C# 通用OCR识别
图像处理·c#·ocr·图像识别·文字提取
老胖闲聊5 小时前
C# 注册表操作类
开发语言·c#
液态不合群7 小时前
理解 C# 中的各类指针
java·开发语言·c#
可喜~可乐7 小时前
C# SQLite高级功能示例
数据库·sql·sqlite·c#