2009-09-02 14 views
8

OK, sortuję XMLListCollection w kolejności alfabetycznej. Mam jednak jedną kwestię. Jeśli wartość to "ALL", chcę, aby była pierwsza na liście. W większości przypadków dzieje się to już wcześniej, ale wartości będące liczbami są sortowane przed "ALL". Chcę, aby "ALL" zawsze był pierwszym wyborem w moim dataProvider, a następnie reszta alfabetycznie.Flex: Sortuj - Zapisywanie niestandardowej funkcji porównania?

Więc staram się napisać własną funkcję sortowania. Czy istnieje sposób, aby sprawdzić, czy jedna z wartości jest wszystkim, a jeśli nie powiedzieć, aby zrobić regularne porównanie wartości?

Oto co mam:

function myCompare(a:Object, b:Object, fields:Array = null):int 
{ 
    if(String(a).toLowerCase() == 'all') 
    { 
     return -1; 
    } 
    else 
     if(String(b).toLowerCase() == 'all') 
     { 
      return 1; 
     } 
    // NEED to return default comparison results here? 
} 

//------------------------------ 

var sort:Sort = new Sort(); 
sort.compareFunction = myCompare; 

Czy istnieje rozwiązanie dla co usiłuję zrobić?

+0

Co zrobić, jeśli obie są" wszystkie "? –

+0

Chciałbym powiedzieć, że to się nigdy nie zdarzy. Ale tak, wiem, że nigdy nie jest tak lol. Dodam jeszcze jedną instrukcję if przed sprawdzeniem, czy są one takie same, a return 0 jest prawdziwe. Dzięki. –

Odpowiedz

8

Cóż, spróbowałem czegoś i jestem naprawdę zaskoczony, że zadziałało, ale oto co zrobiłem.

Klasa Sort ma prywatną funkcję o nazwie internalCompare. Ponieważ jest prywatne, nie możesz tego nazwać. ALE istnieje funkcja getter o nazwie compareFunction, a jeśli nie jest zdefiniowana funkcja porównania, zwraca odwołanie do funkcji internalCompare. Więc to, co zrobiłem, otrzymałem to odwołanie, a potem zadzwoniłem.

private function myCompare(a:Object, b:Object, fields:Array = null):int 
{ 
    if(String(a).toLowerCase() == 'all') 
    { 
     return -1; 
    } 
    else if(String(b).toLowerCase() == 'all') 
    { 
     return 1; 
    } 
    // NEED to return default comparison results here? 
    var s:Sort = new Sort(); 
    var f:Function = s.compareFunction; 
    return f.call(null,a,b,fields); 
} 
+1

Możesz także być w stanie utworzyć instancję lub statyczny element klasy, więc nie musisz tworzyć nowego sortowania za każdym razem, gdy dokonywany jest porównywanie. –

+0

@Kathy, dobry punkt. –

+0

fajny, dobry klejnot :) – Tox

14

Rozwiązanie John Isaacks jest niesamowite, ale zapomniał o „polach” zmienna i jego przykład nie działa dla bardziej skomplikowanych obiektów (innych niż Strings)

Przykład:

// collection with custom objects. We want to sort them on "value" property 
// var item:CustomObject = new CustomObject(); 
// item.name = 'Test'; 
// item.value = 'Simple Value'; 

var collection:ArrayCollection = new ArrayCollection(); 
var s:Sort = new Sort(); 
s.fields = [new SortField("value")]; 
s.compareFunction = myCompare; 
collection.sort = s; 
collection.refresh(); 

private function myCompare(a:Object, b:Object, fields:Array = null):int 
{ 
    if(String((a as CustomObject).value).toLowerCase() == 'all') 
    { 
     return -1; 
    } 
    else if(String((b as CustomObject).value).toLowerCase() == 'all') 
    { 
     return 1; 
    } 
    // NEED to return default comparison results here? 
    var s:Sort = new Sort(); 
    s.fields = fields; 
    var f:Function = s.compareFunction; 
    return f.call(null,a,b,fields); 
} 
+0

Na pierwszy rzut oka myślałem, że się mylisz, ale okazuje się, że Adobe znowu zepsuł. Ich funkcja internalCompare sprawdza pola instancji zamiast parametru funkcji. Jeszcze jeden klejnot Adobe ... –

+0

To było bardzo pomocne. Próbowałem użyć String.localeCompare(), ale ma to pewne nieprzyjemne skutki uboczne sortowania nazywa się zbyt często –

0

Dzięki chłopaki, to bardzo pomogło. W naszym przypadku potrzebowaliśmy wszystkich pustych wierszy (w DataGrid) na dole. Wszystkie niepuste wiersze powinny być posortowane normalnie. Naszymi danymi wiersza są wszystkie obiekty dynamiczne (konwertowane z JSON) - wywołanie funkcji ValidationHelper.hasData() po prostu sprawdza, czy wiersz jest pusty. Z jakiegoś powodu pola czasami zawierają wartość dataField String zamiast SortFields, stąd sprawdzić przed ustawienie właściwości „Fields”:

private function compareEmptyAlwaysLast(a:Object, b:Object, fields:Array = null):int { 
    var result:int; 
    if (!ValidationHelper.hasData(a)) { 
     result = 1; 
    } else if (!ValidationHelper.hasData(b)) { 
     result = -1; 
    } else { 
     if (fields && fields.length > 0 && fields[0] is SortField) { 
      STATIC_SORT.fields = fields; 
     } 
     var f:Function = STATIC_SORT.compareFunction; 
     result = f.call(null,a,b,fields); 
    } 
    return result; 
} 
-1

Nie mogę znaleźć te podejścia do pracy dla mojej sytuacji, która miała alphabetize listę Ciągów, a następnie dodaj element "Utwórz nowy ..." na końcu listy.

Sposób w jaki postępowałem, jest trochę nieelegancki, ale niezawodny.

I sortowane mój ArrayCollection strun, zwana orgNameList, z alfa rodzaju, tak jak poniżej:

var alphaSort:Sort = new Sort(); 
    alphaSort.fields = [new SortField(null, true)]; 
    orgNameList.sort = alphaSort; 
    orgNameList.refresh(); 

Potem kopiowane elementy na liście posortowanej do nowego ArrayCollection, zwany customerDataList. W wyniku tego nowe elementy ArrayCollection są uporządkowane alfabetycznie, ale nie są pod wpływem obiektu Sort. Dodanie nowego elementu spowoduje dodanie go do końca ArrayCollection. Podobnie dodanie elementu do określonego indeksu w urządzeniu ArrayCollection będzie działać zgodnie z oczekiwaniami.

for each(var org:String in orgNameList) 
    { 
     customerDataList.addItem(org); 
    } 

Wtedy właśnie wkleiłem "Utwórz nowy ..."pozycja, jak to:

if(userIsAllowedToCreateNewCustomer) 
    { 
     customerDataList.addItem(CREATE_NEW); 
     customerDataList.refresh(); 
    } 
Powiązane problemy