在UWP应用中,我正在尝试对绑定到ObservableCollection
的{{1}}进行排序 - 因此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);
}
}
而被重置,并且相应的source.Clear()
滚动一直回到顶部 - 这是非常糟糕的用户体验。
有什么想法吗?
答案 0 :(得分:4)
您可以尝试创建一个 temp 集合,其中包含原始集合中的所有项目,对其进行排序,然后循环遍历其项目,并仅重新排序需要的位置。得到更新。像这样的东西 -
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);
}
}
此外,您希望ListView
在项目动画时保持滚动偏移。这可以通过设置 -
<ItemsPanelTemplate>
<ItemsStackPanel ItemsUpdatingScrollMode="KeepScrollOffset" />
</ItemsPanelTemplate>
我发现这个与UX相关的问题非常有趣,我甚至最终为它创建了一个demo project。 :)下面的 gif 演示了最终结果。对我而言,它提供了一种更好的体验,因为我在视觉上知道,哪些项目是通过排序重新定位的。
答案 1 :(得分:1)
前一段时间我正在处理同样的问题而且我最终得到了这个问题:
Func<TempoMarking, IComparable> selectorGetter = null;
// Setting the selectorGetter here
for (int i = 0; i < Collection.Count; i++)
{
for (int j = 0; j < Collection.Count - 1; j++)
{
YourType currentItem = Collection[j];
if (selectorGetter(currentItem).CompareTo(selectorGetter(Collection[j + 1])) == 1)
{
Collection.Remove(currentItem);
Collection.Insert(j + 1, currentItem);
}
}
}
它可能不是最好的解决方案,它在L640这样的手机上有点落后但是它有效。如果您需要滚动到ListView
中的某个项目,可以使用以下方法:
YourListView.ScrollIntoView(ListViewItemToScrollTo);