The default sorting behavior of DataGrid
needs some
customization to suit the list pane of my remote
file explorer. Rather than a simple alphabetical sort in every
case, the behavior depends on the sort column:
- The last modified column should sort in chronological order.
- The file size column should sort by actual size (i.e. 1 KB, 500 KB and 1.5 MB should sort correctly).
- Text columns should sort in case-insenstive order.
The documentation for DataGridColumn
mentions the
optional sortCompareFunction
property, which specifies a
comparison function with the contract:
private function compare(a:Object, b:Object):int { return (a < b) ? -1 : (a == b) ? 0 : 1; }
However, the documentation doesn't say what the arguments
a
and b
actually are. Turns out that they
are the data for the rows being compared, not the column values.
This is convenient for writing generic functions that can be applied to multiple columns. First I wrote a function to do a case-insensitive comparison for text columns:
/** * Compares items by the case-insensitive value of the current sort * column. **/ private function compareCaseInsensitive(a:Object, b:Object):int { var sortColumn:String = itemData.sort.fields[0].name; var valueA:String = (a as XML)[sortColumn].toString().toLowerCase(); var valueB:String = (b as XML)[sortColumn].toString().toLowerCase(); return (valueA < valueB) ? -1 : (valueA == valueB) ? 0 : 1; }
The sort.fields
collection indicates the current sort
column. Note that the < and > operators work for strings as
well as numbers in ActionScript.
For the Last Modified and Size columns of the list pane, I added a
sortable value
attribute to the XML data supplied by the
server, i.e.:
<item> <title>clone</title> <size value="1024">1 KB</size> <type>Web Page</type> <lastModified value="200606241611">24 Jun 06 04:11 PM PDT</lastModified> </item>
This convention allowed me to use a single comparison function for all columns that do not sort alphabetically:
/** * Compares items by the value attribute of the current sort column. **/ private function compareByValue(a:Object, b:Object):int { var sortColumn:String = itemData.sort.fields[0].name; var sizeA:int = (a as XML)[sortColumn].@value; var sizeB:int = (b as XML)[sortColumn].@value; return (sizeA < sizeB) ? -1 : (sizeA == sizeB) ? 0 : 1; }
I applied these functions to the corresponding columns by modifying their declarations in the MXML file:
<mx:DataGridColumn dataField="title" headerText="Title" sortCompareFunction="compareCaseInsensitive"/> <mx:DataGridColumn dataField="size" headerText="Size" sortCompareFunction="compareByValue"/> <mx:DataGridColumn dataField="type" headerText="Type" sortCompareFunction="compareCaseInsensitive"/> <mx:DataGridColumn dataField="lastModified" headerText="Modified" sortCompareFunction="compareByValue"/>
I tested this arrangement and it worked fine.
No comments:
Post a Comment