回答
DataGrid コンポーネントにはカラム単位でソートを行う機能があります。データグリッドの列タイトルをクリックすることでこの機能が働き、クリックしたカラムの列でソートが実行されます。またこのソート操作が行われると、特定の列でソートされたということを視覚的に表現するために、ソートが行われた列の列タイトルの領域に矢印のアイコンが表示されます。
これは非常に便利な機能ですが、ソートされたことを表す矢印のアイコンと、内部のデータとは様々な理由で同期しなくなります。矢印のアイコンはソート操作が行われたタイミングで表示されますが、その後のデータの更新には関与しないからです。例えば、ソート操作を行った後、dataProvider プロパティーを更新し内部データを入れ替えた場合、ソートアイコンの表示と実際の内部データの並び順はまったく一致しなくなります。
この問題に対する最も簡単な回避方法の一つは DataGridの持つ sortIndex、sortDirection という2つのプロパティー、そして placeSortArrow メソッドを利用して追加の機能を実装するということです。 sortIndex, sortDirection プロパティーは API ドキュメントには出てきませんが、比較的知られた DataGrid のプロパティーです。この2つのプロパティーを利用することなしにこの問題に対する回避コードを実装しようとした場合、相当な手間がかかりますので、この2つのプロパティーを有効に利用することがいいと思います。
次に実装例を示します。 DataGrid コンポーネントを継承して新しく AutoSortDataGrid というカスタムコンポーネントを作成しました。 AutoSortDataGrid は DataGrid の機能を引き継ぎつつ、次の2つの機能を加えました。
- 追加機能1. updateDataProvider(dg, resetSortIndex)
- 現在のソート順序を保ちつつ、第一引数で与えられたデータで dataProvider を更新します。第二引数で true を指定した場合は現在設定されているソート順序をキャンセルし、dataProvider 第一引数で与えられたデータで更新します。
- 追加機能2.sortColumn(sortIndex, sortDirection)
- ActionScript からデータ のソートを 行います。ソートの状態に従って矢印アイコンも正しく表示されます。第一引数でソートを行う列の番号(0〜)、第二引数は、降順か、昇順かを文字列 "ASC" / "DESC" で指定します。
カスタムコンポーネント AutoSortDataGrid.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:DataGrid xmlns:mx="http://www.macromedia.com/2003/mxml" >
<mx:Script>
<![CDATA[
function sortColumn(aSortIndex, direction) {
sortIndex = aSortIndex;
sortDirection = direction;
doSort();
}
function updateDataProvider(dt:Object, resetSortIndex:Boolean) {
if (resetSortIndex) {
sortIndex = undefined;
}
dataProvider = dt;
doSort();
}
private function doSort() {
if (sortIndex != undefined) {
var col = columns[sortIndex].columnName;
sortItemsBy(col,sortDirection);
placeSortArrow();
}
}
]]>
</mx:Script>
</mx:DataGrid>
AutoSortdataGrid.mxml を利用したサンプルアプリケーション
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*" >
<mx:Script>
<![CDATA[
var items0 = [{num:'111', name:'NAME1', price:123},
{num:'222', name:'NAME2', price:456}];
var items1 = [{num:'001', name:'Data1', price:100},
{num:'002', name:'Data2', price:150},
{num:'003', name:'Data3', price:100},
{num:'004', name:'Data4', price:1000},
{num:'005', name:'Data5', price:1001},
{num:'010', name:'Data10', price:10}
];
var items2 = [{num:'501', name:'A Data1', price:5100},
{num:'002', name:'Data2', price:4150},
{num:'403', name:'Data3', price:3100},
{num:'004', name:'B Data4', price:21000},
{num:'305', name:'Data5', price:11001},
{num:'010', name:'C Data10', price:010}
];
]]>
</mx:Script>
<mx:HBox>
<mx:Button label="load items1" click="datagrid1.updateDataProvider(items1);" />
<mx:Button label="load items2" click="datagrid1.updateDataProvider(items2);" />
<mx:Button label="load items1(reset sortIndex)" click="datagrid1.updateDataProvider(items1,true);" />
<mx:Button label="load items2(reset sortIndex)" click="datagrid1.updateDataProvider(items2,true);" />
</mx:HBox>
<mx:HBox>
<mx:Button label="sort by col1 (ASC)" click="datagrid1.sortColumn(0, 'ASC')" />
<mx:Button label="sort by col1 (DESC)" click="datagrid1.sortColumn(0, 'DESC')" />
</mx:HBox>
<AutoSortDataGrid id="datagrid1" width="100%" height="100%" dataProvider="{items0}" >
<columns>
<mx:Array>
<mx:DataGridColumn headerText="カラムA" columnName="num" />
<mx:DataGridColumn headerText="カラムB" columnName="name" />
<mx:DataGridColumn headerText="カラムC" columnName="price" />
</mx:Array>
</columns>
</AutoSortDataGrid>
</mx:Application>
実行例:

|