为了保持数据和控件内容的同步,我们通常的方法是在:数据类中创建事件,在属性修改时通知控件修改内容;在控件所属类中创建事件,在内容修改时通知数据对象更新属性,这叫做数据绑定
如果有很多个数据类,这样做非常麻烦,而且做的都是同一件事。
使用WPF数据绑定
在WPF中,数据绑定很简单,只要把属性注册到数据绑定引擎中,让其来进行数据同步和对应的类型转换。
具体来说有2步:
- 数据类实现INotifyPropertyChanged接口,这是引擎需要的
- 对应属性和控件进行绑定
Example
<Grid x:Name="grid">
<StackPanel>
<WrapPanel>
<TextBlock>Name:</TextBlock>
<TextBox Name="nameTextBox" Width="100" Text="{Binding Path=Name}"/>
</WrapPanel>
<WrapPanel>
<TextBlock >Age:</TextBlock>
<TextBox Name="ageTextBox" Width="100" Text="{Binding Path=Age}">
</TextBox>
</WrapPanel>
<Button Name="birthdayButton" >Birthday</Button>
</StackPanel>
</Grid>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace WPF简单数据绑定
{
/// <summary>
/// PersonManager.xaml 的交互逻辑
/// </summary>
public partial class PersonManager : Window
{
Person p = new Person("Tom", 11);
public PersonManager()
{
InitializeComponent();
////初始化控件内容
//this.nameTextBox.Text = p.Name;
//this.ageTextBox.Text = p.Age.ToString();
//p.PropertyChanged += P_PropertyChanged;
grid.DataContext = p;
this.birthdayButton.Click += BirthdayButton_Click;
}
private void BirthdayButton_Click(object sender, RoutedEventArgs e)
{
++this.p.Age;
MessageBox.Show(String.Format(
"Happy birthday!{0},age {1}",p.Name,p.Age
),"Birthday");
}
private void P_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Name":
this.nameTextBox.Text = p.Name;
break;
case "Age":
this.ageTextBox.Text = p.Age.ToString();
break;
}
}
}
}
Value Conversion
在进行数据绑定时,有可能双方的数据类型不一致,程序运行时会报错:
此时需要自定义类型转换。
定义转换器
[ValueConversion(typeof(int), typeof(Brush))]
public class AgeToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(Brush))
{
return null;
}
int age = int.Parse(value.ToString());
return age > 15 ? Brushes.Red : Brushes.Black;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
使用转换器
<Window.Resources>
<local:AgeToBrushConverter x:Key="ageConverter"/>
</Window.Resources>
<Grid x:Name="grid">
<StackPanel>
<WrapPanel>
<TextBlock>Name:</TextBlock>
<TextBox Name="nameTextBox" Width="100" Text="{Binding Path=Name}"/>
</WrapPanel>
<WrapPanel>
<TextBlock >Age:</TextBlock>
<TextBox Name="ageTextBox" Width="100" Text="{Binding Path=Age}"
Foreground="{Binding Path=Age,Converter={StaticResource ageConverter}}"
>
</TextBox>
</WrapPanel>
<Button Name="birthdayButton" >Birthday</Button>
</StackPanel>
</Grid>