Using a CheckBox in a DataGrid in ActionScript 3.0 [AS3](⇐ In English)
ビジネスアプリケーションにとってデータの操作は基本中の基本。だから、GUIコンポーネントを提供する言語だったら、データをリスト表示したり並べ替えたりする機能やコンポーネントがある、と想定してもおかしくありません。ActionScript3.0にもあります。
今回はActionScript3.0で、そのリスト表示の中にチェックボックスを表示する方法について、Adobe社のオンラインドキュメントに掲載されているサンプルに追加機能を加えながら解説します。これができると、例えば社員教育の受講管理で、リスト上で受講ステータスチェックボックスにチェックを入れればその人を受講済みにできたり、複数のレコードを選択して処理する場合に、処理チェックボックスにチェックが入っている行だけ処理をする、などということができます。もちろんコントロールキーを押しながらクリックして複数選択する、という手もありますが、「これってユーザに優しくないよね」と常日頃思っている人には、チェックボックスのほうが良いかもしれません。
データのリスト表示や操作をするコンポーネントは一般的に、データ部分を提供するものと、そのデータの表示の仕方を指定して操作するものとに分ける、というパターンを使って作られていますが、ActionScript3.0もそのパターンで、データをグリッド(grid)表示するDataGrid、そのDataGridにデータを提供(provide)するのがDataProvider、そして、DataGridのそれぞれの列やセルの表示/描画の仕方を指示する(render)のがCellRenderer、という組み合わせになっています。デフォルトではデータをテキスト表示をするCellRendererが提供されています。
このDataGridのひとつの列をCheckboxにするには、fl.controls.CheckBoxクラスを拡張してfl.controls.listClasses.ICellRendererインターフェイスを実装した新しいクラスを定義し、チェックボックスにしたい列のcellRendererプロパティに、そのクラスを指定します。詳細なやり方はActionScript3.0のマニュアル「カスタムCellRendererクラスの定義」の「ICellRendererインターフェイスを実装するクラスを使用してカスタムCellRendererを定義するには」のセクションに記載されています。しかし、このページに掲載されているサンプルは動かすとエラーになるので、その代わりに、「DataGridCellEditorのオンラインマニュアルの(なぜか)コメント欄に記載されているコード例が一番参考になるでしょう。CellRendererを作成するのが初めてのかたは、まずはこのコード例を、そのまま試してみることをおすすめします。
このコード例ではDataGridの選択状況がチェックボックスと連動する作りになっています。今回、著者はチェックボックスが独立して機能するようにしたかったので、この記事ではこのコード例をベースに、その変更点について解説します。
では変更点を見ていきましょう。まずはfunction set selected()です。Adobe社のコード例では、ここでチェックボックスの選択状況をセットしていますが、このメソッドは、DataGridの行が選択された際に呼び出されます。一番最初にDataGridを表示した時点では、このメソッドは呼び出されないので、セルの値がチェックボックスにチェックに反映されず、チェックボックスは常にチェックが入っていない状態で表示されます。セルをクリックして初めてセルの値がチェックボックスに反映されます。また、ここでチェックボックスの選択状況をセットすると、DataGridの選択状況とチェックボックスの選択状況を連動させることになるため、ショッピングカートや冒頭で例示したような「社員教育受講管理」など、チェックボックスが単独で機能しないといけない場合に対応できません。DataGridの行を選択したらチェックが入るのではなく、チェックボックスをクリックしたらチェックが入ったりはずれたりして欲しいのです。なので、このロジックは後述のfunction set listData()とtoggleSelected()で実装します。ただし_rowSelected属性をセットしている部分は、DataGridを選択した際に表示色などを変えるときに使うので、残しておきます。
|
override public function set selected(value:Boolean):void { _rowSelected = value; } |
次にtoggleSelected()ですが、Adobe社のコード例では”don’t set selected or dispatch change event.” (selected属性に値をセットしたり、CHANGEイベントを送出しないように)と書いてありますが、上記のset selected()で記述した理由で、selected属性はここでセットします。
|
override protected function toggleSelected(event:MouseEvent):void { var dg:DataGrid = this.parent.parent.parent as DataGrid; var fName:String = dg.getColumnAt(_listData.column).dataField; var newStatus:Boolean = (_data[fName] == true || _data[fName] == "true" || _data[fName] == 1); super.selected = _data[fName] = newStatus; } |
これで、DataGridの選択状況とは関係なく、チェックボックスをクリックすれば正しい値がセットされる、チェックボックスらしい動きになります。もう一つやりたかったのは、DataGridを最初に表示したときにセルのBooleanの状況を正しくチェックボックスに反映することです。それがもう一箇所の変更点set listData()になります。set listData()は、DataProviderがDataGridにセットされるタイミングと、DataGridで何か変更が起きるタイミングの2箇所で呼び出されます(DataGrid.selectable=trueのとき)。その前者のタイミングを利用したいので、上記のset selected()で実装するはずだったロジックをこちらに移動するわけです。
|
public function set listData(ld:ListData):void { _listData = ld; var dg:DataGrid = this.parent.parent.parent as DataGrid; var fName:String = dg.getColumnAt(_listData.column).dataField; var newStatus:Boolean = (_data[fName] == true || _data[fName] == "true" || _data[fName] == 1); super.selected = newStatus; } |
これでDataGridの初期値がDataProviderのデータで埋まったときに、チェックボックスがセルの値を正しく表すようになります。
上記の変更を加えたCellRendererをDataGridのカラムにセットすれば、”true”や”false”という文字列の代わりにチェックボックスが表示されるようになります。このままでも使えますが、もしDataGridのListEvent.ITEM_CLICKイベントを拾って処理をするアプリケーションに使う場合は、最後にもう一工夫必要です。それはチェックボックスのCLICKイベントがListEvent.ITEM_CLICKEDに変換されるのを止めることです。なぜなら、今回実装しようとしている、DataGridとは連動せず単独に動作するチェックボックスの場合、チェックボックスをクリックするという行為の目的は、チェックボックスの値を変えることであり、DataGridの行を選択する、という目的ではないからです。
|
public function CheckBoxCellRenderer() { super(); this.addEventListener(MouseEvent.CLICK, handleClick, false, 0, true); } private function handleClick(ev:Event):void { ev.stopImmediatePropagation(); } |
これでOKです。
ところで、どこかのフォーラムの書き込みで、Adobe社のサンプルを見て「こんなに長いコードを書かないといけないの?!」と驚いている人を見かけました。確かにぱっと見ただけですと、ただチェックボックスを表示したいだけのわりには長く見えるかもしれませんが、要点はこの記事に書いた点だけで、他の6~7割のコードは全て表示スタイルに関するものです。まずは表示スタイルは何もいじらずそのままにして使ってみると、見た目ほど複雑ではないことに気が付かれると思います。
なお、このコードは著者がアプリケーション開発の過程で試行錯誤の結果導き出した一つの手法であり、皆様の参考用に掲載しているものです。ご
利用の条件につきましては、「サイトのご利用条件」をご一読ください。また、このコードは弊社が開発しているアプリケーションで実際に使われています。したがいまして、今後改善やバグ修正がされる可能性がありますが、変更が入りましたら随時この記事を更新します。