Stellen Sie eine FrageStellen Sie eine Frage
 

BeantwortetSorting an ObservableCollection<T>

  • Montag, 8. Januar 2007 22:11dmetz TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    I was recently using a List<T> to keep track of my data, but we had to move to an ObservableCollection<T> because it will eventually be used in binding to a UI.  I was using the List<T>.Sort(IComparer<T>) to sort the list, but it appears that ObservableCollection<T> does not implement this.  Is there a way to sort it or do I have to do that manually? 

    It seems odd to have to redo this work that clearly is already implemented in .Net but I can't seem to find a way to do it. I figured it was worth asking about.  Thanks for the help.

Antworten

  • Montag, 8. Januar 2007 23:18Kiforl TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet

    You can sort it on UI level thru CollectionViewSoure. (http://msdn2.microsoft.com/en-us/library/ms742542.aspx)

  • Dienstag, 9. Januar 2007 01:03Kiforl TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet

    You can write your own sorting logic, something like that:

    public class SortableObservableCollection<T> : ObservableCollection<T>

    {

    public void Sort()

    {

    Sort(Comparer<T>.Default);

    }

    public void Sort(IComparer<T> comparer)

    {

    int i, j;

    T index;

    for (i = 1; i < Count; i++)

    {

    index = thisIdea;     //If you can't read it, it should be index = this[x], where x is i :-)

    j = i;

    while ((j > 0) && (comparer.Compare(this[j - 1], index) == 1))

    {

    this[j] = this[j - 1];

    j = j - 1;

    }

    this[j] = index;

    }

    }

    }

    If you planning to sort collections with 5000 items or more it's better to use another algorithm, I can write you a code if you want, let me know.

     

Alle Antworten

  • Montag, 8. Januar 2007 23:18Kiforl TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet

    You can sort it on UI level thru CollectionViewSoure. (http://msdn2.microsoft.com/en-us/library/ms742542.aspx)

  • Montag, 8. Januar 2007 23:57dmetz TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    Thanks for the idea.  I saw something about that before but was hoping to do the sorting on the business logic instead of at the UI so if another developer could reuse it without worrying about sorting it again

    If there is anyone knows a way of sorting an ObservableCollection directly I would appreciate it.  Our current communications layer only supports ObservableCollection and not Lists anymore so I'm sure I'll want to sort an observable collection that might not be displayed.

    Thanks again.
  • Dienstag, 9. Januar 2007 01:03Kiforl TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Beantwortet

    You can write your own sorting logic, something like that:

    public class SortableObservableCollection<T> : ObservableCollection<T>

    {

    public void Sort()

    {

    Sort(Comparer<T>.Default);

    }

    public void Sort(IComparer<T> comparer)

    {

    int i, j;

    T index;

    for (i = 1; i < Count; i++)

    {

    index = thisIdea;     //If you can't read it, it should be index = this[x], where x is i :-)

    j = i;

    while ((j > 0) && (comparer.Compare(this[j - 1], index) == 1))

    {

    this[j] = this[j - 1];

    j = j - 1;

    }

    this[j] = index;

    }

    }

    }

    If you planning to sort collections with 5000 items or more it's better to use another algorithm, I can write you a code if you want, let me know.

     

  • Dienstag, 9. Januar 2007 16:28dmetz TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    Thanks for the reply.  I guess this is the best option if you want to have the observable collection sort itself.  I'll look into both suggestions and see what works best in my case.

    Thanks again for both replies!
  • Dienstag, 31. Juli 2007 13:52Kurtl99 TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     

    Have anyone a performed sorting algorithm for the ObservableCollection<T>

    Thanks!

  • Dienstag, 8. Juli 2008 14:19alphabj TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    but after you sort the ObservableCollection<T> in the background, how do you get it to update the UI?

    Thanks.
  • Mittwoch, 15. April 2009 03:14str8asacircle TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Vorgeschlagene AntwortEnthält Code

    Hi all,

    I realise that this is an old thread, but I recently ran into the same issue.

    I have an ObservableCollection<T> set as the ItemsSource of an ItemsCollection. I'm using an animated wrap panel to animate the generated UI into position. Later, I want to reorder the items in the ObservableCollection in place so that the animated wrap panel animates them into their new positions.

    To do this, I needed a sorting function that uses the Move method of the ObservableCollection (this is because removing an item and adding it again causes new UI to be generated rather than the existing UI to be animated to its new position).

    This turned out (eventually) to be very simple by subclassing ObservableCollection<T> as follows:

    /// <summary>
    /// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed and allows sorting.
    /// </summary>
    /// <typeparam name="T">The type of elements in the collection.</typeparam>
    public class SortableObservableCollection<T> : ObservableCollection<T>
    {
        /// <summary>
        /// Sorts the items of the collection in ascending order according to a key.
        /// </summary>
        /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
        /// <param name="keySelector">A function to extract a key from an item.</param>
        public void Sort<TKey>(Func<T, TKey> keySelector)
        {
            InternalSort(Items.OrderBy(keySelector));
        }
    
        /// <summary>
        /// Sorts the items of the collection in ascending order according to a key.
        /// </summary>
        /// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/>.</typeparam>
        /// <param name="keySelector">A function to extract a key from an item.</param>
        /// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
        public void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer)
        {
            InternalSort(Items.OrderBy(keySelector, comparer));
        }
    
        /// <summary>
        /// Moves the items of the collection so that their orders are the same as those of the items provided.
        /// </summary>
        /// <param name="sortedItems">An <see cref="IEnumerable{T}"/> to provide item orders.</param>
        private void InternalSort(IEnumerable<T> sortedItems)
        {
            var sortedItemsList = sortedItems.ToList();
    
            foreach (var item in sortedItemsList)
            {
                Move(IndexOf(item), sortedItemsList.IndexOf(item));
            }
        }
    }
    



    The ItemsSource is then sorted as follows (using a lambda expression that converts a T (in this case a Player) into an int key):

    ((SortableObservableCollection<Player>)OrderDisplay.ItemsSource).Sort(player => GetOrder(player).Value);
    



    This way, the internal OnCollectionChanged is called with a NotifyCollectionChangedEventArgs Action of Move, which allows the ItemsControl to re-layout the existing UI (which is then animated by the animated wrap panel) instead of generating new UI.

    • Als Antwort vorgeschlagenstr8asacircle Mittwoch, 15. April 2009 03:14
    •  
  • Donnerstag, 23. April 2009 13:43Michel Miranda TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     

    Hi str8asacircle,

    First, thanks for your contribution.

    I am getting a compile error when using your SortableObservableCollection. The Move method is not recognized by the compiler. What is it I am missing? Thanks in advance.

  • Donnerstag, 23. April 2009 16:12str8asacircle TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    Hi Michel,

    Move is a method on the base class (ObservableCollection(T).Move - see http://msdn.microsoft.com/en-us/library/ms654933.aspx), so I'm not sure why the compiler isn't seeing it...

    Which version of the Framework are you targeting?

    Cheers,
    Matt.
  • Donnerstag, 23. April 2009 18:04Michel Miranda TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    Hi Matt,

    My fault. I am developing a Silverlight client. Silverlight supports only a subset of the .NET library. The Move method isn't part of the ObservableCollection class.

    Thanks for your response.
    Michel
  • Donnerstag, 10. September 2009 10:15niao TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Enthält Code
    You can use Lambda Expression:

    List<CSomeClass> temp = observableCollectionObject.ToList();
    temp.Sort((x, y) => string.Compare(x.Title, y.Title));
    ObservableCollection<CSomeClass> result = new ObservableCollection<CSomeClass>(temp);
  • Samstag, 10. Oktober 2009 10:59GearWorld TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     Enthält Code
    You can use Lambda Expression:

    List<CSomeClass> temp = observableCollectionObject.ToList();
    
    temp.Sort((x, y) => string.Compare(x.Title, y.Title));
    
    ObservableCollection<CSomeClass> result = new ObservableCollection<CSomeClass>(temp);

    I don't know where you took this but there's no constructor on the ObservableCollection class
    am I wrong ?
  • Dienstag, 13. Oktober 2009 17:36niao TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
  • Freitag, 13. November 2009 10:48consept TeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillenTeilnehmermedaillen
     
    Have a look at http://softcollections.codeplex.com/ . You can find there implementation of the SortedObservableCollection.