数据转换
Silverlight中实现数据转换的机制与ASP.NET应该讲是同样的思想,只不过ASP.NET中似乎淡化了手动编写关于数据转换的部分,在Silverlight中我们实现数据转换需实现接口IValueConverter,其位于System.Windows.Data中,IValueConverter其包含两个方法:
Convert():当数据从数据源发送到绑定目标时调用
ConvertBack():当数据从绑定目标发送回绑定源时调用
只有双向绑定时才需要真正实现这两个方法,当单向绑定时,只需实现Convert(),对于ConvertBack()可以使用throw new NotImplementException形式的代码填充。下面仍然以之前的示例为基础,实现FirstName与LastName中的内容为首字母大写形式。
首先仍然沿用先前的Person类:
public class Person:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Person() { }
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
}
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set {
lastName = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
}
}
}
}
然后实现一个基于IValueConverter的类,完整代码:
namespace DataBindSilverlight
{
public class UCFirst:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var name = (string)value;
if (name.Length > 0)
{
var firstname = name.Substring(0,1);
name = firstname.ToUpper() + name.Substring(1);
}
return name;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (string)value;
}
}
}
这两步工作完成后,下面的工作即是需要在XAML标记中告知Silverlight使用此转换器,首先,定义一个XML前缀,使得XAML可以访问DataBindSilverlight 空间中的类,代码为:<Canvas xmlns:local="clr-namespace:DataBindSilverlight"/> 第二步则是创建一个Resource子元素,其可以使用DataBindSilverlight,包括UCfirst转换器,这里我们将UCfirst作为内部资源加载,代码:
<Canvas.Resources>
<local:UCFirst x:Key="ucfirstConverter"></local:UCFirst>
</Canvas.Resources>
以上代码添加了一个键x:Key,用来对资源的引用,接下来在TextBox元素中提供转换器的名称
<TextBox Name="textBlock4" Text="{Binding LastName, Mode=TwoWay,Converter={StaticResource ucfirstConverter}}" />
关键字StaticResouces表示使用的资源是内部资源,ucfirstConverter是分配给<local:UCFirst/>的键值。 那么我们已经完成了整个XAML的代码的设计:
< Grid x:Name ="PersonalPanel" Background ="White" >
后台代码其实没有变化,为了方便,仍然贴出来
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];
}
尽管在硬编码中,我们看到的是小写字母单词呈现的单词,但是运行时,已经成功的将其首字母改变为大写形式。
数据验证
当绑定的数据发生更改时,如果需要确保新数据仍然符合某些预先设定的规则,我们基于前面的数据转换示例扩展这一功能首先更新XAML文件,在TextBox元素中提供绑定信息时设置ValidatesOnExceptions,NotifyOnValidationError两个属性为True
XAML完整代码:
注意BindingValidationError设置了出现异常的事件处理程序,showError方法的第2个参数类型为ValidationErrorEventArgs, 可通过访问该参数获取相关信息,
public void showError(object sender,ValidationErrorEventArgs e)
{
//异常不会冒泡
e.Handled = true;
if (e.Action == ValidationErrorEventAction.Added)
{
(e.OriginalSource as TextBox).Text = "**Error**"; }
}
ValidationErrorEventAction枚举包含2个值:Added 新验证错误已经信号
Removed 之前的错误输入已经纠正
运行后,当输入的值为空时,异常会抛出(F5忽略该异常),单击前进或后退,返回该记录时,文本会发送改变