SortedList没有';I don’我好像在整理
本文关键字:don 没有 SortedList | 更新日期: 2023-09-27 18:22:20
我围绕SortedList创建了一个包装类。我向这个类添加对象,希望它们能自动按字母顺序排序,但当我绑定到WPF中的ListBox时,我会看到它们按未排序的顺序排列。
public class SortedObservableCollection<T> : ICollection<T>, INotifyPropertyChanged, INotifyCollectionChanged where T : INotifyPropertyChanged//, IComparable<T>
{
private readonly SortedList<string,T> _innerSortedList;
public SortedObservableCollection()
{
_innerSortedList = new SortedList<string, T>();
}
public void Add(T item)
{
_innerSortedList.Add(item.ToString(), item);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item);
item.PropertyChanged += ItemPropertyChanged;
}
void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public void Clear()
{
_innerSortedList.Clear();
}
public bool Contains(T item)
{
return _innerSortedList.ContainsKey(item.ToString());
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { return _innerSortedList.Count; }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(T item)
{
bool success = _innerSortedList.Remove(item.ToString());
if (success)
{
item.PropertyChanged -= ItemPropertyChanged;
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item);
}
return success;
}
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _innerSortedList.GetEnumerator();
}
protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = "")
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, object item)
{
if (this.CollectionChanged != null)
{
this.CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event NotifyCollectionChangedEventHandler CollectionChanged;
}
绑定我只需:
SortedObservableCollection<IRCUser> Users { get; private set; }
.. fill users...
lstUsers.ItemsSource = users;
样本输入:
5Muhammad0
2Muhammad1
5Muhammad2
输出也显示出类似的情况,以2、4等开头的输出在5之间千疮百孔。
注意:我的IRCUser
类确实实现了IComparable,但由于我现在只想要一个字母排序,我对实现进行了注释,希望默认排序能够生效。
注2:我已经覆盖了toString()方法,我忘了提到它:
public override string ToString()
{
return (int)Type + Nick;
}
更新:
在内部,sortedList
似乎保持着正确的顺序,但它并没有以正确的顺序传递给ListBox
。。。
您没有正确创建事件对象NotifyCollectionChangedEventArgs。根据操作的不同,此对象具有不同的构造函数重载。创建新项目时,必须使用使用新项目索引的重载:
new NotifyCollectionChangedEventArgs(action, item, index)
这里引用MSDN的话:
初始化NotifyCollectionChangedEventArgs的新实例描述添加或删除更改的类。
NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction, Object, Int32)
更新0
此外,最好不要使用方法ToString
的重载来比较项目,并为此使用特殊的IComparer<TKey>
。在您的情况下,正确的代码如下所示:
public void Add(T item)
{
var key = item.ToString();
_innerSortedList.Add(key, item);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, _innerSortedList.IndexOfKey(key)));
item.PropertyChanged += ItemPropertyChanged;
}
public bool Remove(T item)
{
var indexOfKey = _innerSortedList.IndexOfKey(item.ToString());
if (indexOfKey == -1)
return false;
_innerSortedList.RemoveAt(indexOfKey);
item.PropertyChanged -= ItemPropertyChanged;
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item,
indexOfKey));
return true;
}
public IEnumerator<T> GetEnumerator()
{
return _innerSortedList.Values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
var handler = this.CollectionChanged;
if (handler != null)
{
handler(this, args);
}
}
有问题
_innerSortedList.Add(item.ToString(), item);
假设项的类型为Project.Test.CustomEntity
,那么item.ToString()
会给您"Project.Test.CustomEntity
",它是按实体的全名而不是值排序的。
您需要根据T.的属性选择器编写一个自定义分类器
看看这篇文章。
我不确定,但:
1) 如果UI有一个数据模板,并且您显示的示例输出没有IRCUser.ToString()的结果,那么ToString()可能不会为排序提供"好"的哈希值。
2) 使用PagedCollectionView包装您的收藏,并在那里设置排序,可能会更好地为您服务。
您正在item.ToString()
上对数据进行排序,这可能不是一个非常有用的排序值。
除非它被重写,否则它将是类的类型名,因此对于您添加的所有内容都是一样的。
这显然引出了一个问题,应该如何对通用数据进行排序。这就是IComparable<T>
的作用。
您会注意到,有几个SortedList<T>
构造函数允许您传递一个IComparable
实现来定义自己的订单。
在任何情况下,如果要使用字符串的默认IComparable
实现,则需要根据所需顺序使用不同的字符串。不要键入完全不同的名称。