做过ASP.NET或者Silverlight的童鞋对数据绑定比较熟悉,WP7是基于Silverlight的,silverlight for windows phone页面也是使用XAML,所以页面渲染的原理是一样的。
数据绑定分为源(Source)和目标(Target),Source一般分为两种,其他控件的数据源,或者数据对象。
先说说以控件作为数据源的吧,最简单的格式是:目标控件属性="{Binding ElementName=源控件名, Path=源控件属性}"。
为了便于一会介绍Converter,我放弃使用TextBox作为数据源,转而使用Silvder,免得一会有童鞋挑错。
在页面中放置一个Silder和一个TextBlock,XAML代码如下
public class ValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string strValue = "";
double doubleValue = (double)value;
if (doubleValue > 50)
strValue = "获取的值比较大";
else
strValue = "获取的值比较小";
return strValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
然后还要将该类添加到静态资源中,以便使用,在App.xaml中添加当前项目中的命名空间:xmlns:local="clr-namespace:DataBindings"
然后将ValueConverter类声明为静态资源:
现在修改MainPage.xaml中的TextBlock的Text的内容:。
上面已经将Binding的Mode设置成了TwoWay,所以我们用代码修改TextBlock的Text属性的值,看看Silder是否跟着变化。
在Page_Loaded方式中添加一句代码,用来在页面初始化后修改TextBlock的Text属性的值:TargetTB.Text = "40";
运行项目,效果如下
我没在Page_Loaded方法中设置了TextBlock的Text值为40,看到Silder的值变成了40,证明Mode=TwoWay起作用了,看到,TextBlock的Text值显示的不是40,而是"获取的值比较小",证明我们的ValueConverter起作用了,那么拖动Silder,使他的值大于50%,我们应该猜到TextBlock的Text值,应该是"获取的值比较大",看看效果是不是
接下来我们说说,实际开发中使用更多的,使用数据对象作为数据源
先添加一个用于提供数据源的类DataSource和Person,代码如下
public class DataSource
{
private Person _personData;
public Person PersonData
{
get
{
return _personData;
}
set
{
_personData = value;
}
}
public DataSource()
{
PersonData = new Person()
{
Name = "DHC",
Sex = "男",
Age = 27
};
}
}
public class Person: INotifyPropertyChanged
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
private string _sex;
public string Sex
{
get
{
return _sex;
}
set
{
_sex = value;
}
}
private int _age;
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
然后为MainPage页面设置数据源
DataSource ds = new DataSource();
DataContext = ds.PersonData;
在MainPage.xaml页面中添加三个TextBlock,并绑定数据
Person person = DataContext as Person;
person.Age = 100;
运行并点击,按钮,效果如下
Age没有变成100,这不是我们想要的结果,这事为什么呢
INotifyPropertyChanged接口
上面的程序,点击按钮,并没有像我们想象中的那样,显示Age的TextBlock的Text没有改变,这事因为数据改变后,并没有通知UI界面,为什么Silder的Value改变后通知了,我们自己定义的数据没有通知呢,这是因为我们上面定义的Person类没有继承INotifyPropertyChanged,看到这个接口的名字,就知道他是干什么的,通知属性改变,他就是干这个用的。
用法是直接继承INotifyPropertyChanged,利用PropertyChangedEventHandler添加委托,通知数据已经改变,现在修改Person类
public class Person: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
if (PropertyChanged != null)
PropertyChanged(this, args);
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
private string _sex;
public string Sex
{
get
{
return _sex;
}
set
{
_sex = value;
OnPropertyChanged(new PropertyChangedEventArgs("Sex"));
}
}
private int _age;
public int Age
{
get
{
return _age;
}
set
{
_age = value;
OnPropertyChanged(new PropertyChangedEventArgs("Age"));
}
}
}
再次运行程序,点击按钮,效果如下
好了,这就是我们想要的结果。
在最后补充一点东西,我们可以将数据声明为静态资源,然后也可以绑定
声明静态资源:
为页面设置数据源:DataContext="{StaticResource data}"
为控件属性绑定数据