2009-09-02 5 views
8

ОК, я сортирую XMLListCollection в алфавитном порядке. У меня есть один вопрос. Если значение «ВСЕ», я хочу, чтобы оно было первым в списке. В большинстве случаев это происходит уже, но значения, которые являются числами, сортируются до «ВСЕ». Я хочу, чтобы «ВСЕ» всегда был первым выбором в моем dataProvider, а затем остальным в алфавитном порядке.Flex: Sort - Написание пользовательской функции compareFunction?

Так что я пытаюсь написать свою собственную функцию сортировки. Есть ли способ проверить, является ли одно из значений, и если не сказать, что он делает регулярное сравнение значений?

Вот что у меня есть:

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; 

Есть ли решение для того, что я пытаюсь сделать?

+0

Что делать, если оба являются «все»? –

+0

Я бы хотел сказать, что этого никогда не произойдет. Но да, я знаю, что это никогда не бывает. Я добавлю еще один оператор if перед проверкой того, что они одинаковы, а return 0 - true. Благодарю. –

ответ

8

Ну, я попробовал что-то, и я действительно удивлен, что это действительно сработало, но вот что я сделал.

Класс Sort имеет частную функцию internalCompare. Поскольку он является частным, вы не можете его назвать. НО есть функция getter, называемая compareFunction, и если функция сравнения не определена, она возвращает ссылку на функцию internalCompare. Так что я сделал это получить эту ссылку, а затем позвонил.

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

Вы также можете сделать f экземпляром или статическим членом класса, поэтому вам не нужно создавать новый сортировку каждый раз при сопоставлении. –

+0

@ Kathy, хороший пункт. –

+0

приятный, хороший драгоценный камень :) – Tox

14

Решение от Джона Isaacks является удивительным, но он забыл о «полях» переменной и его пример не работает для более сложных объектов (кроме строк)

Пример:

// 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

На первый взгляд я думал, что вы ошибаетесь, но оказывается, что Adobe удалось еще раз испортить. Их функция internalCompare проверяет поля экземпляра вместо параметра функции. Еще один из камней Adobe ... –

+0

Это было очень полезно. Я попытался использовать String.localeCompare() вместо этого, но у этого есть некоторые неприятные побочные эффекты сортировки, вызываемые слишком часто –

0

Спасибо, ребята, это очень помогло. В нашем случае нам понадобятся все пустые строки (в DataGrid) внизу. Все непустые строки должны быть отсортированы в обычном порядке. Наши данные строк - это все динамические объекты (конвертированные из JSON) - вызов ValidationHelper.hasData() просто проверяет, является ли строка пустой. По какой-то причине поля иногда содержат значение DataField Строка вместо SortFields, следовательно, проверка перед установкой свойства «поля»:

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

я не нашел эти подходы к работе для моей ситуации, которая должна была в алфавитном порядке список строк, а затем добавьте элемент «Создать новый ...» в конце списка.

То, как я обрабатывал вещи, немного неэлегантно, но надежно.

Я отсортирован мой ArrayCollection из строк, называется orgNameList, с альфа рода, например, так:

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

Затем я скопировал элементы отсортированного списка в новый ArrayCollection, называется customerDataList. Результатом является то, что новые элементы ArrayCollection находятся в алфавитном порядке, но не находятся под воздействием объекта Sort. Таким образом, добавление нового элемента добавит его в конец ArrayCollection. Аналогично, добавление элемента к определенному индексу в ArrayCollection также будет работать, как ожидалось.

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

Затем я просто нажал на «Создать новый ...', вот так:

if(userIsAllowedToCreateNewCustomer) 
    { 
     customerDataList.addItem(CREATE_NEW); 
     customerDataList.refresh(); 
    } 
Смежные вопросы