Using a CheckBox in a DataGrid in ActionScript 3.0 [AS3] – I Want a CheckBox Inside a DataGrid that Behaves Like a CheckBox

There is an entry on this blog that answers questions like “How do I put check boxes inside a datagrid?” and “How do I enable multiple check box selections?”, which is one of the popular entries on this blog. The entry is in Japanese, but I recently found out in an English forum that they seem to be universal questions. Thinking the entry might help a few more people, I tried some web page translation tools on the entry, but I couldn’t figure out any of what I was trying to say by reading the translated stuff, so I decided to translate the entry into English myself.

Well, so much for the introductory remarks. Here it is.

Data manipulation is a basic aspect of business applications, so it is probably safe to assume that a GUI-providing programming language has functions and components that deal with data manipulation like listing, sorting, etc. ActionScript 3.0 does, too.

In this entry, I will explain how to put check boxes in such data lists by adding few functions to code samples in Adobe’s online documents. Let’s assume that you are making a course registration application. By using the method explained in this entry, you can change the status of multiple students in one step by ticking multiple check boxes. Some components allow you to select multiple lines by clicking on them while holding down the Ctrl key, but if you think that method is not so user-friendly, then check boxes may be the solution.

Data manipulation components are commonly made with a pattern using a data grid, a data provider and a renderer. ActionScript 3.0 uses the same pattern, and provides
fl.controls.DataGrid that displays data in a grid of rows and columns, fl.data.DataProvider that provides data to a DataGrid, and fl.controls.listClasses.CellRenderer that tells the grid how to display the provided data. By default ActionScript 3.0 provides a CellRenderer class that displays the data in text.

To change one of the columns in a DataGrid to display a check box, 1) you make a new class that inherits the fl.controls.CheckBox class and implements the fl.controls.listClasses.ICellRenderer interface, and 2) specify the new class in the cellRenderer property of the subject column. The details are explained in the “Define a custom CellRenderer class” section of “Work with a CellRenderer” page on the ActionScript 3.0 Components manual. However, the code listed on this page results in an error, so for a samples code, the one listed in the comments section on fl.controls.dataGridClasses.DataGridCell is much more useful. If you are making a CellRenderer class for the very first time, I’d recommend you to just try this sample code first. This sample code is hereafter referred to as “the sample code” in this entry.

One point that I found inconvenient with the sample code was that each check box represents the selection status of a line in the grid. So, let’s take a step forward and make the check boxes independent of the selection status by going through the modifications that need to be made to the sample code.

First, we modify the function set selected(). In the sample code, the CheckBox’s status is set here, which presents two problems:

  1. This method is called when a line in the DataGrid is selected, so the status of a CheckBox always reflects the selection status of the containing row in the DataGrid; i.e a CheckBox is ticked when a row is selected, making it not appropriate for applications like shopping carts and the aforementioned course registration program. Instead, it should toggle its status when you click on it.
  2. This method is not called when the DataGrid is first displayed, so the cell values are not reflected to the CheckBox status, making the CheckBox unchecked by default no matter what the cell value is. It is only when a row is clicked (selected) that a cell value is reflected to the corresponding CheckBox.

In order to solve these problems, a part of the logic in set selected() is moved to functions set listData() and toggleSelected() both of which will be described later. The line that sets the _rowSelected attribute remains in set selected() so that visual attributes of the DataGrid object (e.g. colors) can be changed when a row is selected.

To solve problem #1, we will modify the function toggleSelected(), for which the sample code says “don’t set selected or dispatch change event”, but for the above mentioned reasons, the selected attribute is set here. (Please note that this is only a suggestion, so please use this at your own risk. For the rest of the usual caveats, please read our “Terms of Use”.)

Now we have a CheckBox that behaves like a CheckBox; i.e. if you click on it it toggles its check mark status regardless of the selection status of the DataGrid.

