views:

5139

answers:

2

I have a datagrid, populated as shown below. When the user clicks on a column header, I would like to sort the rows using a lexicographic sort in which the selected column is used first, then the remaining columns are used in left-to-right order to break any ties. How can I code this?

(I have one answer, which I'll post below, but it has a problem -- I'll be thrilled if somebody can provide a better one!)

Here's the layout:

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" creationComplete="onCreationComplete()">

    <mx:Script source="GridCode.as" />

    <mx:DataGrid id="theGrid" x="61" y="55" width="466" height="317">
     <mx:columns>
      <mx:DataGridColumn dataField="A"/>
      <mx:DataGridColumn dataField="B"/>
      <mx:DataGridColumn dataField="C"/>
     </mx:columns>
    </mx:DataGrid>

</mx:Application>

And here's the backing code:

import mx.collections.ArrayCollection;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.events.DataGridEvent;

public function onCreationComplete():void
{
    var ar:ArrayCollection = new ArrayCollection();
    var ob:Object;
    for( var i:int=0; i<20; i++ )
    {
     ob = new Object();
     ob["A"] = i;
     ob["B"] = i%3;
     ob["C"] = i%5;
     ar.addItem(ob);
    }
    this.theGrid.dataProvider = ar;
}
+4  A: 

The best answer I've found so far is to capture the headerRelease event when the user clicks:

<mx:DataGrid id="theGrid" x="61" y="55" width="466" height="317"
        headerRelease="onHeaderRelease(event)">

The event handler can then apply a sort order to the data:

private var lastIndex:int = -1;
private var desc:Boolean = false;

public function onHeaderRelease(evt:DataGridEvent):void
{
    evt.preventDefault();

    var srt:Sort = new Sort();
    var fields:Array = new Array();

    if( evt.columnIndex == lastIndex )
    {
     desc = !desc;
    }
    else
    {
     desc = false;
     lastIndex = evt.columnIndex;
    }

    fields.push( new SortField( evt.dataField, false, desc ) );
    if( evt.dataField != "A" )
     fields.push( new SortField("A", false, desc) );
    if( evt.dataField != "B" )
     fields.push( new SortField("B", false, desc) );
    if( evt.dataField != "C" )
     fields.push( new SortField("C", false, desc) );
    srt.fields = fields;

    var ar:ArrayCollection = this.theGrid.dataProvider as ArrayCollection;
    ar.sort = srt;
    ar.refresh();
}

However this approach has a well-known problem, which is that the column headers no longer display little arrows to show the sort direction. This is a side-effect of calling evt.preventDefault() however you must make that call or else your custom sort won't be applied.

Eric
A: 

Hi Eric,

I tried your code in my apps and it worked! Using Flex 3, it displays the little arrow that shows the sort direction.

Thanks, Arnold