WPF 的数据绑定(Data Binding)是其核心特性之一,它使得视图(View)可以直接绑定到数据源(Model 或 ViewModel),从而实现松耦合。以下是 WPF 数据绑定的详解,包括基本概念、绑定模式、绑定路径、更新触发、转换器等。
1. 数据绑定的基本概念
数据绑定是指将 UI 元素的属性(如 Text 或 Value)与数据源中的属性关联起来,使它们之间能够自动同步更新。
绑定的基本结构
<TextBox Text="{Binding Path=PropertyName}" />
- Binding:声明绑定。
- Path:数据源中的属性路径。
2. 数据绑定的关键要素
(1) 绑定的目标和源
-
目标(Target):UI 元素的属性(如
Text、Width、Height)。 -
源(Source):数据源(如
ViewModel、Model、静态资源)。
(2) 数据上下文(DataContext)
数据上下文是绑定源的根。通常绑定时使用 DataContext 指定数据源。
// 在代码中设置 DataContext
this.DataContext = new MyViewModel();
3. 绑定模式
WPF 支持以下四种绑定模式:
(1) OneWay
- 数据从源更新到目标,目标属性的变化不会反过来更新源。
- 用于静态数据或只读数据。
<TextBlock Text="{Binding Path=Name, Mode=OneWay}" />
(2) TwoWay
- 数据源和目标属性之间双向绑定。
- 用于需要用户输入的场景(如表单)。
<TextBox Text="{Binding Path=Name, Mode=TwoWay}" />
(3) OneTime
- 数据在绑定时初始化一次,之后不再更新。
- 用于只需要加载时设置值的情况。
<TextBlock Text="{Binding Path=Name, Mode=OneTime}" />
(4) OneWayToSource
- 数据从目标更新到源,源的变化不会反映到目标。
<TextBox Text="{Binding Path=Name, Mode=OneWayToSource}" />
4. 数据更新触发(UpdateSourceTrigger)
控制数据源更新的时机:
-
Default:默认值,
TextBox.Text默认在控件失去焦点时更新。 - PropertyChanged:值改变时立即更新数据源。
-
Explicit:手动调用
BindingExpression.UpdateSource()触发更新。
<TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
5. 绑定路径(Path)
Path 是绑定源中属性的访问路径。
简单属性
直接绑定到一个属性:
<TextBlock Text="{Binding Path=Name}" />
嵌套属性
绑定到嵌套对象的属性:
<TextBlock Text="{Binding Path=Address.City}" />
索引器
绑定集合的索引器:
<TextBlock Text="{Binding Path=Items[0]}" />
附加属性
绑定附加属性:
<TextBlock Text="{Binding Path=(Grid.Row)}" />
6. 绑定的源(Source)
(1) 相对绑定(RelativeSource)
绑定到另一个 UI 元素或控件。
<TextBox Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=Self}}" />
(2) 静态资源(StaticResource 或 DynamicResource)
绑定到静态或动态资源。
<TextBox Text="{Binding Source={StaticResource MyData}}" />
(3) 静态类(x:Static)
绑定到静态属性。
<TextBlock Text="{Binding Source={x:Static local:MyStaticClass.MyStaticProperty}}" />
(4) 数据上下文(DataContext)
通常直接绑定到设置在 DataContext 中的属性:
this.DataContext = new MyViewModel();
7. 绑定转换器(IValueConverter)
用于在绑定过程中转换数据类型或值。
实现自定义转换器
using System;
using System.Globalization;
using System.Windows.Data;
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (Visibility)value == Visibility.Visible;
}
}
使用转换器
<Window.Resources>
<local:BooleanToVisibilityConverter x:Key="BoolToVisibility" />
</Window.Resources>
<TextBlock Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibility}}" />
8. 绑定验证
WPF 提供验证机制以确保绑定值的有效性。
绑定验证规则
实现 ValidationRule 类:
public class NumberValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
if (int.TryParse(value as string, out int result))
{
return ValidationResult.ValidResult;
}
return new ValidationResult(false, "Not a valid number");
}
}
在 XAML 中使用验证规则
<TextBox>
<TextBox.Text>
<Binding Path="Number" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:NumberValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
9. 绑定集合(ItemsControl)
WPF 支持绑定集合到控件如 ListBox、ComboBox。
示例:绑定到集合
<ListBox ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
集合变更通知
使用 ObservableCollection 确保集合的动态更新:
public ObservableCollection<Item> Items { get; set; } = new ObservableCollection<Item>();
10. 多重绑定(MultiBinding)
将多个绑定值组合在一起。
定义多重绑定
<Window.Resources>
<local:MultiValueConverter x:Key="MyMultiConverter" />
</Window.Resources>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource MyMultiConverter}">
<Binding Path="FirstName" />
<Binding Path="LastName" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
实现 IMultiValueConverter
public class MultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return $"{values[0]} {values[1]}";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return value.ToString().Split(' ');
}
}
总结
-
绑定模式:选择合适的绑定模式(如
OneWay、TwoWay)。 -
更新触发:根据需求配置
UpdateSourceTrigger。 -
数据上下文:合理设置
DataContext,避免重复绑定源。 -
转换器:在数据类型或值需要转换时使用
IValueConverter。 - 验证:使用验证规则确保输入合法。
-
集合绑定:动态数据列表推荐使用
ObservableCollection。
通过掌握这些技术,WPF 数据绑定可以极大提升 UI 开发效率,同时保持代码的可维护性和可扩展性。