WinForm中实体类批量修改、批量提交辅助类

    在WinForm项目开发中习惯于对于集合数据的批量修改,再一次性提交更新同步到数据库。这里我们就必须实现对对象的改变的跟踪记录,我们实现对象的改变跟踪有许多方式,大致我尝试了两种方式:1:对象强制实现接口,State守信和MakeMark行为。2:利用字典序继续改变。虽然1的方式是否更加合理,但是在winform中与BindingSource集合使用简化修增修改的书写,配合的不是很好,供给开发人员使用不是很爽。于是我修改成为第二种方式集合记录更改,在继续在原集合真实修改,触发BindingSource事件和与BindingSource很好的结合。

   我们所要做的是对集合实体的变化做记录,这个在微软类库中的System.Data.DataTable一样,利用一套变化记录机制,我们可以抽象出我们接口:

public  interface IObjectObserveable

{

bool IsCanReject

{

get;

}

void AcceptChanged();

void RejectChanged();

event ObjectCollectionChanged objectCollectionChanged;

IEnumerable<KeyValuePair< object, ObjectObserveChangeState>> GetChangeds();

IEnumerable< object> GetChangeds(ObjectObserveChangeState changedState);

}

public  enum ObjectObserveChangeState

{

None, Add, Modify, Delete

}
接口中: 

1:包含守信IsCanReject表示是否可以回滚(必须是可序列化的集合者可以回滚,内部利用序列化实现单级撤销)。

2:AcceptChanged表示接受更改。

3:RejectChanged拒绝更改回滚。

4:GetChangeds获取数据集合的更改或者某类型更改的集合。

数据更改通知事件:

View Code
public  class ObjectCollectionChangedEventArgs : EventArgs
    { 

         public ObjectObserveChangeState ChangeState
        {
             get;
             private  set;
        } 

         public  object ItemValue
        {
             get;
             private  set;
        } 

         public ObjectCollectionChangedEventArgs(ObjectObserveChangeState changeState,  object itemValue)
        {
             this.ChangeState = changeState;
             this.ItemValue = itemValue;
        }
    } 

     public  delegate  void ObjectCollectionChanged( object sender, ObjectCollectionChangedEventArgs e);

最后对于List集合的实现如下: 

View Code
public  class ObjectObserveCollection : IList, IDisposable, IObjectObserveable

{

private IList collection;

private Dictionary< object, ObjectObserveChangeState> itemChangedCollection =  new Dictionary< object, ObjectObserveChangeState>();

public  event ObjectCollectionChanged objectCollectionChanged =  null;

private  byte[] _seriable;

public ObjectObserveCollection(IList list)

{

collection = list;

IsCanReject = list.GetType().IsSerializable;

if (IsCanReject)

{

try

{

_seriable = UtilsSerializer.BinarySerializer(list);

}

catch (Exception ex)

{

IsCanReject =  false;

}

}

try

{

RegisterNotifyPropertyChanged(list.OfType<INotifyPropertyChanged>());

}

catch (Exception ex)

{

throw  new Exception( " The collection model must implement the interface of INotifyPropertyChanged; ");

}

}

protected  void RegisterNotifyPropertyChanged(IEnumerable<INotifyPropertyChanged> notifyCollection)

{

notifyCollection.ToList().ForEach(t =>

{

t.PropertyChanged += t_PropertyChanged;

});

}

protected  void t_PropertyChanged( object sender, PropertyChangedEventArgs e)

{

if (!itemChangedCollection.ContainsKey(sender))

{

itemChangedCollection.Add(sender, ObjectObserveChangeState.Modify);

}

}

#region IList 成员

public  int Add( object value)

{

var index =  this.collection.Add(value);

this.OnObjectCollectionChanged( new ObjectCollectionChangedEventArgs(ObjectObserveChangeState.Add, value));

return index;

}

protected  void OnObjectCollectionChanged(ObjectCollectionChangedEventArgs e)

{

RecoredChanged(e);

if ( this.objectCollectionChanged !=  null)

{

this.objectCollectionChanged( this, e);

}

}

protected  void RecoredChanged(ObjectCollectionChangedEventArgs e)

{

switch (e.ChangeState)

{

case ObjectObserveChangeState.Add:

this.itemChangedCollection.Add(e.ItemValue, e.ChangeState);

RegisterNotifyPropertyChanged( new List<INotifyPropertyChanged>() { e.ItemValue  as INotifyPropertyChanged });

break;

case ObjectObserveChangeState.Delete:

if (itemChangedCollection.ContainsKey(e.ItemValue))

{

switch (itemChangedCollection[e.ItemValue])

{

case ObjectObserveChangeState.Add:

itemChangedCollection.Remove(e.ItemValue);

break;

default:

itemChangedCollection[e.ItemValue] = ObjectObserveChangeState.Delete;

break;

}

}

else

{

itemChangedCollection.Add(e.ItemValue, ObjectObserveChangeState.Delete);

}

(e.ItemValue  as INotifyPropertyChanged).PropertyChanged -= t_PropertyChanged;

break;

default:

if (itemChangedCollection.ContainsKey(e.ItemValue))

{

itemChangedCollection[e.ItemValue] = ObjectObserveChangeState.Modify;

}

else

{

itemChangedCollection.Add(e.ItemValue, ObjectObserveChangeState.Modify);

}

break;

}

}

public  void Clear()

{

foreach ( var item  in  this.collection)

{

OnObjectCollectionChanged( new ObjectCollectionChangedEventArgs(ObjectObserveChangeState.Delete, item));

}

this.collection.Clear();

}

public  bool Contains( object value)

{

return  this.collection.Contains(value);

}

public  int IndexOf( object value)

{

return  this.collection.IndexOf(value);

}

public  void Insert( int index,  object value)

{

this.collection.Insert(index, value);

this.OnObjectCollectionChanged( new ObjectCollectionChangedEventArgs(ObjectObserveChangeState.Add, value));

}

public  bool IsFixedSize

{

get {  return  this.collection.IsFixedSize; }

}

public  bool IsReadOnly

{

get {  return  this.collection.IsReadOnly; }

}

public  void Remove( object value)

{

this.collection.Remove(value);

this.OnObjectCollectionChanged( new ObjectCollectionChangedEventArgs(ObjectObserveChangeState.Delete, value));

}

public  void RemoveAt( int index)

{

var value =  this.collection[index];

this.collection.RemoveAt(index);

this.OnObjectCollectionChanged( new ObjectCollectionChangedEventArgs(ObjectObserveChangeState.Delete, value));

}

public  object  this[ int index]

{

get

{

return  this.collection[index];

}

set

{

this.collection[index] = value;

}

}

#endregion

#region ICollection 成员

public  void CopyTo(Array array,  int index)

{

this.collection.CopyTo(array, index);

}

public  int Count

{

get {  return  this.collection.Count; }

}

public  bool IsSynchronized

{

get {  return  this.collection.IsSynchronized; }

}

public  object SyncRoot

{

get {  return  this.collection.SyncRoot; }

}

#endregion

#region IEnumerable 成员

public IEnumerator GetEnumerator()

{

return  this.collection.GetEnumerator();

}

#endregion

#region IDisposable 成员

public  void Dispose()

{

this.itemChangedCollection.Clear();

this.itemChangedCollection =  null;

}

#endregion

#region IObjectObserveable 成员

public  void AcceptChanged()

{

this.itemChangedCollection.Clear();

if (IsCanReject)

{

_seriable = UtilsSerializer.BinarySerializer( this.collection);

}

}

public IEnumerable<KeyValuePair< object,ObjectObserveChangeState>> GetChangeds()

{

return  this.itemChangedCollection.ToDictionary(t => t.Key, t => t.Value);

}

public IEnumerable< object> GetChangeds(ObjectObserveChangeState changedState)

{

return  this.itemChangedCollection.Where(t => t.Value == changedState).Select(t => t.Key);

}

public  void RejectChanged()

{

if (!IsCanReject)

{

throw  new Exception( "  This method required the collection type must be Serializable; ");

}

this.collection =(IList) UtilsSerializer.BinaryDeserialize( this._seriable);

}

public  bool IsCanReject

{

get;

private  set;

}

#endregion

}

 

