2009-09-02 74 views
8

好的,我按字母順序排序XMLListCollection。我有一個問題,但。如果值是「ALL」,我希望它是列表中的第一個。在大多數情況下,這種情況已經發生,但是在「ALL」之前正在對數字進行排序。我希望「ALL」始終是我的dataProvider中的第一個選擇,然後按字母順序排列。Flex:排序 - 編寫自定義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

如果兩者都是'全部'會怎麼樣? – 2009-09-02 14:58:08

+0

我想說永遠不會發生。但是,我知道這絕不是這種情況。我會再添加一個if語句來檢查它們是否相同,並返回0是否爲真。謝謝。 – 2009-09-02 15:07:10

回答

8

那麼我嘗試了一些東西,我真的很驚訝它的實際工作,但這是我做的。

Sort類有一個名爲internalCompare的私有函數。由於它是私人的,你不能稱之爲。但有一個名爲compareFunction的getter函數,如果沒有定義比較函數,它將返回對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成爲類的實例或靜態成員,因此每次進行比較時都不必創建新的排序。 – 2009-09-02 15:10:21

+0

@凱西,好點。 – 2009-09-02 15:28:21

+0

不錯,很好的寶石:) – Tox 2015-08-25 20:05:20

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的寶石... – 2009-12-10 15:21:43

+0

這是非常有幫助的。我嘗試使用String.localeCompare()來代替,但是這種方法有一些令人討厭的副作用,那就是太頻繁地調用排序 – 2013-02-28 08:15:02

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

我沒有發現這些方法對於我的情況,這是按字母順序排列工作一個字符串列表,然後在列表的末尾追加一個'Create new ...'項目。

我處理事物的方式有點不雅,但可靠。

我整理我的琴絃的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(); 
    }