2009-06-15 10 views
20

Tengo una colección observable y la clasifico usando linq. Todo es genial, pero el problema que tengo es ¿cómo puedo ordenar la colección observable real? En vez de eso, termino con algo de IEnumerable y termino borrando la colección y volviendo a agregar las cosas. Esto no puede ser bueno para el rendimiento. ¿Alguien sabe de una mejor manera de hacer esto?Ordenando una colección observable con linq

+0

duplicado posible de [Ordenar ObservableCollection C#] (http://stackoverflow.com/questions/19112922/sort-observablecollectionstring-c-sharp) –

Respuesta

15

Si está utilizando Silverlight 3.0, a continuación, utilizando CollectionViewSource es la manera más limpia. Consulte por debajo de ejemplo: (se puede hacer a través de xaml así)

ObservableCollection<DateTime> ecAll = new ObservableCollection<DateTime>(); 
CollectionViewSource sortedcvs = new CollectionViewSource(); 
sortedcvs.SortDescriptions.Add(new System.ComponentModel.SortDescription("Date", 
    System.ComponentModel.ListSortDirection.Ascending)); 
sortedcvs.Source = ecAll; 
ListBoxContainer.DataContext = sortedcvs; 

Y en correspondiente xaml establecer

ItemsSource="{Binding}" 

para el ListBox o cualquier ItemsControl deriva de control

3

Tenga en cuenta que en Linq, se le asigna un IEnumerable a partir de su consulta, y esa consulta aún no se ha ejecutado. Por lo tanto, el siguiente código sólo se ejecuta la consulta una vez, para agregarlo a un ObservableCollection:

var query = from x in Data 
      where x.Tag == "Something" 
      select x; 

foreach(var item in query) 
    MyObservableCollection.Add(item); 

Tome un vistazo a la extensión "OrderBy" en IEnumerable:

foreach(var item in query.OrderBy(x => x.Name)) 
    MyObservableCollection.Add(item); 
+0

he utilizado esto como una base para algo similar para mi código. Estoy empezando a pensar que Linq es bastante pateador :) – djcouchycouch

+0

No estoy seguro de qué tan bien funcionaría si obtienes el ObservableCollection del servicio WCF, ¿algún consejo? ¿Debo crear un nuevo ObservableCollection en el cliente y aplicarle "OrderBy"? - Gracias. – VoodooChild

+0

@VoodooChild: si ya tiene un ObservableCollection en lugar de solo un IEnumerable, mire la pregunta SO: http://stackoverflow.com/questions/996126/sorting-an-observable-collection-with-linq –

8

Dado que la colección no hace proporcione cualquier mecanismo Sort, esta es probablemente la opción más práctica. Puede implementar un orden manualmente usando Move, etc., pero probablemente sea más lento que hacerlo de esta manera.

var arr = list.OrderBy(x => x.SomeProp).ToArray(); 
    list.Clear(); 
    foreach (var item in arr) { 
     list.Add(item); 
    } 

Además, es posible considerar desatar los elementos de interfaz de usuario, mientras que la clasificación (a través de cualquiera de los enfoques) que se paga sólo para volver a enlazar una vez:

Curiosamente, si esto era BindingList<T>, podría utilizar RaiseListChangedEvents para minimizar el número de notificaciones:

var arr = list.OrderBy(x => x).ToArray(); 
    bool oldRaise = list.RaiseListChangedEvents; 
    list.RaiseListChangedEvents = false; 
    try { 
     list.Clear(); 
     foreach (var item in arr) { 
      list.Add(item); 
     } 
    } finally { 
     list.RaiseListChangedEvents = oldRaise; 
     if (oldRaise) list.ResetBindings(); 
    } 
+0

Lo encontré servicial, gracias! – Masha

+0

Si va a seguir esta ruta, para el rendimiento, usaría 'var ordered = list.OrderBy (x => x.SomeProp); list.Clear(); list.AddRange (ordenado); 'Evitará la iteración y ejecución innecesarias de ToArray() y solo lo hará una vez durante AddRange(). (Tendría que descompilar para verificar esto, ya que AddRange toma un IEnumerable, incluso puede simplemente almacenarlo sin ejecutarlo, y luego ejecutar y almacenar la colección aplanada antes de llamar a cualquier operación específica de la lista. Mismo rendimiento al final, pero solo difiere el ciclo golpeado hasta más tarde.) – JoeBrockhaus

3

ObservableCollections no están diseñados para ser ordenados. La lista es ordenable, y ese es el mecanismo subyacente utilizado por la respuesta que hace referencia a List.Sort(), pero ObservableCollection no se deriva de List, por lo que no tiene suerte. Imo, la solución "correcta" no es intentar ordenar el ObservableCollection, sino implementar ICollectionView y vincular una instancia de eso a su control. Esa interfaz agrega métodos para la clasificación y tiene el beneficio adicional que es reconocido por los controles de Silverlight (bueno, los que lo soportan de todos modos, como DataGrid) para que su clasificación pueda ser utilizada directamente desde la capa de UI. Esta pregunta podría ser útil:

Silverlight and icollectionview

0

i seguido el enlace mencionado en esta publicación http://mokosh.co.uk/post/2009/08/04/how-to-sort-observablecollection/comment-page-1/#comment-75

pero tiene problemas para que funcione en Silverlight

creé una propiedad pública SortableObservableCollection Términos Cuando llamo Terms.Sort (nueva TermComparer()) los registros todavía están sin clasificar muestran en la IU

pude algunos sugieren lo que podría ir mal.gracias

+0

debe levantar un evento cambiado propiedad en los Términos-propiedad – Jack

Cuestiones relacionadas