前面我们实现了如何添加,删除,修改以及校验数据记录,这里我们将使用一个接口IEditableObject来实现输入数据的回滚操作。
我们在界面上输入的数据有校验错误或笔误时,我们希望找回录入单元内原有的数据,也即回滚到原有的数据。这就要通过IEditableObject接口来实现。
前面我们实现了如何添加,删除,修改以及校验数据记录,这里我们将使用一个接口IEditableObject来实现输入数据的回滚操作。
我们在界面上输入的数据有校验错误或笔误时,我们希望回滚到原有的数据。这就要通过IEditableObject接口来实现。
IEditableObject是数据绑定中用到的,主要是三个函数:BeginEdit()、CancelEdit()、EndEdit()。
此类提供提交或回滚对用作数据源的对象所做更改的功能。
该接口通常用于捕获 DataRow 的 BeginEdit,EndEdit 和 CancelEdit语义。这个接口支持撤销,当在DataGrid编辑一个实现了IEditableObject的 T 类型集合时,当前行默认的是编辑状态,当前焦点进入一个DataRow时,会触发 T中定义IEditableObject.BeginEdit函数,离开焦点时,会触发T中定义IEditableObject.EndEdit函数,按下ESC时,会触发CancelEdit函数。有了这个接口,我们就可以将一个类型的读写操作放到对象中,更符合面向对象的思想。同时,在一个界面中给DataGrid赋予不同的类型集合,集合中对象类型不同,都能实现属性的编辑,委托给合适的对象中的编辑函数,而不用对界面进行什么更改!
1、加入并实现IEditableObject接口
下面我们来实现程序的数据回滚操作,修改Person类,
首先要继承接口,并加入下面的接口实现:
public class Person : INotifyPropertyChanged,IEditableObject
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
IEditableObject 接口实现#region IEditableObject 接口实现
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private Person _backup; //用于保存编辑对象的原本
private bool _editing; //处于编辑状态时为true,退出编辑状态时为false
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.BeginEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_editing = true;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//MemberwiseClone 方法在这里仅做演示,如果在实际应用时,应该用deep copy.
_backup = this.MemberwiseClone() as Person; //保存编辑前的内容
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.CancelEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//取消当前编辑,恢复编辑前内容
//如果要取消当前编辑,请按下Esc键
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Name = _backup.Name;
Sex = _backup.Sex;
Age = _backup.Age;
Address = _backup.Address;
_editing = false;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.EndEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_editing = false;
this._backup = null;//当前编辑生效
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
然后按下F5运行,依次修改某行的Name,Age,Sex或Address,然后再依次按下ESC健,可以看到,各记录的值依次回滚到修改前的数据(注意:当你的输入焦点退出当前行进入其它数据行时,前一行的回滚操作不再有效,因为当它退出焦点时,就提交了数据修改的生效)。
2、加入数据录入确定生效时的自定义事件
借助IEditableObject,我们可以加入数据录入生效后的自定义事件。 也即:我们对数据进行了修改,如果用户cancel掉新的录入或修改,则不用激发我们的自定义事件,而如果用户确定录入生效,则激活我们的自定义事件。
在Person类对象内加入以下自定义事件处理代码:
在EndEdit中激活ChangesCommitted 事件
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
void IEditableObject.EndEdit()
{
if (_editing)
{
_editing = false;
this._backup = null;//当前编辑生效
OnChangesCommitted();
}
}
}
#endregion
ChangesCommitted 事件处理代码
#region ChangesCommitted 自定义事件处理过程
void emptyPerson_ChangesCommitted(object sender, EventArgs e)
{
emptyPerson.ChangesCommitted -= new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
emptyPerson = new Person();
MessageBox.Show("本记录行更改已提交!");
emptyPerson.ChangesCommitted += new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
base.InsertItem(this.Count, emptyPerson);
}
#endregion
我们定义了一个ChangesCommitted 事件,当用户结束editing时就会激活此事件(在EndEdit()代码段中激发此事件)
接下来,我们需要修改People类,在那里加入我们对ChangesCommitted事件的具体处理方法。我们首先给People类新加入了一个方法AddNewPerson(),
此方法提供在当前的People记录中添加一个新的Person记录。代码如下:
public People AddNewPerson( )
{
emptyPerson = new Person();
emptyPerson.ChangesCommitted += new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
base.InsertItem(this.Count, emptyPerson);
return this;
}
接下来修改我们的Add按钮事件如下:
#region 通过按钮添加新记录行
void addButton_Click(object sender, RoutedEventArgs e)
{
// mypeople.Add(new Person());
mypeople = mypeople.AddNewPerson();
}
#endregion
按F5运行,按Add添加一新行,修改其中的记录,然后退出焦点,点击其它行,可以看到效果如下:
现在的问题是,即使我们输入的数据校验通不过,这个新的录入也会确定,并会自动在最后新添一行新记录,这不是我们想要的。所以,我们需要进一步完善,如果新的录入通不过校验,则不予确定,程序也不会在后面自动添加一个新的记录行。而如果校验通过,则程序会弹出提交修改信息,并自动在最后另起一新数据行。这个工作我们放在EndEdit中进行,如果录入的数据有效,则激活ChangesCommitted事件,PersonValidator 类已经有了Validate方法,我们将会使用它。
修改Person类的EndEdit()如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
void IEditableObject.EndEdit()
{
if (_editing)
{
_editing = false;
this._backup = null;//当前编辑生效
//当用户结束Edit时,激发我们自定义的ChangesCommitted事件,在此事件中执行我们期望的其它处理工作
if (null != ChangesCommitted)
{
_fireChangesCommited = true;
//this.RootVisual就是Application.Current.RootVisual的值,也就是page control
//所有的子控件都在RootVisual里面,可以通过 Page page = (Page)Application.Current.RootVisual得到这个Page对象。
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => _personValidator.Validate()); //调用 Validate方法进行校验
//取消下面的OnChangesCommitted,也即不再在此处提交修改,推迟为由PersonValidator类中来做此项工作,如果校验都通过则提交否则不提交
// OnChangesCommitted();
}
}
}
我们还另加入validator_Validated()来响应PersonValidator类校验通过的Validated事件。代码如下:
#region PersonValidator 类校验通过事件响应
void _validator_Validated(object sender, EventArgs e)
{
if (_fireChangesCommited)
{
_fireChangesCommited = false;
if (_personValidator.IsValid)
{
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => OnChangesCommitted());
}
}
}
#endregion
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接口
using SLApplicationDataTest.SexServiceReference; //因为要使用WCF服务
using System.Windows.Browser; //因为要使用HtmlPage.Window.Alert
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](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 class Person : INotifyPropertyChanged,IEditableObject
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private PersonValidator _personValidator; //定义一个PersonValidator类对象
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private string _name;
private string _sex;
private int _age;
private string _address;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Person类对象的构造函数#region Person类对象的构造函数
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
构造函数一#region 构造函数一
public Person()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//在新创建一个Person类对象的同时,创建一个PersonValidator对象,并将新创建的Person类对象传递给PersonValidator对象
//从而在Person类对象和PersonValidator之间建立了关联
_personValidator = new PersonValidator(this);
_personValidator.Validated += new EventHandler<EventArgs>(_validator_Validated);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
构造函数二#region 构造函数二
public Person(string NameStr, string SexStr, int AgeInt, string AddressStr):this()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this._name = NameStr;
this._sex = SexStr;
this._age = AgeInt;
this._address = AddressStr;
}
#endregion
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Person类对象的属性#region Person类对象的属性
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
姓名属性#region 姓名属性
public string Name
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _name; }
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (value == _name) return;
_name = value;
OnPropertyChanged("Name");
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
性别属性#region 性别属性
public string Sex
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _sex; }
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (value == _sex) return;
_sex = value;
OnPropertyChanged("Sex");
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
年龄属性#region 年龄属性
public int Age
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _age; }
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (value == _age) return;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
年龄校验 OLD#region 年龄校验 OLD
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/////如果输入的不是整数,则抛出异常
//try
//{
// Convert.ToInt32(value);
//}
//catch(Exception ex)
//{
// throw new Exception(ex.ToString());
//}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/////如果输入的整数不在合理范围同,则也抛出异常
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//if (value < 0 || value > 200)
//{
// throw new Exception("Age must be between 0 and 200");
//}
#endregion
_age = value;
OnPropertyChanged("Age");
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
地址属性#region 地址属性
public string Address
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _address; }
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (value == _address) return;
_address = value;
OnPropertyChanged("Address");
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Validator属性#region Validator属性
public PersonValidator Validator
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return this._personValidator; }
}
#endregion
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
INotifyPropertyChanged 接口实现#region INotifyPropertyChanged 接口实现
public event PropertyChangedEventHandler PropertyChanged;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
protected void OnPropertyChanged(string name)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
RaisePropertyChanged方法#region RaisePropertyChanged方法
internal void RaisePropertyChanged(string name)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
OnPropertyChanged(name);
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
IEditableObject 接口实现#region IEditableObject 接口实现
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private Person _backup; //用于保存编辑对象的原本
private bool _editing; //处于编辑状态时为true,退出编辑状态时为false
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.BeginEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (!_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_editing = true;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//MemberwiseClone 方法在这里仅做演示,如果在实际应用时,应该用deep copy.
_backup = this.MemberwiseClone() as Person; //保存编辑前的内容
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.CancelEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//取消当前编辑,恢复编辑前内容
//如果要取消当前编辑,请按下Esc键
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Name = _backup.Name;
Sex = _backup.Sex;
Age = _backup.Age;
Address = _backup.Address;
_editing = false;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
void IEditableObject.EndEdit()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_editing)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_editing = false;
this._backup = null;//当前编辑生效
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//当用户结束Edit时,激发我们自定义的ChangesCommitted事件,在此事件中执行我们期望的其它处理工作
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (null != ChangesCommitted)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_fireChangesCommited = true;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//this.RootVisual就是Application.Current.RootVisual的值,也就是page control
//所有的子控件都在RootVisual里面,可以通过 Page page = (Page)Application.Current.RootVisual得到这个Page对象。
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => _personValidator.Validate()); //调用 Validate方法进行校验
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//取消下面的OnChangesCommitted,也即不再在此处提交修改,推迟为由PersonValidator类中来做此项工作,如果校验都通过则提交否则不提交
// OnChangesCommitted();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
数据修改生效确定#region 数据修改生效确定
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
bool _fireChangesCommited;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public event EventHandler<EventArgs> ChangesCommitted;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
protected void OnChangesCommitted()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (null != ChangesCommitted)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ChangesCommitted(this, new EventArgs());
}
}
#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)
PersonValidator 类校验通过事件响应#region PersonValidator 类校验通过事件响应
void _validator_Validated(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_fireChangesCommited)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_fireChangesCommited = false;
if (_personValidator.IsValid)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => OnChangesCommitted());
}
}
}
#endregion
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
修改People类代码如下:
![](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.Collections.ObjectModel; //引入此空间,因为要用到ObservableCollection类
using System.Collections.Generic;
![](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 class People : ObservableCollection<Person>
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private Person emptyPerson;
private People peopleData;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
GetTestData方法#region GetTestData方法
public static People GetTestData()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
People peopleData = new People()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
new Person("Marge", "Female", 33, "SpringVale"),
new Person("Tom", "Male", 8, "Toorak"),
new Person("Simon", "Male", 21, "RingWood"),
new Person("Abby", "Male", 18, "BoxHill")
};
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
return peopleData;
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
GetTestDataList方法#region GetTestDataList方法
public static List<Person> GetTestDataList()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return new List<Person>()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
new Person("Jack", "Male", 38, "ChengDu"),
new Person("Marge", "Female", 33, "SpringVale"),
new Person("Tom", "Male", 8, "Toorak"),
new Person("Simon", "Male", 21, "RingWood"),
new Person("Abby", "Male", 18, "BoxHill")
};
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public People AddNewPerson( )
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
emptyPerson = new Person();
emptyPerson.ChangesCommitted += new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
base.InsertItem(this.Count, emptyPerson);
return this;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
ChangesCommitted 自定义事件处理过程#region ChangesCommitted 自定义事件处理过程
void emptyPerson_ChangesCommitted(object sender, EventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
emptyPerson.ChangesCommitted -= new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
emptyPerson = new Person();
MessageBox.Show("本记录行更改已提交!");
emptyPerson.ChangesCommitted += new EventHandler<EventArgs>(emptyPerson_ChangesCommitted);
base.InsertItem(this.Count, emptyPerson);
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
修改PersonValidator类,其全部代码如下:
![](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 SLApplicationDataTest.SexServiceReference; //因为要使用WCF服务
using System.Windows.Browser; //因为要用到HtmlPage.Window.Alert
using System.ComponentModel; //因为要用到INotifyPropertyChanged
using System.Collections.Generic;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](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 class PersonValidator:INotifyPropertyChanged
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
相关常量定义#region 相关常量定义
public const string PROPERTY_NAME_ISVALID = "IsValid";
public const string PROPERTY_NAME_INVALID = "Invalid";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public const string PROPERTY_NAME_NAME = "Name";
public const string PROPERTY_NAME_AGE = "Age";
public const string PROPERTY_NAME_SEX = "Sex";
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private Dictionary<string, string> _errors; //定义一个数据字典用于集中管理校验结果
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private bool _fireValidated; //用于配合录入确定时的数据校验
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private List<string> _propertiesToValidate;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
年龄属性及年龄校验#region 年龄属性及年龄校验
// private bool _invalidAge;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public bool InvalidAge
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//return _invalidAge;
return _errors.ContainsKey(PROPERTY_NAME_AGE);
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//if (_invalidAge == value)
// return;
//_invalidAge = value;
//OnPropertyChanged("InvalidAge");
if (value)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RegisterError(PROPERTY_NAME_AGE, "年龄必须介于0到200之间!");
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ClearError(PROPERTY_NAME_AGE);
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void ValidateAge(int newValue)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InvalidAge = (newValue < 0 || newValue > 200);//年龄应该介于0到200之间,如果超过逻辑范围,则返回true,表示校验没通过!
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
姓名属性及姓名校验#region 姓名属性及姓名校验
// private bool _invalidName;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public bool InvalidName
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//return _invalidName;
return _errors.ContainsKey(PROPERTY_NAME_NAME);
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//if (_invalidName == value) return;
//_invalidName = value;
//OnPropertyChanged("InvalidName");
if (value)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RegisterError(PROPERTY_NAME_NAME, "请输入您的姓名!");
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ClearError(PROPERTY_NAME_NAME);
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void ValidateName(string newValue)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (string.IsNullOrEmpty(newValue)) //姓名输入不能为空
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InvalidName = true; //如果为空,则返回true
return;
}
InvalidName = (0 == newValue.Trim().Length);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
性别属性及性别校验#region 性别属性及性别校验
//private bool _invalidSex;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public bool InvalidSex
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// return _invalidSex;
return _errors.ContainsKey(PROPERTY_NAME_SEX);
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//if (_invalidSex == value) return;
//_invalidSex = value;
//OnPropertyChanged("InvalidSex");
if (value)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
RegisterError(PROPERTY_NAME_SEX, "请输入正确的性别!");
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ClearError(PROPERTY_NAME_SEX);
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
性别输入校验程序:通过调用WCF服务来完成校验工作#region 性别输入校验程序:通过调用WCF服务来完成校验工作
private void ValidateSex(string SexStr)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (string.IsNullOrEmpty(SexStr))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InvalidSex = true;
return;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
SexWCFClient sexCs = new SexWCFClient();
sexCs.SexValidationCompleted += new EventHandler<SexValidationCompletedEventArgs>(sexCs_SexValidationCompleted);
((Page)Application.Current.RootVisual).StartWait("请稍候,正在校验性别输入!"); //打开等待提示界面,提示用户指定的提示信息
sexCs.SexValidationAsync(SexStr, SexStr); //其中第二个SexStr为传入的UserState参数,将在sexCs_SexValidationCompleted中使用
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void sexCs_SexValidationCompleted(object sender, SexValidationCompletedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
((Page)Application.Current.RootVisual).EndWait(null); //关闭等待提示界面
InvalidSex = !e.Result;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
整体校验属性#region 整体校验属性
// private bool _isValid;
public bool IsValid
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//return _isValid;
return (0 == _errors.Keys.Count); //当字典中没有任何error记录时,返回true,表示整体校验通过
}
set
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
//if (_isValid == value) return;
//_isValid = value;
//OnPropertyChanged("IsValid");
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
OnPropertyChanged(PROPERTY_NAME_ISVALID);
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => _data.RaisePropertyChanged("Validator"));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// _data.RaisePropertyChanged("Validator");
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
Person _data; //定义一个Person类对象(此对象将会被关联到需要校验的实际Person对象)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
PersonValidator构造函数(把要校验的Person类对象做为参数传递给PersonValidator类的构造函数以建立相互之间的关联)#region PersonValidator构造函数(把要校验的Person类对象做为参数传递给PersonValidator类的构造函数以建立相互之间的关联)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
构造函数一#region 构造函数一
public PersonValidator(Person data)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_data = data;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//当它所关联的Person类对象实例的任何属性发生变更时则会激活_data_PropertyChanged事件处理
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
OLD#region OLD
//_data_PropertyChanged事件处理实际就是对变更的属性值进行数据校验
// default valid
// _isValid = true;
#endregion
//_data.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_data_PropertyChanged);
_data.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Person_PropertyChanged);
_errors = new Dictionary<string, string>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
构造函数二#region 构造函数二
public PersonValidator(Person data, bool defaultInvalid) : this(data)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (defaultInvalid)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
OLD#region OLD
//_invalidAge = true;
//_invalidName = true;
//_invalidSex = true;
//_isValid = false;
#endregion
_errors.Add(PROPERTY_NAME_AGE, PROPERTY_NAME_AGE);
_errors.Add(PROPERTY_NAME_SEX, PROPERTY_NAME_SEX);
_errors.Add(PROPERTY_NAME_NAME, PROPERTY_NAME_NAME);
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
当Person类对象的任一属性发生改变时重新进行校验#region 当Person类对象的任一属性发生改变时重新进行校验
void _data_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (e.PropertyName == "IsValid")
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
switch (e.PropertyName)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
OLD#region OLD
//case "Age":
// ValidateAge(_data.Age);
// break;
//case "Name":
// ValidateName(_data.Name);
// break;
//case "Sex":
// ValidateSex(_data.Sex);
// break;
#endregion
case PROPERTY_NAME_AGE: ValidateAge(_data.Age); break;
case PROPERTY_NAME_NAME: ValidateName(_data.Name); break;
case PROPERTY_NAME_SEX: ValidateSex(_data.Sex); break;
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
PersonValidator类的Validate方法#region PersonValidator类的Validate方法
public void Validate()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_fireValidated = true;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_propertiesToValidate = new List<string>()
{
PROPERTY_NAME_INVALID + PROPERTY_NAME_AGE,
PROPERTY_NAME_INVALID + PROPERTY_NAME_SEX,
PROPERTY_NAME_INVALID + PROPERTY_NAME_NAME };
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
ValidateAge(_data.Age);
ValidateName(_data.Name);
ValidateSex(_data.Sex);
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
INotifyPropertyChanged Members#region INotifyPropertyChanged Members
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public event PropertyChangedEventHandler PropertyChanged;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
protected void OnPropertyChanged(string name)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (_fireValidated && AllPropertiesValidated(name))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_fireValidated = false;
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => OnValidated());
}
}
#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 获取对应字段的校验出错提示信息
public string this[string propertyName]
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_errors.ContainsKey(propertyName))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _errors[propertyName];
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return null;// propertyName;
}
}
}
#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)
error Dictionary 字典管理#region error Dictionary 字典管理
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
添加与更新Dictionary记录#region 添加与更新Dictionary记录
public void RegisterError(string propertyName, string message)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_errors.ContainsKey(propertyName))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_errors[propertyName] = message; //更新对应的error信息对
}
else
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_errors.Add(propertyName, message); //添加新的error信息对
}
OnPropertyChanged(PROPERTY_NAME_INVALID + propertyName);
//IsValid = false;
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => IsValid = false);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
移除Dictionary记录#region 移除Dictionary记录
public void ClearError(string propertyName)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_errors.ContainsKey(propertyName))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_errors.Remove(propertyName); //删除指定的error信息对
}
OnPropertyChanged(PROPERTY_NAME_INVALID + propertyName);
// IsValid = true;
Application.Current.RootVisual.Dispatcher.BeginInvoke(() => IsValid = true);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Person_PropertyChanged 时的校验#region Person_PropertyChanged 时的校验
void Person_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (e.PropertyName == "IsValid")
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return;
}
switch (e.PropertyName)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case PROPERTY_NAME_AGE:
ValidateAge(_data.Age);
break;
case PROPERTY_NAME_NAME:
ValidateName(_data.Name);
break;
case PROPERTY_NAME_SEX:
ValidateSex(_data.Sex);
break;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public bool AllPropertiesValidated(string propertyValidated)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_propertiesToValidate.Remove(propertyValidated);
return (_propertiesToValidate.Count == 0);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public event EventHandler<EventArgs> Validated;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
protected void OnValidated()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (null != Validated)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Validated(this, new EventArgs());
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
Page.xaml.cs全部代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
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)
![](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;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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());
mypeople = mypeople.AddNewPerson();
}
#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)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
if (e.Action == ValidationErrorEventAction.Added)
![](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)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
else if (e.Action == ValidationErrorEventAction.Removed)
![](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/ContractedSubBlock.gif)
打开与关闭“等待校验窗口”#region 打开与关闭“等待校验窗口”
public void StartWait(string message)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.myWaitingSexValidateScreen.DataContext = message;
this.myWaitingSexValidateScreen.StartWait();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public void EndWait(string message)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.myWaitingSexValidateScreen.DataContext = message;
this.myWaitingSexValidateScreen.StopWait();
}
#endregion
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
private void dgPeople_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)
{
Person person = ((Control)e.OriginalSource).DataContext as Person;
if (null != person && null != ((Control)e.OriginalSource).Tag)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
person.Validator.RegisterError(((Control)e.OriginalSource).Tag.ToString(), e.Error.Exception.Message);
}
//((Control)e.Source).Background = new SolidColorBrush(Colors.Red);
//((Control)e.Source).SetValue(ToolTipService.ToolTipProperty, e.Error.Exception.Message);
}
else if (e.Action == ValidationErrorEventAction.Removed)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Person person = ((Control)e.OriginalSource).DataContext as Person;
if (null != person && null != ((Control)e.OriginalSource).Tag)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
person.Validator.ClearError(((Control)e.OriginalSource).Tag.ToString());
}
//((Control)e.Source).Background = new SolidColorBrush(Colors.White);
//((Control)e.Source).SetValue(ToolTipService.ToolTipProperty, null);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
从代码可以看到,我们在此方法中不再直接激活ChangesCommitted事件,而是先由PersonValidator 类进行校验,校验通过后,由Person类的中的_validator_Validated方法来激活ChangesCommitted事件。如果校验没有通过,则不激活ChangesCommitted事件。
生成项目并运行,可以看到
1、当新行数据录入校验没通过时,程序会提示并不会自动添加新行,如下图
2、当新行数据录入校验通过后,程序会自动添加一新行,如下图:
先显示提交修改的数据
![](https://images.cnblogs.com/cnblogs_com/wsdj-ittech/2009Y9M/SLApplicationDataTest/Part6/3.png)
再在最后自动添加一新行,如下图:
前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)