In order to solve problem #2, we will take a look at set listData(). set listData() is called 1) when a DataProvider is set to a DataGrid, and 2) when something is changed in a DataGrid (when DataGrid.selectable = true). We are taking advantage of the former timing, so we are moving the logic that had been implemented in set selected() down here.

By implementing this, a CheckBox will appropriately reflect the cell value when a DataGrid is filled with values specified in a DataProvider.

By setting the newly implemented CellRenderer to a column in a DataGrid, you will start seeing check boxes instead of “true” and “false” strings.

You can use the CellRenderer like this, but if your application handles ListEvent.ITEM_CLICK events, there is one more modification to make, which is to stop CheckBox’s CLICK events to be transformed to ListEvent.ITEM_CLICKED events, because we are making check boxes that behave independently of DataGrid’s selection status, and clicking on a check box does not mean selecting the corresponding row in a DataGrid.

So, there you have it – a Checkbox in a DataGrid that behaves like a CheckBox!

A few last comments — This code is one implementation method that I derived after much trial and error, which is listed here for your reference. Please read our “Terms of Use” before using the code.

This code is being used in application that we develop, and is subject for future modifications and bug fixes.

ActionScript3.0のDataGridでCheckboxを使いたい [AS3] – Checkbox CellRendererを作る

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を選択した際に表示色などを変えるときに使うので、残しておきます。

次にtoggleSelected()ですが、Adobe社のコード例では”don’t set selected or dispatch change event.” (selected属性に値をセットしたり、CHANGEイベントを送出しないように)と書いてありますが、上記のset selected()で記述した理由で、selected属性はここでセットします。

これで、DataGridの選択状況とは関係なく、チェックボックスをクリックすれば正しい値がセットされる、チェックボックスらしい動きになります。もう一つやりたかったのは、DataGridを最初に表示したときにセルのBooleanの状況を正しくチェックボックスに反映することです。それがもう一箇所の変更点set listData()になります。set listData()は、DataProviderがDataGridにセットされるタイミングと、DataGridで何か変更が起きるタイミングの2箇所で呼び出されます(DataGrid.selectable=trueのとき)。その前者のタイミングを利用したいので、上記のset selected()で実装するはずだったロジックをこちらに移動するわけです。

これでDataGridの初期値がDataProviderのデータで埋まったときに、チェックボックスがセルの値を正しく表すようになります。

上記の変更を加えたCellRendererをDataGridのカラムにセットすれば、”true”や”false”という文字列の代わりにチェックボックスが表示されるようになります。このままでも使えますが、もしDataGridのListEvent.ITEM_CLICKイベントを拾って処理をするアプリケーションに使う場合は、最後にもう一工夫必要です。それはチェックボックスのCLICKイベントがListEvent.ITEM_CLICKEDに変換されるのを止めることです。なぜなら、今回実装しようとしている、DataGridとは連動せず単独に動作するチェックボックスの場合、チェックボックスをクリックするという行為の目的は、チェックボックスの値を変えることであり、DataGridの行を選択する、という目的ではないからです。

これでOKです。

ところで、どこかのフォーラムの書き込みで、Adobe社のサンプルを見て「こんなに長いコードを書かないといけないの?!」と驚いている人を見かけました。確かにぱっと見ただけですと、ただチェックボックスを表示したいだけのわりには長く見えるかもしれませんが、要点はこの記事に書いた点だけで、他の6~7割のコードは全て表示スタイルに関するものです。まずは表示スタイルは何もいじらずそのままにして使ってみると、見た目ほど複雑ではないことに気が付かれると思います。

なお、このコードは著者がアプリケーション開発の過程で試行錯誤の結果導き出した一つの手法であり、皆様の参考用に掲載しているものです。ご
利用の条件につきましては、「サイトのご利用条件」をご一読ください。また、このコードは弊社が開発しているアプリケーションで実際に使われています。したがいまして、今後改善やバグ修正がされる可能性がありますが、変更が入りましたら随時この記事を更新します。