13.8.1 问题
需要对一个XMLListCollection过滤和排序
13.8.2解决
使用ListViewCollection类的filterFunction和sortFunction属性(XMLListCollection类扩展自该类)或者仅仅传递一个类型Sort的对象给XMLListCollections的sort属性。
13.8.3讨论
XMLListCollections描述XML数据,在根部含有多个节点。例如,包含在nutriton节点里的food项目集将被解释成XMLListCollection,使得这些food节点被看作一个集合。
<food>
<name>Avocado Dip</name>
<calories>110</calories>
<total-fat>11</total-fat>
<saturated-fat>3</saturated-fat>
<cholesterol>5</cholesterol>
<sodium>210</sodium>
<carb>2</carb>
<fiber>0</fiber>
<protein>1</protein>
</food>
...
</nutrition>
过滤XMLListCollection的方式和ArrayCollection相同:也是通过传递一个函数的引用,该函数接收一个Object作为参数,返回布尔值,用来决定是否该对象应该留在过滤后的视图中。例如:
private function lowCalFilter(value:Object):Boolean {
if(Number(value.calories) < 200) {
return true;
}
return false;
}
过滤XMLListCollection需要一个Sort对象,这个对象的fields数组属性需要设置为一些SortField对象。
sort.fields = [new SortField("calories", false, false, true)];
coll.sort = sort;
coll.refresh();
这里列出了演示XMLListCollection的完整的代码,代码包含HTTPService的调用,排序及过滤,如下:
creationComplete="xmlService.send()">
<mx:HTTPService url="assets/data.xml" resultFormat="xml" id="xmlService" result=
"createXMLCollection(event)"/>
<mx:Script>
<![CDATA[
import mx.collections.SortField;
import mx.collections.Sort;
import mx.rpc.events.ResultEvent;
import mx.collections.XMLListCollection;
[Bindable]
private var coll:XMLListCollection;
private function createXMLCollection(event:ResultEvent):void {
var list:XMLList = new XMLList(event.result);
coll = new XMLListCollection(list.food);
var sort:Sort = new Sort();
sort.fields = [new SortField("calories", false, false, true)];
coll.sort = sort;
coll.refresh();
}
private function applyFilter():void {
coll.filterFunction = lowCalFilter;
coll.refresh();
}
private function lowCalFilter(value:Object):Boolean {
if(Number(value.calories) < 200) {
return true;
}
return false;
}
]]>
</mx:Script>
<mx:DataGrid dataProvider="{coll}">
<mx:columns>
<mx:DataGridColumn dataField="calories"/>
<mx:DataGridColumn dataField="name"/>
</mx:columns>
</mx:DataGrid>
<mx:Button click="applyFilter()" label="filter"/>
</mx:VBox>
通过对XML集合中的不同节点使用E4X语句可以实现复杂的过滤;例如,通过如下所示的@语法访问属性:
if(value.calories(@fat) < Number(value.calories)/5) {
return true;
}
return false;
}
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="xmlService.send()">
<mx:Style>
Application{font-size:12px;}
</mx:Style>
<mx:HTTPService url="data.xml" resultFormat="xml" id="xmlService" result="createXMLCollection(event)"/>
<mx:Script>
<![CDATA[
import mx.collections.SortField;
import mx.collections.Sort;
import mx.rpc.events.ResultEvent;
import mx.collections.XMLListCollection;
[Bindable]
private var coll:XMLListCollection;
private function createXMLCollection(event:ResultEvent):void {
var list:XML = new XML(event.result);
coll = new XMLListCollection(list.student);
var sort:Sort = new Sort();
//SortField(字段名=null,大小写不敏感?=false,降序?=false,Object是否按编号?=null)
sort.fields = [new SortField("total", false, true, true)];//降序
coll.sort = sort;
coll.refresh();//因为绑定,coll的变化引起DataGrid的刷新
}
private function applyFilter():void {
coll.filterFunction = myFilter;
coll.refresh();
}
private function myFilter(value:Object):Boolean {
if(Number(value.total) < 380) {
return true;//保留总分<380,看看<380的都有哪些人
}
return false;
}
]]>
</mx:Script>
<mx:DataGrid dataProvider="{coll}">
<mx:columns>
<mx:DataGridColumn headerText="姓名" dataField="name"/>
<mx:DataGridColumn headerText="语文" dataField="chinese"/>
<mx:DataGridColumn headerText="数学" dataField="math"/>
<mx:DataGridColumn headerText="英语" dataField="english"/>
<mx:DataGridColumn headerText="总分" dataField="total"/>
</mx:columns>
</mx:DataGrid>
<mx:Button click="applyFilter()" label="过滤"/>
</mx:Application>
<students>
<student>
<name>张三</name>
<chinese>130</chinese>
<math>140</math>
<english>125</english>
<total>395</total>
</student>
<student>
<name>李四</name>
<chinese>110</chinese>
<math>138</math>
<english>126</english>
<total>374</total>
</student>
<student>
<name>王五</name>
<chinese>120</chinese>
<math>125</math>
<english>135</english>
<total>380</total>
</student>
</students>
这里的total字段的值是钉死的,实际中可能会根据其他字段计算求和的。