2011-04-07 9 views
5

Ho un ListView (GridView) che voglio ordinare per 2 colonne, quindi se 2+ elementi hanno lo stesso valore nella Colonna 1, ordina per Colonna 2. Abbastanza facile. Ma le stringhe vuote appaiono in alto quando si ordina A-Z. Mi piacerebbe spostarli verso il basso. Ho creato un comparatore (IComparer) che si occupa di questo, ma non sono sicuro di come utilizzarlo.WPF - Utilizzo di un comparatore personalizzato quando si ordina per più colonne

Ecco il codice che ho provato:

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 

Il problema è il mio operatore di confronto viene dato un tipo di mia classe al posto del valore della proprietà/colonna di essere ordinati per. Quindi se la classe è Foo e sto ordinando da Foo.Bar, ottengo l'intera classe Foo, non solo il valore di Bar (che in realtà è tutto ciò di cui dovrebbe preoccuparsi, dato che è ciò che ordina da).

Come sarà il mio comparatore a sapere quale proprietà confrontare? Forse sto facendo qualcosa di sbagliato qui, perché questo non ha alcun senso. Mi aspettavo di ottenere una stringa (il tipo di proprietà) per xe y ...

Qualcuno sa come fare questo?

risposta

6

tuo IComparer implementazione sarà dato l'intero oggetto, è necessario capire quale colonna viene cliccato, probabilmente facendo qualcosa di simile a questo:

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

e poi feed che nella vostra MyComparer probabilmente modificando il costruttore prendere il sentiero della proprietà.

In Column_Sort si può ottenere il percorso di proprietà qualcosa di simile (Sono un po 'arrugginito su vb, ma C# potrebbe fare questo:.

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

e poi alimentare che nella vostra logica di ordinamento

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: Hai solo bisogno di personalizzare il IComparer per supportare più l'ordinamento colonna, ho cercato con Google e trovato this comparer implementation che si può alimentarlo Severa l percorsi di proprietà separate da virgole e con suffisso ASC/DESC simili:

User.LastName DESC, User.FirstName DESC 

Credo la convenzione per più colonne classificare quanto UI è interessato è che è necessario avere il pulsante Ctrl tenuta. Quindi, sottoclassi la classe ListView e collegalo all'evento cliccato di GridViewColumnHeader e all'evento KeyDown per sapere quali colonne sono state cliccate in successione e quindi usa un'implementazione IComparer per inserirla.

+0

Questo funziona quando si ordina da una colonna, ma poiché PropertyPath fa riferimento alla colonna su cui è stato fatto clic (che è anche sortHeader nel mio codice), guarda a quella colonna anche quando dovrebbe comparare la seconda colonna (la seconda SortDescription). Come fa il comparatore a sapere se dovrebbe guardare la prima colonna (quella cliccata) o la seconda (quando c'è 2+ che hanno lo stesso valore nella colonna 1)? – grant

+0

Apportate alcune modifiche sopra per provare a rispondere alla domanda esatta :) – Jose

Problemi correlati