2011-04-07 15 views
5

Mam ListView (GridView), który chcę posortować według 2 kolumn, więc jeśli 2+ elementy mają taką samą wartość w kolumnie 1, sortuje według kolumny 2. Pretty łatwo. Jednak przy sortowaniu A-Z pojawiają się puste struny u góry. Chciałbym przenieść je na sam dół. Zrobiłem porównywarkę (IComparer), która zajmuje się tym, ale nie jestem pewien, jak z niego korzystać.WPF - Używanie niestandardowego porównywalnika podczas sortowania według wielu kolumn

Oto kod próbowałem:

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 

Problem jest mój comparer podano typ mojej klasie zamiast wartości nieruchomości/kolumnie są posortowane wg. Więc jeśli klasa jest Foo i sortuję według Foo.Bar, otrzymuję całą klasę Foo, nie tylko wartość Bar (która tak naprawdę powinna być zatroskana, ponieważ to jest to, przez co ją sortuje).

W jaki sposób mój porównawca będzie wiedział, którą nieruchomość porównać? Może robię coś złego tutaj, ponieważ to nie ma sensu. Spodziewałem się uzyskać String (typ właściwości) dla x i y ...

Czy ktoś wie, jak to zrobić?

Odpowiedz

6

Implementacja IComparer będą cały obiekt, trzeba dowiedzieć się, która kolumna zostanie kliknięty, prawdopodobnie robiąc coś takiego:

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

a następnie karmić, że w swojej MyComparer prawdopodobnie przez zmodyfikowanie konstruktora wziąć ścieżkę własności.

W Column_Sort można uzyskać coś ścieżki nieruchomość tak (jestem trochę zardzewiały na VB, ale C# by to zrobić.

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

a następnie karmić, że w logice sortowania

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: trzeba tylko, aby dostosować IComparer do obsługi wielu kolumn sortowania, google i znalazłem this comparer implementation że można go karmić Severa l ścieżki mieszkalne oddzielone przecinkami i sufiksem z ASC/DESC tak:

User.LastName DESC, User.FirstName DESC 

myślę konwencja dla wielu sortowania kolumny miarę UI jest zaniepokojony jest to, że trzeba mieć przycisk Ctrl odbyć. Podklasuj więc klasę ListView i powiązaj ze zdarzeniem klikniętym GridViewColumnHeader i zdarzeniem KeyDown, aby wiedzieć, które kolumny kliknięto po kolei, a następnie użyj implementacji IComparer, aby ją wprowadzić.

+0

Działa to podczas sortowania za pomocą jednej kolumny, ale ponieważ ścieżka właściwości PropertyPath odnosi się do klikniętej kolumny (która jest również sortHeader w moim kodzie), wygląda na tę kolumnę, nawet jeśli powinna porównywać drugą kolumnę (drugi parametr SortDescription). W jaki sposób porównawca wie, czy powinien wyglądać do pierwszej kolumny (klikniętej) czy drugiej (kiedy są 2+, które mają taką samą wartość w kolumnie 1)? – grant

+0

Wprowadzono kilka zmian powyżej, aby spróbować odpowiedzieć na dokładne pytanie :) – Jose

Powiązane problemy