2014-01-16 4 views
1

У меня есть ListBox, DataSource которого является источником BindingSource. Этот DataSource BindingSource является специальным классом, который я написал, который реализует IList < T>. Когда пользователь вводит данные для нового элемента в списке, я обновляю BindingSource, вызывая BindingSource.Insert() с новым элементом. Это добавляет элемент в ListBox, но, похоже, он не изменяет базовый список, который является источником данных для BindingSource.BindingSource не меняет свой DataSource при вставке

Когда я пытаюсь сделать то же самое с простым списком < T>, а не с моим пользовательским классом IList (FilteredList < T>), список обновляется BindingSource. Поэтому проблема, похоже, связана с моим обычным классом. Но я поставил точки останова для каждого метода в FilteredList < T>, и ни один из них не вызван, кроме конструктора. Поэтому я в тупике.

Здесь для справки, код для FilteredList < T>:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace AmesView.Encapsulation 
{ 
    public class FilteredList<T>: IList<T> 
    { 
     public delegate bool TestMethod<T>(T item); 

     private IList<T> _innerList; 

     private TestMethod<T> _test; 

     public FilteredList(IList<T> innerList, TestMethod<T> test) 
     { 
      if (innerList == null) 
      { 
       throw new ArgumentException("innerList must not be null"); 
      } 
      if (test == null) 
      { 
       throw new ArgumentException("test must not be null"); 
      } 
      _innerList = innerList; 
      _test = test; 
     } 

     public int IndexOf(T item) 
     { 
      int count = 0; 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        if (item.Equals(tmp)) 
        { 
         break; 
        } 
        count++; 
       } 
      } 
      return count; 
     } 

     public void Insert(int index, T item) 
     { 
      int count = 0; 
      int allidx = 0; 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        if (count == index) 
        { 
         _innerList.Insert(allidx, item); 
         return; 
        } 
        count++; 
       } 
       allidx++; 
      } 
     } 

     public void RemoveAt(int index) 
     { 
      int count = 0; 
      int allidx = 0; 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        if (count == index) 
        { 
         _innerList.RemoveAt(allidx); 
         return; 
        } 
        count++; 
       } 
       allidx++; 
      } 
     } 

     public T this[int index] 
     { 
      get 
      { 
       int count = 0; 
       int allidx = 0; 
       foreach (T tmp in _innerList) 
       { 
        if (_test(tmp)) 
        { 
         if (count == index) 
         { 
          return _innerList[allidx]; 
         } 
         count++; 
        } 
        allidx++; 
       } 
       return default(T); 
      } 
      set 
      { 
       int count = 0; 
       int allidx = 0; 
       foreach (T tmp in _innerList) 
       { 
        if (_test(tmp)) 
        { 
         if (count == index) 
         { 
          _innerList[allidx] = value; 
         } 
         count++; 
        } 
        allidx++; 
       } 
      } 
     } 

     public void Add(T item) 
     { 
      _innerList.Add(item); 
     } 

     public void Clear() 
     { 
      _innerList.Clear(); 
     } 

     public bool Contains(T item) 
     { 
      foreach (T tmp in _innerList) 
      { 
       if (tmp.Equals(item) && _test(tmp)) 
       { 
        return true; 
       } 
      } 
      return false; 
     } 

     public void CopyTo(T[] array, int arrayIndex) 
     { 
      int count = 0; 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        int idx = arrayIndex + count; 
        if (idx < array.Length) 
        { 
         array[idx] = tmp; 
        } 
        count++; 
       } 
      } 
     } 

     public int Count 
     { 
      get 
      { 
       int count = 0; 
       foreach (T tmp in _innerList) 
       { 
        if (_test(tmp)) 
        { 
         count++; 
        } 
       } 
       return count; 
      } 
     } 

     public bool IsReadOnly 
     { 
      get 
      { 
       return _innerList.IsReadOnly; 
      } 
     } 

     public bool Remove(T item) 
     { 
      return _innerList.Remove(item); 
     } 

     public IEnumerator<T> GetEnumerator() 
     { 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        yield return tmp; 
       } 
      } 
     } 

     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      foreach (T tmp in _innerList) 
      { 
       if (_test(tmp)) 
       { 
        yield return tmp; 
       } 
      } 
     } 
    } 
} 

ответ

0

Это, как представляется, предполагаемое поведение класса BindingSource. Смотрите раздел Замечания в документации Microsoft по собственности BindingSource.DataSource:

http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.datasource%28v=vs.110%29.aspx

Поскольку DataSource может быть установлен множество различных типов объектов, есть нестандартное поведение для многих типов. Поведение для DataSource типа List < T>, по-видимому, должно обернуть список < T> в BindingList < T>, тогда как поведение для других классов, реализующих IEnumerable < T>, должно создать новый BindingList < T>, в который копируются элементы из IEnumerable < T>. Поскольку мой FilteredList < T> класс не наследовал из списка < T>, он получил «менее специальное лечение» и обрабатывался как общий IEnumerable < T>, а не List < T>. Несчастливо, для моих целей, но понятно.

С приходом к такому выводу, я наткнулся на другой полезный бит информации: если вы создаете BindingList < T> себя, передавая IList < T> в конструктор, а затем присвоить этот BindingList < T> в DataSource свойство вашего BindingSource, все работает и изменения, внесенные в BindingSource, отражаются в исходном списке.

Смежные вопросы