2017-06-01 102 views
2

在UWP應用程序中,我試圖對ObservableCollection進行排序,它綁定到ListView--因此collection.OrderBy(..)(它創建了一個新的集合)不是一個選項。UWP/C#:ObservableCollection排序就地(沒有滾動)

直到現在我用這個擴展法:

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()和相應的ListView滾動所有的方式回到頂端 - 這是非常不好的用戶體驗。

任何想法?

+0

我不熟悉你問我該問你試圖保存對象「滾動偏移」 source.Clear前(),並再次重置價值,這可能會有幫助。 –

+0

這將是我'最後的手段'。它可能會工作,但與source.Clear()清單將首先滾動到頂部,然後重置到存儲的'滾動偏移'不久。那看起來很奇怪。 –

回答

3

你可以嘗試什麼是創建一個臨時集合,其中包含從原始集合中的所有項目,排序,然後循環通過它的項目,只重新排序需要更新的位置。事情是這樣的 -

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最終結果。對我而言,它提供了一種更好的體驗,因爲我可以直觀地瞭解,哪些項目是否通過排序重新定位。

ListView sorting animation

+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);