Silverlight中的数据绑定2
Silverlight中数据绑定,须由自己决定要使用的绑定模式,在前面一篇文章中都是使用了默认模式OneTime
银光中支持3种模式
OneTime :仅在数据进行绑定时发生一次,以后更改绑定源对输出不产生任何影响
OneWay :数据绑定只在从绑定源到绑定目标这一个方向起作用,即更改绑定源会更改绑定目标,且不需要在代码中进行额外的处理
TwoWay :更改绑定源会更改绑定目标,反之亦然。
其中OneWay和TwoWay类似ASP.NET中的Eval与Bind绑定,需要注意的是,若使用这两者绑定模式,需要实现INotifyPropertyChanged接口
单向数据绑定
Xaml代码只是在之前的基础上添加了一个充当文本的按钮
<Grid x:Name="PersonalPanel" Background="White">
在此基础上完成单击时,使用reverse方法实现FirstName与LastName中的文本顺序颠倒
public void reverse() { char [] c=new char[this.FirstName.Length]; for (int i = 0; i < this.FirstName.Length; i++) { c[i] = this.FirstName[this.FirstName.Length - 1 - i]; } this.FirstName = new String(c); c = new char[this.LastName.Length]; for (int i = 0; i < this.LastName.Length; i++) { c[i] = this.LastName[this.LastName.Length - 1 - i]; } this.LastName = new string(c); }
接下来需要一个在更改属性时实现的公共事件:
public event PropertyChangedEventHandler PropertyChanged;
但是此事件无法自动使用,我们改写代码触发此事件,
private string firstName; public string FirstName { get { return firstName; } set { firstName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("FirstName")); } } }
最后实现鼠标单击的事件处理程序 Person类文件的完整代码:
private string firstName; public string FirstName { get { return firstName; } set { firstName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("FirstName")); } } } //为进行演示,只对FirstName进行额外处理 public string LastName { get; set; } public void reverse() { char [] c=new char[this.FirstName.Length]; for (int i = 0; i < this.FirstName.Length; i++) { c[i] = this.FirstName[this.FirstName.Length - 1 - i]; } this.FirstName = new String(c); c = new char[this.LastName.Length]; for (int i = 0; i < this.LastName.Length; i++) { c[i] = this.LastName[this.LastName.Length - 1 - i]; } this.LastName = new string(c); } public event PropertyChangedEventHandler PropertyChanged;
不要忘记添加System.ComponentModel命名空间
后台代码:
public partial class MainPage : UserControl { private int pos = -1; private Person[] persons; public MainPage() { InitializeComponent(); persons = new Person[] { new Person{FirstName="David",LastName="Grenn"}, new Person{FirstName="Dam",LastName="White"}, new Person{FirstName="Tom",LastName="Smith"}, }; } public void prev(object sender, MouseButtonEventArgs e) { if (pos > 0) pos--; bind(); } public void next(object sender, MouseButtonEventArgs e) { if (pos < persons.Length - 1) pos++; bind(); } private void bind() { PersonalPanel.DataContext = persons[pos]; } private void reverse(object sender, MouseButtonEventArgs e) { persons[pos].reverse(); }
运行时,会发现当单击Reverse时,只有名字颠倒了顺序,但是如果移动到下一个(或上一个),然后返回到之前的记录,会发现两者都颠倒了,原因在于只有FirstName属性触发了PropertyChanged事件,因此只更新名字的显示,但是当前进或者后退时,数据总是会再次绑定到元素上,因此会出现两者全部颠倒的情况。
双向数据绑定
双向数据绑定可以使得显示数据的变化可以在原始数据中得到反映
为简化起见,在前面的示例中进行改写,只保留了其中关键的代码,主要是在绑定中添加了Mode枚举,我们把XAML代码修改为:
<Grid x:Name="PersonalPanel" Background="White">
<TextBox Name="textBlock3" Text="{Binding FirstName, Mode=TwoWay}" />
<TextBox Name="textBlock4" Text="{Binding LastName, Mode=TwoWay}" />
<Canvas Canvas.Left="120">
<Polygon Fill="Black" Points="0,5,10,0,10,10" MouseLeftButtonDown="prev"></Polygon>
<Polygon Fill="Black" Points="15,0,15,10,25,5" MouseLeftButtonDown="next"></Polygon>
</Canvas>
</Grid>
C#代码也进行了一点改变,lastname也实现了触发PropertyChanged事件
private string lastName; public string LastName { get { return lastName; } set { lastName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("LastName")); } } }
其他代码部分则没有改变,运行时,当切换到某个字段时,(改变文本框内容后,需要使得文本框失去焦点),这时PropertyChanged事件会自动触发,
但是该事件不会在键入内容时立即触发,当单击下一条记录再返回时,因为使用了双向绑定,所以会自动传送给数据源。