<?xml version="1.0" encoding="utf-8"?> <!-- http://blog.flexexamples.com/2007/08/23/determining-a-datagridcolumn-objects-current-sort-order/ --> <mx:Application name="DataGridColumn_sortDescending_test" xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" backgroundColor="white"> <mx:Script source="org/util/SortUtil.as"/> <mx:Script> <![CDATA[ import mx.controls.DateField; import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn; import mx.events.AdvancedDataGridEvent; import mx.utils.ObjectUtil; import mx.collections.ArrayCollection; import mx.controls.dataGridClasses.DataGridColumn; import mx.events.DataGridEvent; [Bindable] public var ac:ArrayCollection=new ArrayCollection([ {data:"-1112",label:"ad",date:"2009/11/10"}, {data:"112",label:"a",date:"2009/11/11"}, {data:"1",label:"12b",date:"2009/11/01"}, {data:"2",label:"Ass",date:"2009/11/20"}, {data:"0",label:"ass",date:"2009/11/14"}, {data:"3",label:"csx",date:"2010/11/12"}, {data:"1232",label:"cdf",date:"2009/11/13"}, {data:"4",label:"xzm",date:"2001/12/10"}, {data:"345",label:"awq",date:"2009/01/10"} ]); ]]> </mx:Script> <mx:DataGrid id="dataGrid" rowCount="10" dataProvider="{ac}" headerRelease="dataGridSort(event)" width="600"> <mx:columns> <mx:DataGridColumn dataField="label" headerText="字符串" /> <mx:DataGridColumn dataField="data" headerText="数字"/> <mx:DataGridColumn dataField="date" headerText="日期"/> </mx:columns> </mx:DataGrid> <mx:AdvancedDataGrid dataProvider="{ac}" headerRelease="advancedDataGridSort(event)" width="600" rowCount="10"> <mx:columns> <mx:AdvancedDataGridColumn dataField="label" headerText="字符串" /> <mx:AdvancedDataGridColumn dataField="data" headerText="数字" /> <mx:AdvancedDataGridColumn dataField="date" headerText="日期" /> </mx:columns> </mx:AdvancedDataGrid> </mx:Application>
flex默认的排序只支持string和numer两种排序,从数据库中读出数据到flex前段,很多时候本来是Number类型转化为了Strng类型(java中的Bigdecimal ,因为As3中没有这么大的数据类型),因此排序就乱了。自己动手写了个方法在点击列头上的排序按钮的时候重置此列的排序函数。另外本方法还支持日期格式,当期是有局限的。
用法:在需要排序的表格上加上headerRelease事件。
// ActionScript file 韩敬诺 dataGrid排序 备注:flex的灵魂是事件 import mx.controls.DateField; import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn; import mx.controls.dataGridClasses.DataGridColumn; import mx.events.AdvancedDataGridEvent; import mx.events.DataGridEvent; import mx.utils.ObjectUtil; /** * 点击dataGrid列头上的排序按钮 */ public function dataGridSort(evt:DataGridEvent):void { //1 得到要排序的列 var column:DataGridColumn = DataGridColumn(evt.currentTarget.columns[evt.columnIndex]); //2 得到列名 var columnName:String=column.dataField; //3 重写此列的排序函数 column.sortCompareFunction=function(obj1:Object,obj2:Object):int{ return superSort(obj1,obj2,columnName); }; } /** * 点击AdvancedDataGrid列头上的排序按钮 */ private function advancedDataGridSort(evt:AdvancedDataGridEvent):void { var column:AdvancedDataGridColumn = AdvancedDataGridColumn(evt.currentTarget.columns[evt.columnIndex]); var columnName:String=column.dataField; column.sortCompareFunction=function(obj1:Object,obj2:Object):int{ return superSort(obj1,obj2,columnName); }; } /** * 根据不同的数据类型选择不同的排序方式 优先级是数字、日期、字符串 */ public function superSort(obj1:Object,obj2:Object,columnName:String):int{ //验证数据类型 Numbe Date String if(!isNaN(obj1[columnName])){ return number_sortCompareFunc(obj1,obj2,columnName); } if(strIsDate(obj1[columnName])){ var inputFormat:String=getInputFormat(obj1[columnName]); return date_sortCompareFunc(obj1,obj2,columnName,inputFormat); } return string_sortCompareFunc(obj1,obj2,columnName); } /** * 日期的排序 */ private function date_sortCompareFunc(obj1:Object, obj2:Object,columnName:String,inputFormat:String):int { var date1:Date =DateField.stringToDate(obj1[columnName],inputFormat); var date2:Date =DateField.stringToDate(obj2[columnName],inputFormat); return ObjectUtil.dateCompare(date1, date2); } /** * 字符串的排序 */ private function string_sortCompareFunc(obj1:Object, obj2:Object,columnName:String):int{ var str1:String=obj1[columnName]; var str2:String=obj2[columnName]; return ObjectUtil.stringCompare(str1, str2,false); } /** * 数字的排序 */ private function number_sortCompareFunc(obj1:Object, obj2:Object,columnName:String):int{ var num1:Number=Number(obj1[columnName]); var num2:Number=Number(obj2[columnName]); return ObjectUtil.numericCompare(num1,num2); } /** * 验证一个字符串是否是日期格式 */ private function strIsDate(str:String):Boolean{ var inputFormat:String=getInputFormat(str); //如果找不到日期表示符号则直接返回false if(inputFormat==null){ return false; } var date:Date=DateField.stringToDate(str,inputFormat); //如果是日期date不为null if(date!=null){ return true; }else{ return false; } } /** * 得到日期的格式 判断的顺序为 2009-11-12 2009/11/12 2009.11.12 */ private function getInputFormat(str:String):String{ if(str.indexOf("-")!=-1){ return "YYYY-MM-DD"; } if(str.indexOf("/")!=-1){ return "YYYY/MM/DD"; } if(str.indexOf(".")!=-1){ return "YYYY.MM.DD"; } return null; }
思路: 在做汽车的项目时,就想解决这个问题,但是一直没想到好的方法。flex是基于事件的组件开发,真是flex的真谛。排序函数很容易写,如何把要排序的列传过来是个问题,flex在干一件事情之前会触发一个事件,headerRelease是关键。
另外,也可以用DatagridColumn的sortCompareFunction进行自定义排序,
mySortCompareFunction(obj1:Object, obj2:Object):int
很多时候,我们需要判断根据obj中的那个属性进行排序比较,而不是对每个表格列进行排序。
一个比较巧妙的方法是可以利用Function。
/** * Numerically sorts a column in the DataGrid. * * @param fieldName The string name for the dataField in the column that you want to sort. */ private function numericSortByField(fieldName:String):Function { return function(obj1:Object, obj2:Object):int { var value1:Number = (obj1[fieldName] == '' || obj1[fieldName] == null) ? null : new Number(obj1[fieldName]); var value2:Number = (obj2[fieldName] == '' || obj2[fieldName] == null) ? null : new Number(obj2[fieldName]); return ObjectUtil.numericCompare(value1, value2); } }
使用很简单,如果列的数据类型是数字,可以指定列的sortCompareFunction
if(dataType=="NUMBER"){ //如果是数字则需要按照数字进行排序 dataGridColumn.sortCompareFunction=numericSortByField(dataField); }