排序列表 vs. 可观察集合

4
我发现我在“错误地使用WPF”,必须彻底检查我的代码。如何转换以下内容:
public static class SortName 
    {
       public static  int Compare(Person a, Person b)
        {
            return a.Name.CompareTo(b.Name);
        }

    }

我称其为:

list.Sort(SortName.Compare);

将其转换为ObservableCollection所需的格式。我该如何调用它?到目前为止,我尝试了以下内容,基于我在这里读到的。

class ObservableCollectionSortName<T> : ObservableCollection<T> 
{
    public int Compare (Person a, Person b)
    {
        return a.Name.CompareTo(b.Name);
    }
}

1
我不确定关于“错误地使用WPF”的评论。仅仅因为你在使用WPF,并不意味着所有东西都必须是可观察的集合(observable collection)。如果你不需要对集合中的变化做出反应,那么将其设置为可观察的集合就是浪费资源。 - Jim Anderson
哦,我明白了。这就是我一开始使用列表的原因。问题是我确实需要对集合中的更改做出反应。 - baron
2个回答

14

可观察集合并未实现排序功能,因为每次项目从列表中的一个位置移动到另一个位置时,该集合就会引发事件。这对于观察排序算法的动画非常好,但对于排序来说却不太理想。

有两种方法可以解决这个问题;它们非常相似,并且都从对可观察集合之外的项目进行排序开始,例如如果_FruitsObservableCollection<Fruit>,并且您已经为排序定义了一个IComparer<Fruit>,则需要执行以下操作:

var sorted = _Fruits.OrderBy(x => x, new FruitComparer());

这将创建一个新的 IEnumerable<Fruit>,当您迭代它时,其中的对象将按新顺序排列。您可以使用此方法完成两件事情。

一种方法是创建一个新集合,替换旧集合,并强制 UI 中的任何项控件重新绑定到它:

_Fruits = new ObservableCollection<Fruit>(sorted);
OnPropertyChanged("Fruits");

(这假设你的类按照通常的方式实现了INotifyPropertyChanged。)

另一种方法是创建一个新的已排序列表,然后使用它来移动你的集合中的项:

int i = 0;
foreach (Fruit f in sorted)
{
   _Fruits.MoveItem(_Fruits.IndexOf(f), i);
   i++;
}

如果我非常注重不重新绑定项目控件,那么第二种方法是我只会尝试的方法,因为它会引发大量的集合更改事件。


如果您绑定到集合,最好在CollectionView上添加排序,就像mattythomas2000建议的那样,因为隐式的CollectionView无论如何都会被使用。 - Grokys

3
如果你需要按照特定顺序展示数据给用户而不是为了提高性能(比如更快的访问),那么可以使用CollectionViewSource。Bea Stollnitz在她的博客中详细描述了如何使用CollectionViewSource来实现对UI集合的排序和分组,这可能会帮助你,因为它意味着你不必对observable collection进行排序,也不用担心发送INotifyCollectionChanged所带来的性能损失。但是,它将允许在UI中按照排序顺序显示项目。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接