在最后WinForm中测试: 

View Code
using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using Green.Utility;

using Green.Config.FrameWork;

namespace WindowsFormsApplication1

{

public  partial  class Form3 : Form

{

public Form3()

{

InitializeComponent();

}

ObjectObserveCollection stus;

int count =  0;

private  void Form3_Load( object sender, EventArgs e)

{

var list =  new List<Student>();

list.Add(GeneratorStu());

stus =  new ObjectObserveCollection(list);

bs =  new BindingSource() { DataSource = stus };

dataGridView1.DataSource = bs;

}

BindingSource bs =  null;

public Student GeneratorStu()

{

return  new Student() { ID = ++count, Name = count.ToString() };

}

private  void button4_Click( object sender, EventArgs e)

{

stus.AcceptChanged();

}

private  void button1_Click( object sender, EventArgs e)

{

var model=bs.AddNew()  as Student;

model.ID = ++count;

model.Name = count.ToString();

}

private  void button2_Click( object sender, EventArgs e)

{

if (bs.Position != - 1)

{

bs.RemoveCurrent();

}

}

private  void button3_Click( object sender, EventArgs e)

{

var add = stus.GetChangeds(ObjectObserveChangeState.Add).ToList();

var delete = stus.GetChangeds(ObjectObserveChangeState.Delete).ToList();

var update = stus.GetChangeds(ObjectObserveChangeState.Modify).ToList();

}

}

[Serializable]

public  class Student : INotifyPropertyChanged

{

private  int _ID;

public  int ID

{

get {  return _ID; }

set

{

if (_ID != value)

{

_ID = value;

OnPropertyChanged( " ID ");

}

}

}

private  string _Name;

public  string Name

{

get {  return _Name; }

set

{

if (_Name != value)

{

_Name = value;

OnPropertyChanged( " Name ");

}

}

}

private  void OnPropertyChanged( string p)

{

if ( this.PropertyChanged !=  null)

{

this.PropertyChanged( thisnew PropertyChangedEventArgs(p));

}

}

#region INotifyPropertyChanged 成员

public  event PropertyChangedEventHandler PropertyChanged;

#endregion

}

}

对于新增和删除我们只需利用BindingSource的,bs.AddNew() 和bs.RemoveCurrent();感觉使用起来方便了吧。最后获取数据更改利用GetChangeds。对于保存后AcceptChanges。 

效果图:

欢迎大家指正和建议,希望能够共同进步,谢谢。

你可能感兴趣的:(WinForm)