2009-09-02 10 views
8

OK, estoy ordenando una XMLListCollection en orden alfabético. Tengo un problema sin embargo. Si el valor es "TODO", quiero que sea el primero en la lista. En la mayoría de los casos esto ya sucede, pero los valores que son números se están ordenando antes de "TODOS". Quiero que "ALL" sea siempre la primera selección en mi dataProvider y luego el resto en orden alfabético.Flex: Ordenar - ¿Escribir una función de comparación personalizada?

Así que estoy tratando de escribir mi propia función de ordenación. ¿Hay alguna manera de verificar si uno de los valores es todo y, si no, indicarle que haga una comparación regular de los valores?

Aquí es lo que tengo:

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; 

¿Hay una solución para lo que yo estoy tratando de hacer?

+0

¿Qué pasa si ambos son' todo '? –

+0

Me gustaría decir que eso nunca sucederá. Pero sí sé que nunca es el caso jajaja. Agregaré otra instrucción if antes de verificar para verificar si son iguales y devolver 0 es verdadero. Gracias. –

Respuesta

8

Bueno, probé algo, y estoy realmente sorprendido de que realmente funcionó, pero esto es lo que hice.

La clase Sort tiene una función privada llamada internalCompare. Como es privado, no puedes llamarlo. PERO hay una función getter llamada compareFunction, y si no se define ninguna función de comparación, devuelve una referencia a la función internalCompare. Entonces, lo que hice fue obtener esta referencia y luego llamarla.

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

También es posible que pueda crear una instancia o un miembro estático de la clase, de modo que no tenga que crear una clasificación nueva cada vez que se realice una comparación. –

+0

@Kathy, buen punto. –

+0

nice, good gem :) – Tox

14

La solución de John Isaacks es impresionante, pero se olvidó de "campos" variable y su ejemplo no funciona para objetos más complicados (aparte de Cuerdas)

Ejemplo:

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

A primera vista, pensé que estabas equivocado, pero resulta que Adobe logró arruinarse una vez más. Su función internalCompare comprueba los campos de instancia en lugar del parámetro de función. Sin embargo, otra de las gemas de Adobe ... –

+0

Esto fue muy útil. Intenté usar String.localeCompare() en su lugar, pero eso tiene algunos desagradables efectos secundarios de que la clasificación se llame con demasiada frecuencia –

0

Gracias chicos, esto ayudó mucho. En nuestro caso, necesitábamos todas las filas vacías (en un DataGrid) en la parte inferior. Todas las filas no vacías se deben ordenar normalmente. Nuestros datos de fila son todos Objetos dinámicos (convertidos de JSON): la llamada a ValidationHelper.hasData() simplemente comprueba si la fila está vacía. Por alguna razón los campos contienen a veces el valor dataField cadena en lugar de SortFields, por lo tanto, el cheque antes de establecer la propiedad '' campos:

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

no he encontrado estos enfoques para trabajar por mi situación, que era para alfabetizar una lista de cadenas y luego agregar un elemento 'Crear nuevo ...' al final de la lista.

La forma en que manejé las cosas es un poco poco elegante, pero confiable.

que ordenan mis ArrayCollection de cuerdas, llamado orgNameList, con un tipo alfa, así:

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

Entonces me copian los elementos de la lista ordenada en una nueva ArrayCollection, llamados customerDataList. El resultado es que los nuevos elementos ArrayCollection están en orden alfabético, pero no están bajo la influencia de un objeto Sort. Por lo tanto, agregar un nuevo elemento lo agregará al final de ArrayCollection. Del mismo modo, agregar un elemento a un índice particular en el ArrayCollection también funcionará como se esperaba.

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

Luego agregué el 'Crear nuevo ...'artículo, como este:

if(userIsAllowedToCreateNewCustomer) 
    { 
     customerDataList.addItem(CREATE_NEW); 
     customerDataList.refresh(); 
    } 
Cuestiones relacionadas