c# Metro (Windows Store)保持ListView排序



保持一个ObservableCollection绑定到ListView按字母顺序排序是一个很好的解决方案?似乎是Windows 8。x不提供CollectionViewSource上的排序,所以我需要对ObservableCollection进行排序。

集合需要在适当的排序顺序,每次一个字符串被添加到它,所以我相信我需要的是一个方法来插入数据到适当的位置,而不是将其添加到ObservableCollection,然后排序的集合,但我还没有找到一个好方法来做到这一点。

一种不影响整个集合的插入方法是首先找到新条目插入的索引,然后使用内置的Insert将其添加到集合中。

在这种情况下,扩展方法将是完美的。

public static void InsertInOrder<T>(this IList<T> list, T newItem, IComparer<T> comparer = null)
{
    comparer = comparer ?? Comparer<T>.Default;
    var index = Array.BinarySearch<T>(list.ToArray<T>(), newItem, comparer);
    if (index >= 0)
    {
        throw new ArgumentException("Cannot insert duplicated items");
    }
    else
    {
        list.Insert(~index, newItem);
    }
}

确保你有一个这样的集合,

ObservableCollection<string> _collection = new ObservableCollection<string> { "a", "b", "c", "e", "f" };

然后调用扩展方法,执行

_collection.InsertInOrder("d");

希望这对你有帮助!

ObservableCollection<T>实现了IList<T>,因此每次需要添加内容时,您可以将其作为列表进行二进制搜索,并在适当的位置插入:

public static class ListHelper
{
    public static int BinarySearchFirst<T>(this IList<T> list, T item, IComparer<T> comparer)
    {
        comparer = comparer ?? Comparer<T>.Default;
        int start = list.BinarySearch(item, comparer);
        for (; start > 0 && comparer.Compare(list[start], list[start - 1]) == 0; start--)
            ;
        return start;
    }
    public static int BinarySearchLast<T>(this IList<T> list, T item, IComparer<T> comparer)
    {
        comparer = comparer ?? Comparer<T>.Default;
        int start = list.BinarySearch(item, comparer);
        if (start > 0)
        {
            for (int end = list.Count - 1; start < end && comparer.Compare(list[start], list[start + 1]) == 0; start++)
                ;
        }
        return start;
    }
    public static int BinarySearch<T>(this IList<T> list, T value)
    {
        return BinarySearch(list, value, null);
    }
    // Searches the list for a given element using a binary search
    // algorithm. Elements of the list are compared to the search value using
    // the given IComparer interface. If comparer is null, elements of
    // the list are compared to the search value using the IComparable
    // interface, which in that case must be implemented by all elements of the
    // list and the given search value. This method assumes that the given
    // section of the list is already sorted; if this is not the case, the
    // result will be incorrect.
    //
    // The method returns the index of the given value in the list. If the
    // list does not contain the given value, the method returns a negative
    // integer. The bitwise complement operator (~) can be applied to a
    // negative result to produce the index of the first element (if any) that
    // is larger than the given search value. This is also the index at which
    // the search value should be inserted into the list in order for the list
    // to remain sorted.
    public static int BinarySearch<T>(this IList<T> list, T value, IComparer<T> comparer)
    {
        // Adapted from http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
        if (list == null)
            throw new ArgumentNullException("list");
        comparer = comparer ?? Comparer<T>.Default;
        int lo = 0;
        int hi = list.Count - 1;
        while (lo <= hi)
        {
            int i = lo + ((hi - lo) >> 1);
            int order = comparer.Compare(list[i], value);
            if (order == 0)
                return i;
            if (order < 0)
            {
                lo = i + 1;
            }
            else
            {
                hi = i - 1;
            }
        }
        return ~lo;
    }
    public static int AddToSortedList<T>(this IList<T> list, T value, bool allowDuplicates)
    {
        return list.AddToSortedList(value, allowDuplicates, null);
    }
    public static int AddToSortedList<T>(this IList<T> list, T value, bool allowDuplicates, IComparer<T> comparer)
    {
        // If the incoming value is equivalent to the some value already in the list using the current comparer,
        // add it to the END of the sequence of equivalent entries.
        int index = list.BinarySearchLast(value, comparer);
        if (!allowDuplicates && index >= 0)
            return index;
        if (index < 0)
            index = ~index;
        list.Insert(index, value);
        return index;
    }
}

这是有争议的AddToSortedList()是否应该是一个扩展方法或只是一些静态助手方法,因为许多列表将不排序。如果尝试向列表中添加与某些预先存在的条目相等的条目,我的方法将新条目添加到等效条目序列的末尾,或者返回调用者指定的现有条目的索引。根据您的需要,您可能更喜欢抛出一个异常。

最新更新