现在我们的程序有了添加和删除以及修改功能,下面我们看一看如何让程序具备数据校验功能。我们将用两种方式实现数据的校验,一种是在客户端进行同步校验。另一种是在服务器端进行异步校验。
本篇我们先实现如何在客户端进行同步校验。基本原理是:利用数据的双向绑定和INotifyPropertyChanged 接口以及控件的NotifyOnValidationError与ValidatesOnExceptions两个属性设置来配合实现客户端同步校验。
现在我们的程序有了添加和删除以及修改功能,下面我们看一看如何让程序具备数据校验功能。我们将用两种方式实现数据的校验,一种是在客户端进行同步校验。另一种是在服务器端进行异步校验。
本篇我们先实现如何在客户端进行同步校验。基本原理是:利用数据的双向绑定和INotifyPropertyChanged 接口以及控件的NotifyOnValidationError与ValidatesOnExceptions两个属性设置来配合实现客户端同步校验。
现在继续修改完善我们的程序。
1、修改用户界面如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="SLApplicationDataTest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<StackPanel Height="500" Background="White">
<StackPanel Orientation="Horizontal">
<Button x:Name="addButton" Content="Add" Margin="10"/>
<Button x:Name="deleteButton" Content="Delete" Margin="10"/>
</StackPanel>
<data:DataGrid x:Name="dgPeople" AutoGenerateColumns="False" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<data:DataGridTextColumn Header="Sex" Binding="{Binding Sex}" />
<data:DataGridTemplateColumn Header="Age">
<data:DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<TextBlock Text="{Binding Age}" ToolTipService.ToolTip="请输入0至200之间的整数!"></TextBlock>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
<data:DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age , Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" BindingValidationError="TextBox_BindingValidationError"
ToolTipService.ToolTip="请输入0至200之间的整数!"></TextBox>
</DataTemplate>
</data:DataGridTemplateColumn.CellEditingTemplate>
</data:DataGridTemplateColumn>
<data:DataGridTextColumn Header="Address" Binding="{Binding Address}" />
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
</UserControl>
在此界面中,我们不再是简单地进行绑定数据和显示数据,而是对DataGrid控件进行了改造,尤其是运用了模板来定义我们的Age字段。注意Age字段的CellEditingTemplate模板,它的两个属性:NotifyOnValidationError,ValidatesOnExceptions都必须设置为true,这样才会在绑定出错时报错,而对错误事件的处理则字义在BindingValidationError事件中。
2、修改Person类
在此类中加入绑定数据的校验工作。具体代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
public int Age
{
get { return _age; }
set
{
if (value == _age) return;
//如果输入的不是整数,则抛出异常
try
{
Convert.ToInt32(value);
}
catch(Exception ex)
{
throw new Exception(ex.ToString());
}
//如果输入的整数不在合理范围同,则也抛出异常
if (value < 0 || value > 200)
{
throw new Exception("Age must be between 0 and 200");
}
_age = value;
OnPropertyChanged("Age");
}
}
Person类全部代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel; //因为要用到INotifyPropertyChanged接口
namespace SLApplicationDataTest
{
public class Person : INotifyPropertyChanged
{
private string _name;
private string _sex;
private int _age;
private string _address;
#region Constructors
public Person() { }
public Person(string NameStr, string SexStr, int AgeInt, string AddressStr)
{
this._name = NameStr;
this._sex = SexStr;
this._age = AgeInt;
this._address = AddressStr;
}
#endregion
#region Properties
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
public string Sex
{
get { return _sex; }
set
{
if (value == _sex) return;
_sex = value;
OnPropertyChanged("Sex");
}
}
public int Age
{
get { return _age; }
set
{
if (value == _age) return;
//如果输入的不是整数,则抛出异常
try
{
Convert.ToInt32(value);
}
catch(Exception ex)
{
throw new Exception(ex.ToString());
}
//如果输入的整数不在合理范围同,则也抛出异常
if (value < 0 || value > 200)
{
throw new Exception("Age must be between 0 and 200");
}
_age = value;
OnPropertyChanged("Age");
}
}
public string Address
{
get { return _address; }
set
{
if (value == _address) return;
_address = value;
OnPropertyChanged("Address");
}
}
#endregion
#region INotifyPropertyChanged 接口实现
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion
}
}
3、完成校验错误处理程序
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
#region 校验错误处理程序
private void TextBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
{
//((Control)e.OriginalSource).Background = new SolidColorBrush(Colors.Red);
//((Control)e.OriginalSource).SetValue(ToolTipService.ToolTipProperty, e.Error.Exception.Message);
//((Control)e.OriginalSource).Focus();
this.Dispatcher.BeginInvoke(() => HtmlPage.Window.Alert(e.Error.Exception.Message));
}
else if (e.Action == ValidationErrorEventAction.Removed)
{
//((Control)e.OriginalSource).Background = new SolidColorBrush(Colors.White);
//((Control)e.OriginalSource).SetValue(ToolTipService.ToolTipProperty, null);
}
}
#endregion
Page.xaml.cs全部代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser; //因为要使用HtmlPage.Window.Alert(message));
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
namespace SLApplicationDataTest
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public partial class Page : UserControl
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
People mypeople;
public Page()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InitializeComponent();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
this.addButton.Click += new RoutedEventHandler(addButton_Click);
this.deleteButton.Click += new RoutedEventHandler(deleteButton_Click);
this.dgPeople.KeyDown += new KeyEventHandler(peopleDataGrid_KeyDown);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Loaded += new RoutedEventHandler(Page_Loaded);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private void Page_Loaded(object sender, RoutedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
取得数据源数据并绑定到DataGrid控件上#region 取得数据源数据并绑定到DataGrid控件上
mypeople = People.GetTestData();
this.dgPeople.ItemsSource = mypeople;
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
通过按钮添加新记录行#region 通过按钮添加新记录行
void addButton_Click(object sender, RoutedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
mypeople.Add(new Person());
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
通过按钮删除记录#region 通过按钮删除记录
void deleteButton_Click(object sender, RoutedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DeletePerson();
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
删除记录子程序#region 删除记录子程序
private void DeletePerson()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (null == this.dgPeople.SelectedItem)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
Person person = this.dgPeople.SelectedItem as Person;
if (null == person)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
mypeople.Remove(person);
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
处理键盘响应事件#region 处理键盘响应事件
void peopleDataGrid_KeyDown(object sender, KeyEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
如果是Insert键,则做插入新行操作#region 如果是Insert键,则做插入新行操作
if (Key.Insert == e.Key)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
mypeople.Add(new Person());
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
如果是Delete键,则做删除操作#region 如果是Delete键,则做删除操作
if (Key.Delete == e.Key)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DeletePerson();
}
#endregion
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
校验错误处理程序#region 校验错误处理程序
private void TextBox_BindingValidationError(object sender, ValidationErrorEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (e.Action == ValidationErrorEventAction.Added)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//如果校验出错,则抛出错误提示窗口
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/////((Control)e.OriginalSource).Background = new SolidColorBrush(Colors.Red);
////((Control)e.OriginalSource).SetValue(ToolTipService.ToolTipProperty, e.Error.Exception.Message);
////((Control)e.OriginalSource).Focus();
this.Dispatcher.BeginInvoke(() => HtmlPage.Window.Alert(e.Error.Exception.Message));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
else if (e.Action == ValidationErrorEventAction.Removed)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//如果校验通过,则做如下处理
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/////((Control)e.OriginalSource).Background = new SolidColorBrush(Colors.White);
////((Control)e.OriginalSource).SetValue(ToolTipService.ToolTipProperty, null);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
运行效果如下:
![](https://images.cnblogs.com/cnblogs_com/wsdj-ittech/2009Y9M/SLApplicationDataTest/Part3/2.png)
前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)