繁体   English   中英

C#继承的类BindingList <T> 不更新控件

[英]C# Inherited class BindingList<T> doesn't update controls

我有一个从BindingList继承的类,将排序应用于绑定列表。 排序工作正常,但是当我从列表中添加或删除项目时,绑定控件不会更新。 我想我在课堂上想念什么,但我不知道。

我已经在网上某个地方找到了该类的代码,但是我不知道在哪里找到它。 我的问题是,当我从列表中更新或删除项目时,为什么此类不更新控件?

这是完整的课程

public class SortableBindingList<T> : BindingList<T>
{
    #region Membar variables
    private bool _isSortedValue;
    private ArrayList _sortedList;
    private ArrayList _unsortedItems;
    private PropertyDescriptor _sortPropertyValue;
    private ListSortDirection _sortDirectionValue;
    #endregion

    #region Constructor
    public SortableBindingList()
    {
    }

    public SortableBindingList(IList<T> list):base(list)
    {
    }
    #endregion

    #region Overrided Properties
    protected override bool SupportsSearchingCore
    {
        get { return true; }
    }
    protected override bool SupportsSortingCore
    {
        get { return true; }
    }
    protected override bool IsSortedCore
    {
        get { return _isSortedValue; }
    }

    protected override PropertyDescriptor SortPropertyCore
    {
        get { return _sortPropertyValue; }
    }

    protected override ListSortDirection SortDirectionCore
    {
        get { return _sortDirectionValue; }
    }
    #endregion

    #region Public methods
    public int Find(string property, object key)
    {
        // Check the properties for a property with the specified name.
        PropertyDescriptorCollection properties =
            TypeDescriptor.GetProperties(typeof(T));
        PropertyDescriptor prop = properties.Find(property, true);

        // If there is not a match, return -1 otherwise pass search to
        // FindCore method.
        if (prop == null)
            return -1;
        else
            return FindCore(prop, key);
    }

    public void RemoveSort()
    {
        RemoveSortCore();
    }

    public void Sort(string property, ListSortDirection direction)
    {
        // Get all the properties of the object T
        PropertyDescriptorCollection properties = 
            TypeDescriptor.GetProperties(typeof(T));

        // Find the specified property in de collection and ignore case
        PropertyDescriptor prop = properties.Find(property, true);

        if (prop != null)
            ApplySortCore(prop, direction);
    }
    #endregion

    #region Overrided methods
    // The FindCore method searches a list and returns the index of a found item
    protected override int FindCore(PropertyDescriptor prop, object key)
    {
        // Get the property info for the specified property.
        PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
        T item;

        if (key != null)
        {
            // Loop through the items to see if the key
            // value matches the property value.
            for (int i = 0; i < Count; ++i)
            {
                item = (T)Items[i];
                if (propInfo.GetValue(item, null).Equals(key))
                    return i;
            }
        }
        return -1;

    }

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
    {
        _sortedList = new ArrayList();

        // Check to see if the property type we are sorting by implements
        // the IComparable interface.
        Type interfaceType = prop.PropertyType.GetInterface("IComparable");

        if (interfaceType != null)
        {
            // If so, set the SortPropertyValue and SortDirectionValue.
            _sortPropertyValue = prop;
            _sortDirectionValue = direction;

            _unsortedItems = new ArrayList(this.Count);

            // Loop through each item, adding it the the sortedItems ArrayList.
            foreach (Object item in this.Items)
            {
                _sortedList.Add(prop.GetValue(item));
                _unsortedItems.Add(item);
            }
            // Call Sort on the ArrayList.
            _sortedList.Sort();
            T temp;

            // Check the sort direction and then copy the sorted items
            // back into the list.
            if (direction == ListSortDirection.Descending)
                _sortedList.Reverse();

            for (int i = 0; i < this.Count; i++)
            {
                int position = Find(prop.Name, _sortedList[i]);
                if (position != i)
                {
                    temp = this[i];
                    this[i] = this[position];
                    this[position] = temp;
                }
            }

            _isSortedValue = true;

            // Raise the ListChanged event so bound controls refresh their
            // values.
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
        else
            // If the property type does not implement IComparable, let the user
            // know.
            throw new NotSupportedException("Cannot sort by " + prop.Name +
                ". This" + prop.PropertyType.ToString() +
                " does not implement IComparable");

    }

    protected override void RemoveSortCore()
    {
        int position;
        object temp;

        // Ensure the list has been sorted.
        if (_unsortedItems != null)
        {
            // Loop through the unsorted items and reorder the
            // list per the unsorted list.
            for (int i = 0; i < _unsortedItems.Count; )
            {
                position = this.Find(_sortPropertyValue.Name,
                    _unsortedItems[i].GetType().GetProperty(_sortPropertyValue.Name).GetValue(_unsortedItems[i], null));

                if (position > 0 && position != i)
                {
                    temp = this[i];
                    this[i] = this[position];
                    this[position] = (T)temp;
                    i++;
                }
                else if (position == i)
                    i++;
                else
                    // If an item in the unsorted list no longer exists,
                    // delete it.
                    _unsortedItems.RemoveAt(i);
            }

            _isSortedValue = false;

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

    }
    #endregion
}

无法复制; 在这里看起来很好:

static class Program
{
    [STAThread]
    static void Main()
    {
        Button btn;
        var data = new SortableBindingList<Foo> { new Foo { Bar = "abc" } };
        using (var form = new Form
        {
            Controls = {
                (btn = new Button { Dock = DockStyle.Bottom, Text = "add"}),
                new DataGridView { Dock = DockStyle.Fill, DataSource = data,
                    AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells }
            }
        })
        {
            btn.Click += delegate { data.Add(new Foo { Bar = DateTime.Now.Ticks.ToString()}); };
            Application.Run(form);
        }
    }
}
class Foo
{
    public string Bar { get; set; }
}

您可以举一个没有更新的可复制示例吗?


重新评论:该代码正在使用类似于:

data = new BindingList<Foo>(someOtherData.Where(lambda).ToList());

现在, 如果我们添加到someOtherData ,我们确实不会注意到任何区别。 Collection<T>一个特殊之处是,如果将列表传递给构造函数,则该列表确实成为实际的后备列表,但是:

答:除非知道,否则无法引发任何事件; 它唯一知道的方法是是否看到附加项 ,即附加项通过BindingList<T>.Add而不是后备列表的Add 这可能会导致奇怪的效果,即重新加载或重新绑定数据会使项目神奇地出现(在某些情况下,不是这种情况)。

b:在这种情况下,后备列表不是someOtherData ,而是由LINQ( ToList() )生成的单独列表,因此即使向someOtherData添加内容也不会导致绑定列表后备列表看到新项目。

简而言之:如果您希望数据更改能够传播,则需要将绑定列表视为“主”。 其他; 重新绑定数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM