2011-04-07 22 views
5

Tengo un ListView (GridView) que quiero ordenar por 2 columnas, así que si 2+ elementos tienen el mismo valor en la Columna 1, ordena por la Columna 2. Bonita fácil. Pero las cadenas vacías aparecen en la parte superior al ordenar A-Z. Me gustaría moverlos al fondo. Hice un comparador (IComparer) que se encarga de esto, pero no estoy seguro de cómo usarlo.WPF - Usar un comparador personalizado al ordenar por varias columnas

Aquí está el código que he intentado:

Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection) 
Using view.DeferRefresh 
    view.SortDescriptions.Clear() 
    view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction)) 
    view.SortDescriptions.Add(New SortDescription(otherColumn, direction)) 
    view.CustomSort = New MyComparer() 
End Using 

El problema es mi comparador se da un tipo de mi clase en lugar del valor de la propiedad/columna que se está clasificado por. Entonces, si la clase es Foo y estoy clasificando por Foo.Bar, obtengo toda la clase Foo, no solo el valor de Bar (que es realmente todo lo que debería preocuparle, ya que eso es lo que está ordenando).

¿Cómo va a saber mi comparador qué propiedad comparar? Tal vez estoy haciendo algo mal aquí, porque esto no tiene ningún sentido. Esperaba obtener un String (el tipo de propiedad) para xy y ...

¿Alguien sabe cómo hacer esto?

Respuesta

6

Su aplicación IComparer se le dará todo el objeto, es necesario averiguar en qué columna obtiene se hace clic, probablemente haciendo algo como esto:

this.AddHandler(GridViewColumnHeader.ClickEvent, 
       new RoutedEventHandler(Column_Sort)); 

y alimentos para animales que en su MyComparer probablemente mediante la modificación de su constructor para tomar en la ruta de la propiedad.

En Column_Sort se puede obtener la ruta de propiedad algo como esto (estoy un poco oxidado en VB, pero C# podría hacer esto:.

void Column_Sort(object sender, RoutedEventArgs e) 
{ 
    var memberBinding= ((GridViewColumnHeader)e.OriginalSource).Column.DisplayMemberBinding; 
    var path = ((Binding)memberBinding).Path.Path; 
} 

y luego alimentar a que en su lógica de clasificación

Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection) 
Using view.DeferRefresh 
    view.SortDescriptions.Clear() 
    view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction)) 
    view.SortDescriptions.Add(New SortDescription(otherColumn, direction)) 
    view.CustomSort = New MyComparer(PropertyPath) 
End Using 

EDIT: Sólo se necesita para personalizar su IComparer para soportar múltiples columna de clasificación, que en Google y encontró this comparer implementation que se puede alimentar Severa l caminos de propiedad separados por coma, con el sufijo ASC/DESC como esto:

User.LastName DESC, User.FirstName DESC 

creo que la convención para la clasificación de varias columnas en lo que se refiere a la interfaz de usuario es que es necesario tener el botón Ctrl a cabo. Así que subclase la clase ListView y vincularse al evento GridViewColumnHeader clicked y al evento KeyDown para saber en qué columnas se hizo clic sucesivamente y luego utilizar una implementación IComparer para alimentar eso.

+0

Esto funciona cuando se ordena por una columna, pero dado que PropertyPath se refiere a la columna que se hizo clic (que también es sortHeader en mi código), busca esa columna incluso cuando debería comparar la segunda columna (la segunda SortDescription) ¿Cómo sabe el comparador si debe mirar hacia la primera columna (la que se hace clic) o la segunda (cuando hay 2+ que tienen el mismo valor en la columna 1)? – grant

+0

Hizo algunos cambios arriba para intentar responder la pregunta exacta :) – Jose

Cuestiones relacionadas