问题
I have a very simple class: People:
class People
{
private string LastName = null;
private string FirstName = null;
private string Status = null;
public string lastName
{
get { return LastName; }
set { LastName = value; }
}
public string firstName
{
get { return FirstName; }
set { FirstName = value; }
}
public string status
{
get { return Status; }
set { Status = value; }
}
public People(string lastName, string firstName, string status)
{
LastName = lastName;
FirstName = firstName;
Status = status;
}
}
And, I have another class that implements the interface IList<>, which is meant to be used as a collection of the People class, called PeopleList<>. PeopleList<> is special because I am directly binding an instance of this class to a DataGridView. Normally, I would never use an IList<> as a datasource for a datagridview (DGV) for one important reason: an IList does not generate the ListChanged event, which means that once you bind the DGV to the IList<> the number of rows in the DGV is set. In other words, if new items are added to the IList<>, the DGV will not show them! The only way to get that to work is to set the datasource of the DGV to null, and then rebind it to the IList<> after the change is made.
A BindingList is much more suited to this type of need, but alas, for reasons I can't go into, it is imperative that I use an IList<> as the interface. To get around this problem, I have found some code that supposedly integrates the ListChanged event into an implementation of the IList<> interface, but I am having some trouble with it. It seems like even with this code I would have to have an event handler method right? And at some point I would have to declare this method as the handler for the ListChanged event? Have a look:
class PeopleList<T> : IList<T>
{
private IList<T> internalList;
public class ListChangedEventArgs : EventArgs {
public int index;
public T item;
public ListChangedEventArgs(int index, T item) {
this.index = index;
this.item = item;
}
}
public delegate void ListChangedEventHandler(object source, ListChangedEventArgs e);
public delegate void ListClearedEventHandler(object source, EventArgs e);
public event ListChangedEventHandler ListChanged;
public event ListClearedEventHandler ListCleared;
public PeopleList() {
internalList = new List<T>();
}
public PeopleList(IList<T> list) {
internalList = list;
}
public PeopleList(IEnumerable<T> collection) {
internalList = new List<T>(collection);
}
protected virtual void OnListChanged(ListChangedEventArgs e) {
if (ListChanged != null)
ListChanged(this, e);
}
protected virtual void OnListCleared(EventArgs e) {
if (ListCleared != null)
ListCleared(this, e);
}
public int IndexOf(T item) {
return internalList.IndexOf(item);
}
public void Insert(int index, T item) {
internalList.Insert(index, item);
OnListChanged(new ListChangedEventArgs(index, item));
}
public void RemoveAt(int index) {
T item = internalList[index];
internalList.Remove(item);
OnListChanged(new ListChangedEventArgs(index, item));
}
T this[int index] {
get { return internalList[index]; }
set {
internalList[index] = value;
OnListChanged(new ListChangedEventArgs(index, value));
}
}
public void Add(T item) {
internalList.Add(item);
OnListChanged(new ListChangedEventArgs(internalList.IndexOf(item), item));
}
public void Clear() {
internalList.Clear();
OnListCleared(new EventArgs());
}
public bool Contains(T item) {
return internalList.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex) {
internalList.CopyTo(array, arrayIndex);
}
public int Count {
get { return internalList.Count; }
}
public bool IsReadOnly {
get { return IsReadOnly; }
}
public bool Remove(T item) {
lock(this) {
int index = internalList.IndexOf(item);
if (internalList.Remove(item)) {
OnListChanged(new ListChangedEventArgs(index, item));
return true;
}
else
return false;
}
}
public IEnumerator<T> GetEnumerator() {
return internalList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return ((IEnumerable) internalList).GetEnumerator();
}
T IList<T>.this[int index]
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
FYI - I am designing in VS2010.
Any guidance would be greatly appreciated... Thanks!
回答1:
Ok, so I didn't hear back, and there doesn't appear to be a way to make this work without serious side effects. I ended up just gutting my code and basing my list class on System.ComponentModel.BindingList<> which seems to be working ok. I knew that this was a possibility (as I mentioned in my question) but was hoping to avoid the tedious labor of changing out the base class as I wasn't the one who wrote the original code. Oh wells. =)
来源:https://stackoverflow.com/questions/5421806/c-sharp-update-datagridview-based-on-ilist