Flex DataGrid如何实现根据多列排序(Multiple Column Sort)的功能
我们知道这Flex 3.0以前的DataGrid默认只能有一列进行排序,不能进行多列排序。其实要想实现多列排序也并不难。我们只要利用Sort和SortField这两个对象就可以达到这个目的。
不过首先该DataGrid的DataProvider必须是实现了ICollectionView接口,比如ArrayCollection和XMLListCollection都可以。
实现的方法大致如下:
系统初始化时给dataProvider指定一个Sort对象,该对象包括3个SortField,排序的优先级就是按照先后顺序来的。
然后给DataGrid的headerRelease事件指定一个排序方法处理,每次都将最新点击的列作为第一排序,将之前的第一和第二排序分别指定成第二和第三排序,在应用新的排序方法后,我们调用了event.preventDefault()方法,防止调用系统默认的排序方法,否则多行排序的功能就无效。
下面的例子遗憾的是多列排序后,默认的表示排序的箭头图标没能出现,这也是preventDefault()带来的副作用。
下面是代码:
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
????? initialize="initDP();" width="550" height="400">
?? <mx:Script>
????? <![CDATA[
???????? import mx.events.DataGridEvent;
???????? import mx.collections.*;
????????
???????? // Declare storage variables and initialize the simple variables.
???????? // The data provider collection.
???????? private var myDPColl:ArrayCollection;
???????? // The Sort object used to sort the collection.
???????? [Bindable]
???????? private var sortA:Sort;
???????? // The sort fields used to determine the sort.
????????? private var sortByInStock:SortField;
????????? private var sortByArtist:SortField;
????????? private var sortByAlbum:SortField;
????????? private var sortByPrice:SortField;
???????? // The data source that populates the collection.
???????? private var myDP:Array = [
??????????? {Artist:'Pavement', Album:'Slanted and Enchanted',
?????????????? Price:11.99, InStock: true},
??????????? {Artist:'Pavement', Album:'Crooked Rain, Crooked Rain',
?????????????? Price:10.99, InStock: false},
??????????? {Artist:'Pavement', Album:'Wowee Zowee',
?????????????? Price:12.99, InStock: true},
??????????? {Artist:'Asphalt', Album:'Brighten the Corners',
?????????????? Price:11.99, InStock: false},
??????????? {Artist:'Asphalt', Album:'Terror Twilight',
?????????????? Price:11.99, InStock: true},
??????????? {Artist:'Asphalt', Album:'Buildings Meet the Sky',
?????????????? Price:14.99, InStock: true},
??????????? {Artist:'Other', Album:'Other', Price:5.99, InStock: true}
???????? ];
?
???????? //Initialize the DataGrid control with sorted data.
???????? private function initDP():void {
??????????? //Create an ArrayCollection backed by the myDP array of data.
??????????? myDPColl = new ArrayCollection(myDP);
??????????? //Create a Sort object to sort the ArrrayCollection.
??????????? sortA = new Sort();
??????????? //Initialize SortField objects for all valid sort fields:
??????????? // A true second parameter specifies a case-insensitive sort.
??????????? // A true third parameter specifies descending sort order.
??????????? // A true fourth parameter specifies a numeric sort.
???????????? sortByInStock = new SortField("InStock", true, true);
???????????? sortByArtist = new SortField("Artist", true);
???????????? sortByAlbum = new SortField("Album", true);
???????????? sortByPrice = new SortField("Price", true, false, true);
??????????? // Sort the grid using the InStock, Artist, and Album fields.
??????????? sortA.fields=[sortByInStock, sortByArtist, sortByAlbum];
??????????? myDPColl.sort=sortA;
??????????? // Refresh the collection view to show the sort.
??????????? myDPColl.refresh();
??????????? // Initial display of sort fields
??????????? tSort0.text = "First Sort Field: InStock";
??????????? tSort1.text = "Second Sort Field: Artist";
??????????? tSort2.text = "Third Sort Field: Album";
?
??????????? // Set the ArrayCollection as the DataGrid data provider.
??????????? myGrid.dataProvider=myDPColl;
??????????? // Set the DataGrid row count to the array length,
??????????? // plus one for the header.
??????????? myGrid.rowCount=myDPColl.length +1;
???????? }?
?????
???????? // Re-sort the DataGrid control when the user clicks a header.
???????? private function headRelEvt(event:DataGridEvent):void {
??????????? // The new third priority was the old second priority.
??????????? sortA.fields[2] = sortA.fields[1];
??????????? tSort2.text = "Third Sort Field: " + sortA.fields[2].name;
????? ??????// The new second priority was the old first priority.
??????????? sortA.fields[1] = sortA.fields[0];
??????????? tSort1.text = "Second Sort Field: " + sortA.fields[1].name;
??????????? // The clicked column determines the new first priority.
?????? ?????if (event.columnIndex==0) {
??????????? ????? sortByArtist.descending = !sortByArtist.descending;
?????????????? sortA.fields[0] = sortByArtist;
??????????? } else if (event.columnIndex==1) {
??????????? ????? sortByAlbum.descending = !sortByAlbum.descending;
?????????????? sortA.fields[0] = sortByAlbum;
??????????? } else if (event.columnIndex==2) {
??????????? ????? sortByPrice.descending = !sortByPrice.descending;
?????????????? sortA.fields[0] = sortByPrice;
??????????? } else {
?????????????? sortA.fields[0] = sortByInStock;}
??????????? tSort0.text = "First Sort Field: " + sortA.fields[0].name;
??????????? // Apply the updated sort fields and re-sort.
??????????? myDPColl.sort=sortA;
??????????? // Refresh the collection to show the sort in the grid.
??????????? myDPColl.refresh();
??????????? // Prevent the DataGrid from doing a default column sort.
??????????? event.preventDefault();
???????? }
????? ]]>
?? </mx:Script>
?
?? <!-- The Data Grid control.
???????? By default the grid and its columns can be sorted by clicking.
???????? The headerRelease event handler overrides the default sort
???????? behavior. -->
?? <mx:DataGrid id="myGrid" width="100%" headerRelease="headRelEvt(event);">
????? <mx:columns>
??????????? <mx:DataGridColumn minWidth="120" dataField="Artist" />
??????????? <mx:DataGridColumn minWidth="200" dataField="Album" />
??????????? <mx:DataGridColumn width="75" dataField="Price" />
??????????? <mx:DataGridColumn width="75" dataField="InStock" headerText="In Stock"/>
????? </mx:columns>
?? </mx:DataGrid>
?? <mx:VBox>
????? <mx:Label id="tSort0" text="First Sort Field: "/>
????? <mx:Label id="tSort1" text="Second Sort Field: "/>
????? <mx:Label id="tSort2" text="Third Sort Field: "/>
?? </mx:VBox>
</mx:Application>