c# 基于IList更新Datagridview
我有一个非常简单的类: 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;
}
}
而且,我有另一个实现接口 IList<> 的类,该类旨在用作 People 类的集合,称为 PeopleList<>。人员列表>>很特别,因为我直接将此类的实例绑定到 DataGridView。通常,我永远不会使用 IList<>作为 datagridview (DGV) 的数据源,有一个重要原因:IList 不会生成 ListChanged 事件,这意味着一旦将 DGV 绑定到 IList<> DGV 中的行数已设置。换句话说,如果将新项目添加到 IList<>,DGV 将不会显示它们!使其工作的唯一方法是将 DGV 的数据源设置为 null,然后将其重新绑定到 IList<> 。更改后。
BindingList 更适合这种类型的需求,但可惜的是,由于我无法详细说明的原因,我必须使用 IList<> 。作为界面。为了解决这个问题,我发现了一些代码,据称这些代码将 ListChanged 事件集成到 IList<> 的实现中。界面,但我在使用它时遇到了一些问题。似乎即使有了这段代码,我也必须有一个事件处理程序方法,对吗?在某些时候我必须将此方法声明为 ListChanged 事件的处理程序?看一下:
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();
}
}
}
仅供参考 - 我正在 VS2010 中进行设计。
任何指导将不胜感激...谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,所以我没有收到回复,而且似乎没有一种方法可以在没有严重副作用的情况下完成这项工作。我最终只是删除了我的代码并将我的列表类基于 System.ComponentModel.BindingList<>这似乎工作正常。我知道这是一种可能性(正如我在问题中提到的),但希望避免更改基类的繁琐工作,因为我不是编写原始代码的人。噢,井。 =)
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. =)