SilverLight学习笔记--实际应用(一)(7):手把手建立一个Silverlight应用程序之数据回滚

  前面我们实现了如何添加,删除,修改以及校验数据记录,这里我们将使用一个接口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 

  IEditableObject 接口实现

  然后按下F5运行,依次修改某行的Name,Age,Sex或Address,然后再依次按下ESC健,可以看到,各记录的值依次回滚到修改前的数据(注意:当你的输入焦点退出当前行进入其它数据行时,前一行的回滚操作不再有效,因为当它退出焦点时,就提交了数据修改的生效)。 

 2、加入数据录入确定生效时的自定义事件
       借助IEditableObject,我们可以加入数据录入生效后的自定义事件。 也即:我们对数据进行了修改,如果用户cancel掉新的录入或修改,则不用激发我们的自定义事件,而如果用户确定录入生效,则激活我们的自定义事件。
   在Person类对象内加入以下自定义事件处理代码:
在EndEdit中激活ChangesCommitted 事件 

Code

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()如下: 

 

Code

  我们还另加入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类全部代码如下:

 

Code

  修改People类代码如下:

Code

 

  修改PersonValidator类,其全部代码如下:

Code

 

 Page.xaml.cs全部代码如下:

 

Code

 
   从代码可以看到,我们在此方法中不再直接激活ChangesCommitted事件,而是先由PersonValidator 类进行校验,校验通过后,由Person类的中的_validator_Validated方法来激活ChangesCommitted事件。如果校验没有通过,则不激活ChangesCommitted事件。

  生成项目并运行,可以看到
  1、当新行数据录入校验没通过时,程序会提示并不会自动添加新行,如下图

                         
2、当新行数据录入校验通过后,程序会自动添加一新行,如下图:

                        先显示提交修改的数据

                        
        再在最后自动添加一新行,如下图:
                                                 

前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)

posted @ 2009-09-11 11:14  wsdj  阅读(1222)  评论(1编辑  收藏  举报