代码改变世界

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

2012-03-27 11:47  破狼  阅读(3387)  评论(15编辑  收藏  举报

    在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。 

效果图:

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