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
决定绑定模式。