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 决定绑定模式。
相关推荐
yngsqq2 小时前
netdxf—— CAD c#二次开发之(netDxf 处理 DXF 文件)
java·前端·c#
每日出拳老爷子2 小时前
[WinForms] 如何为 .NET Framework 4.8 窗体程序添加自定义图标
visualstudio·c#·.net
甜甜不吃芥末2 小时前
Windows 应用程序的 UI 框架:WPF、WinUI 3 和 UWP的差异区别
windows·ui·wpf
Yan90182 小时前
.net解析雷达拼图3.0组合反射率产品,并按经纬度裁剪绘制组合反射率图
.net
步、步、为营2 小时前
.net服务器Kestrel配置Nginx作为反向代理
服务器·nginx·.net
专注VB编程开发20年2 小时前
各版本操作系统对.NET支持情况(250707更新)
开发语言·前端·ide·vscode·.net
杰哥技术分享2 小时前
宝塔 php支持sqlserver
microsoft
界面开发小八哥5 小时前
界面组件DevExpress WPF中文教程:Grid - 如何检查节点?
ui·.net·wpf·界面控件·devexpress·ui开发
阿酷tony8 小时前
微软语音合成标记语言SSML文档结构和事件(详细文档和实例)
microsoft·微软语音·ssml文档结构·ssml结构·ssml语音合成
钢铁男儿9 小时前
C#接口实现详解:从理论到实践,掌握面向对象编程的核心技巧
java·前端·c#