BindingSource不在Insert上修改其DataSource

时间:2014-01-16 15:43:23

标签: c# winforms data-binding

我有一个ListBox,其DataSource是一个BindingSource。 BindingSource的DataSource是我编写的实现IList< T>的自定义类。当用户为列表中的新项输入数据时,我通过使用新项调用BindingSource.Insert()来更新BindingSource。这会将项添加到ListBox,但它似乎不会修改作为BindingSource的DataSource的基础列表。

当我尝试用普通的List< 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;
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这似乎是BindingSource类的预期行为。请参阅Microsoft关于BindingSource.DataSource属性的文档中的“备注”部分:

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

由于DataSource可以设置为许多不同类型的对象,因此许多类型都有自定义行为。 List&lt; T&gt;类型的DataSource的行为显然是要包装List&lt; T&gt;在BindingList&lt; T&gt;中,而实现IEnumerable&lt; T&gt;的其他类的行为。是创建一个新的BindingList&lt; T&gt;来自IEnumerable&lt; T&gt;的项目。被复制。因为我的FilteredList&lt; T&gt; class没有从List&lt; T&gt;继承,它得到了“不太特殊的处理”,并被作为通用IEnumerable&lt; T&gt;处理。而不是List&lt; T&gt;。不幸的是,出于我的目的,但可以理解。

由于得出这个结论,我偶然发现了另一个有用的信息:如果你创建一个BindingList&lt; T&gt;你自己,传递一个IList&lt; T&gt;到构造函数,然后分配这个BindingList&lt; T&gt;对于BindingSource的DataSource属性,一切正常,对BindingSource所做的更改都会反映在原始列表中。