c# Обновление Datagridview на основе IList

У меня очень простой класс: Люди:

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‹>. PeopleList‹> особенный, потому что я напрямую привязываю экземпляр этого класса к DataGridView. Обычно я бы никогда не использовал IList‹> в качестве источника данных для datagridview (DGV) по одной важной причине: IList не генерирует событие ListChanged, что означает, что после привязки DGV к IList‹> число строк в ДГВ установлено. Другими словами, если в 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.

Мы будем очень признательны за любые рекомендации... Спасибо!


person Chris Barlow    schedule 24.03.2011    source источник


Ответы (1)


Итак, я не получил ответа, и, похоже, нет способа заставить это работать без серьезных побочных эффектов. В итоге я просто выпотрошил свой код и основал свой класс списка на System.ComponentModel.BindingList‹>, который, кажется, работает нормально. Я знал, что это возможно (как я упоминал в своем вопросе), но надеялся избежать утомительной работы по изменению базового класса, поскольку я не был тем, кто написал исходный код. О, колодцы. знак равно

person Chris Barlow    schedule 01.04.2011
comment
BindingList‹T› реализует IList‹T›, поэтому вы можете использовать экземпляр BindingList‹T› везде, где свойство или параметр имеют тип IList‹T›. Вы можете передать ЛЮБОЙ класс, реализующий IList‹T›, в этом весь смысл интерфейса. - person Joel C; 01.04.2011
comment
Неважно, я перечитал и понял, что если ваш источник данных определен как IList‹T›, то даже если вы используете фактический экземпляр BindingList, я не думаю, что его событие ListChanged будет правильно подключено к обработчику на вашем DGV . - person Joel C; 01.04.2011
comment
Вероятно, вам следует использовать IBindingList<T> вместо вашего класса, который наследуется от BindingList<T>, когда вы делаете это, просто чтобы тому, кто последует за вами, не пришлось проходить снова в будущем, если требования снова изменятся;) - person Joel C; 02.04.2011