[英]C# Inherited class BindingList<T> doesn't update controls
I have a class which inherits from BindingList to apply sorting to a bindinglist. 我有一个从BindingList继承的类,将排序应用于绑定列表。 The sorting works fine, but when I add or remove an item from the list the bounded control isn't updated.
排序工作正常,但是当我从列表中添加或删除项目时,绑定控件不会更新。 I think i miss something in the class, but I don't know what.
我想我在课堂上想念什么,但我不知道。
I've found the code of the class somewhere online, but I don't know where I found it. 我已经在网上某个地方找到了该类的代码,但是我不知道在哪里找到它。 My question is, why does this class doesn'u update my control when I update or remove items from the list?
我的问题是,当我从列表中更新或删除项目时,为什么此类不更新控件?
Here is the complete class 这是完整的课程
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
}
Cannot reproduce; 无法复制; it seems fine here:
在这里看起来很好:
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; }
}
Can you give a reproducible example where it doesn't update? 您可以举一个没有更新的可复制示例吗?
Re the comments: the code is using something comparable to: 重新评论:该代码正在使用类似于:
data = new BindingList<Foo>(someOtherData.Where(lambda).ToList());
Now, if we add to someOtherData
, we indeed won't notice any difference. 现在, 如果我们添加到
someOtherData
,我们确实不会注意到任何区别。 A slight peculiarity of Collection<T>
is that if you pass a list into the constructor, that list does become the actual backing list, but: Collection<T>
一个特殊之处是,如果将列表传递给构造函数,则该列表确实成为实际的后备列表,但是:
a: it can't raise any events unless it knows about it; 答:除非知道,否则无法引发任何事件; the only way it can know is if it sees the addition , ie the addition goes through
BindingList<T>.Add
, not the backing list's Add
. 它唯一知道的方法是是否看到附加项 ,即附加项通过
BindingList<T>.Add
而不是后备列表的Add
。 This can cause the odd effect that reloading or rebinding the data can make items magically appear (in some cases, not this one). 这可能会导致奇怪的效果,即重新加载或重新绑定数据会使项目神奇地出现(在某些情况下,不是这种情况)。
b: in this case, the backing list is not someOtherData
, but a separate list generated by LINQ ( ToList()
), so even adding something to someOtherData
will never cause the binding-lists backing list to see the new item. b:在这种情况下,后备列表不是
someOtherData
,而是由LINQ( ToList()
)生成的单独列表,因此即使向someOtherData
添加内容也不会导致绑定列表后备列表看到新项目。
In short: you need to treat the binding-list as the "master" if you expect data changes to propagate. 简而言之:如果您希望数据更改能够传播,则需要将绑定列表视为“主”。 Else;
其他; re-bind the data.
重新绑定数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.