什么是Data Binding(数据绑定)?
Data Binding是WPF中的核心机制,它建立了UI元素(视图)与数据对象(模型/视图模型)之间的连接通道,实现了数据的自动同步。当数据发生变化时,UI自动更新;当用户修改UI时,数据也相应更新。
Data Binding的核心概念
绑定源(Source):提供数据的对象
绑定目标(Target):显示数据的UI元素(必须是DependencyProperty)
绑定路径(Path):指定绑定源中的属性
绑定模式(Binding Mode):
OneWay:源→目标
TwoWay:源⇄目标
OneWayToSource:目标→源
OneTime:仅初始化时绑定一次
基本语法
<TextBox Text="{Binding Path=UserName, Mode=TwoWay}" />
经典应用示例
示例1:简单属性绑定
// 数据类
public class Person : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
<!-- XAML绑定 -->
<Window.DataContext>
<local:Person Name="张三"/>
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Name, Mode=TwoWay}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
示例2:集合绑定(ListBox/ListView)
public class ProductList : ObservableCollection<Product>
{
public ProductList()
{
Add(new Product() { Name="笔记本", Price=5999});
Add(new Product() { Name="手机", Price=3999});
}
}
public class Product : INotifyPropertyChanged
{
// 实现INotifyPropertyChanged...
public string Name { get; set; }
public decimal Price { get; set; }
}
<ListBox ItemsSource="{Binding}" DisplayMemberPath="Name"/>
示例3:主从绑定(Master-Detail)
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<!-- 主表 -->
<ListBox ItemsSource="{Binding Employees}"
DisplayMemberPath="LastName"
SelectedItem="{Binding SelectedEmployee}"/>
<!-- 从表详情 -->
<StackPanel Grid.Column="1" DataContext="{Binding SelectedEmployee}">
<TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
<TextBox Text="{Binding LastName, Mode=TwoWay}"/>
</StackPanel>
</Grid>
示例4:数据转换(ValueConverter)
public class BoolToVisibilityConverter : 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:BoolToVisibilityConverter x:Key="BoolToVisibility"/>
</Window.Resources>
<Button Content="提交" Visibility="{Binding IsValid, Converter={StaticResource BoolToVisibility}}"/>
示例5:命令绑定(Command Binding)
public class RelayCommand : ICommand
{
private Action<object> _execute;
public RelayCommand(Action<object> execute)
{
_execute = execute;
}
public bool CanExecute(object parameter) => true;
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_execute(parameter);
}
}
public class ViewModel
{
public ICommand SaveCommand { get; }
public ViewModel()
{
SaveCommand = new RelayCommand(ExecuteSave);
}
private void ExecuteSave(object param)
{
// 保存逻辑
}
}
<Button Content="保存" Command="{Binding SaveCommand}"/>
高级绑定技巧
RelativeSource绑定:绑定到相对元素
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Title}"/>
ElementName绑定:绑定到命名元素
<Slider x:Name="slider" Minimum="0" Maximum="100"/>
<TextBlock Text="{Binding ElementName=slider, Path=Value}"/>
多绑定(MultiBinding)
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} - {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
最佳实践
始终为可变数据实现INotifyPropertyChanged
对集合使用ObservableCollection<T>
考虑使用MVVM模式组织代码
对复杂转换使用ValueConverter
对用户交互使用Command绑定而非事件处理程序
Data Binding是WPF强大灵活性的核心,合理使用可以极大减少代码量,提高可维护性,实现真正的数据与UI分离。