WinForm中实体类批量修改、批量提交辅助类
2012-03-27 11:47 破狼 阅读(3387) 评论(15) 编辑 收藏 举报在WinForm项目开发中习惯于对于集合数据的批量修改,再一次性提交更新同步到数据库。这里我们就必须实现对对象的改变的跟踪记录,我们实现对象的改变跟踪有许多方式,大致我尝试了两种方式:1:对象强制实现接口,State守信和MakeMark行为。2:利用字典序继续改变。虽然1的方式是否更加合理,但是在winform中与BindingSource集合使用简化修增修改的书写,配合的不是很好,供给开发人员使用不是很爽。于是我修改成为第二种方式集合记录更改,在继续在原集合真实修改,触发BindingSource事件和与BindingSource很好的结合。
我们所要做的是对集合实体的变化做记录,这个在微软类库中的System.Data.DataTable一样,利用一套变化记录机制,我们可以抽象出我们接口:
{
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获取数据集合的更改或者某类型更改的集合。
数据更改通知事件:
{
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集合的实现如下:
{
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中测试:
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(this, new PropertyChangedEventArgs(p));
}
}
#region INotifyPropertyChanged 成员
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
对于新增和删除我们只需利用BindingSource的,bs.AddNew() 和bs.RemoveCurrent();感觉使用起来方便了吧。最后获取数据更改利用GetChangeds。对于保存后AcceptChanges。
效果图:
欢迎大家指正和建议,希望能够共同进步,谢谢。
作者:破 狼
出处:http://www.cnblogs.com/whitewolf/
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客、博客园--破狼和51CTO--破狼。