UWP/C#:ObservableCollection 就地排序(无滚动)

Jer*_*yer 2 c# sorting observablecollection uwp

在 UWP 应用程序中,我试图对ObservableCollection绑定到 a 的 a进行排序ListView- 因此collection.OrderBy(..)(创建一个新集合)不是一个选项。

到目前为止,我使用了这种扩展方法:

public static void Sort<TSource, TKey>(this 
ObservableCollection<TSource> source, Func<TSource, TKey> keySelector)
{
    List<TSource> sortedList = source.OrderBy(keySelector).ToList();
    source.Clear();
    foreach (var sortedItem in sortedList)
    {
        source.Add(sortedItem);
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,通过这种方式,当前的“滚动偏移”被重置, source.Clear()并且相应的ListView滚动一直回到顶部 - 这是非常糟糕的用户体验。

有任何想法吗?

Jus*_* XL 7

您可以尝试创建一个临时集合,其中包含原始集合中的所有项目,对其进行排序,然后循环遍历其项目,并仅对需要更新的位置重新排序。像这样的东西——

public static void Sort<TSource, TKey>(this ObservableCollection<TSource> source, Func<TSource, TKey> keySelector)
{
    var sortedSource = source.OrderBy(keySelector).ToList();

    for (var i = 0; i < sortedSource.Count; i++)
    {
        var itemToSort = sortedSource[i];

        // If the item is already at the right position, leave it and continue.
        if (source.IndexOf(itemToSort) == i)
        {
            continue;
        }

        source.Remove(itemToSort);
        source.Insert(i, itemToSort);
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,您将希望ListView在项目动画时保持滚动偏移。这可以通过设置来完成 -

<ItemsPanelTemplate>
    <ItemsStackPanel ItemsUpdatingScrollMode="KeepScrollOffset" />
</ItemsPanelTemplate>
Run Code Online (Sandbox Code Playgroud)

我发现这个与 UX 相关的问题非常有趣,我什至为此创建了一个小演示项目。:)下面的gif演示了最终结果。对我来说,它提供了更好的体验,因为我在视觉上知道哪些项目是或不通过排序重新定位的。

ListView排序动画