Hello everyone,
I found that i can use bindinglist as datasource, now when i implement in a griedview datasource i came up with a problem that i cant track which item has been modified. so i make a little research and found about the INotifyPropertyChanged and will trigger if there is data that has been modified.
but what i need is a list of item that has been modified. not triggering an event for every property of the object that has been modified, and also found out that implementing INotifyPropertyChanged can cause some drawback in performance as i read in some blog.
so i came up inheriting bindinglist and add some features, without implementing NotifyPropertyChanged in the item class.
so this is my solution.
First the IEditableObject
namespace gcsc.Interface
{
public interface IEditableObject
{
bool IsNew();
void IsNew(bool status);
bool IsDirty();
void IsDirty(bool status);
}
}then the class that should be inherited by the item
namespace gcsc.UI
{
public abstract class EditableObject : Interface.IEditableObject
{
private bool _isNew;
private bool _isDirty;
public bool IsNew()
{
return _isNew;
}
public void IsNew(bool status)
{
_isNew = status;
}
public bool IsDirty()
{
return _isDirty;
}
public void IsDirty(bool status)
{
_isDirty = status;
}
}
}then that last is the GCSCBindingList<T> that will inherit the binding list
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using GI = gcsc.Interface;
namespace gcsc.Util
{
public sealed class GCSCBindingList<T> : BindingList<T>
{
private readonly List<T> _removeItems;
private readonly bool _initValues;
public IEnumerable<T> GetRemovedItems()
{
return _removeItems.AsEnumerable();
}
public IEnumerable<T> GetUpdatedItems()
{
foreach (GI.IEditableObject item in this)
{
if (item.IsDirty())
yield return (T)item;
}
}
public IEnumerable<T> GetNewItems()
{
foreach (GI.IEditableObject item in this)
{
if (item.IsNew())
yield return (T)item;
}
}
public GCSCBindingList()
{
if (!typeof(T).ImplementsInterface<GI.IEditableObject>())
throw new ArrayTypeMismatchException("T must implement gcsc.Interface.IEditableObject");
_removeItems = new List<T>();
AllowEdit = true;
AllowNew = true;
AllowRemove = true;
}
public GCSCBindingList(IList<T> list)
{
if (!typeof(T).ImplementsInterface<GI.IEditableObject>())
throw new ArrayTypeMismatchException("T must implement gcsc.Interface.IEditableObject");
_removeItems = new List<T>();
AllowEdit = true;
AllowNew = true;
AllowRemove = true;
_initValues = true;
foreach (var v in list)
base.Add(v);
_initValues = false;
}
protected override void InsertItem(int index, T item)
{
if (!_initValues)
((GI.IEditableObject)item).IsNew(true);
base.InsertItem(index, item);
}
public new void Insert(int index, T item)
{
((GI.IEditableObject)item).IsNew(true);
base.Insert(index, item);
}
protected override void RemoveItem(int index)
{
if (index >= 0 && index < base.Count)
{
var item = base[index];
_removeItems.Add(item);
base.RemoveItem(index);
}
}
}
}Now with the GCSCBindingList<T>
i can retrieve all deleted items and all the new items, but still i cant find a way to collect all edited items.
the IsDirty(bool status) method should set to true if the item has been modified, but i cant find the way to implement this.
Could you help me do this?
this is my sample usage, first the class
public class person : gcsc.UI.EditableObject
{
public person()
{
}
public person(string lastname, string firstname)
{
LastName = lastname;
FirstName = firstname;
}
public override string ToString()
{
return string.Format("{0}, {1} status new:{2}, dirty:{3}", LastName, FirstName, IsNew(), IsDirty());
}
public string FirstName { get; set; }
public string LastName { get; set; }
}then can be used like this
List<person> p = new List<person>();
p.Add(new person("John", "smith"));
p.Add(new person("pual", "carl"));
GB = new gcsc.Util.GCSCBindingList<person>(p);private void simpleButton1_Click(object sender, EventArgs e)
{
GB.RemoveAt(0);
foreach (person p in GB.GetNewItems())
{
XtraMessageBox.Show(p.ToString());
}
foreach (person p in GB.GetRemovedItems())
{
XtraMessageBox.Show(p.ToString());
}
foreach (person p in GB.GetUpdatedItems())
{
MessageBox.Show(p.ToString());
}
}now the GB.GetUpdatedItems() is empty because the IsDirty() is still return false even there is item edited.
Please help me solving this problem.
I Will appreciate for any help will come.
Thank you,
PS. sorry for my bad english