第4回Flex勉強会

テーマ

  • データプロバイダ (P257 ~ P300)
  • レンダラーとラベルファンクション (P287 ~ P290)
  • ViewStack?TabNavigator? (P305 ~ P307)

日時

2008/2/16(土)

概要

資料のダウンロードはこちら

データプロバイダ (P257 ~ P300) - 詳細

  1. データプロバイダの基礎知識 - 詳細
  2. XMLと連携する - 詳細
  3. Arrayと連携する - 詳細
  4. ArrayとArrayCollection?の違い - 詳細
  5. ソート順の指定 - 詳細
  6. ツリーの表示 - 詳細

レンダラーとラベルファンクション (P287 ~ P290) - 詳細

  1. レンダラーとラベルファンクションの基礎知識 - 詳細
  2. ラベルファンクション - 詳細
    1. リスト系コントロール用のラベルファンクション - 詳細
    2. データグリッド用のラベルファンクション - 詳細
    3. 指定するのはあくまでもFunctionオブジェクト - 詳細
    4. DTOの読み取り専用プロパティで代用 - 詳細
  3. レンダラー - 詳細
    1. 既存のコントロールをレンダラーに指定 - 詳細
    2. インラインでレンダラーを記述 - 詳細
    3. MXMLでレンダラークラスを作成 - 詳細
    4. ActionScript?でレンダラークラスを作成 - 詳細
    5. データグリッド全体にレンダラーを適用 - 詳細
    6. ClassFactory?をレンダラーに指定 - 詳細

ViewStack?TabNavigator? (P305 ~ P307) - 詳細

  1. ViewStack? - 詳細
  2. TabNavigator? - 詳細
  3. Accordion - 詳細

詳細

データプロバイダ (P257 ~ P300)

  1. データプロバイダの基礎知識
    • データプロバイダとは、複数の値を表示するコンポーネント(リスト系コントロールやデータグリッド)に対象となるデータを関連づける仕組み。
    • 複数の値を表示するコンポーネントのdataProviderプロパティに、XMLやArrayオブジェクトを指定する。
      (主にデータバインディングを使って指定する。)
    • リスト系のコンポーネントには次のようなものがある。
      • mx.controls.List - リスト (HTMLの複数行表示のSELECTフォームに似ている、リストに無い値をユーザーが自由に追加することは基本的にできない)
      • mx.controls.ComboBox? - コンボボックス (HTMLの単一行表示のSELECTフォームに似ている、リストに無い値をユーザーが自由に追加することも基本的にできる)
      • mx.controls.HorizontalList? - 横方向のリスト
      • mx.controls.Tree - ツリー
      • mx.controls.Menu - ポップアップメニュー
      • mx.controls.ButtonBar? - ボタン(mx.controls.Button)のグループ
      • mx.controls.LinkBar? - リンクボタン(mx.controls.LinkButton?)のグループ (ViewStack?の制御にも使える)
      • mx.controls.ToggleButtonBar? - トグルボタン(1つだけが選択状態にできるボタン)のグループ (ViewStack?の制御にも使える)
    • 関連付けたデータのどのフィールドの値を表示するかは、リスト系のコンポーネントの場合はlabelFieldプロパティ使って指定する。
      (注)XMLのノードの属性の値を表示する場合は、指定する値の先頭に「@」をつける必要があるので注意。
    • データグリッド(mx.controls.DataGrid?)は複数列に渡ってデータを表示するので、以下のようにリスト系のコンポーネントとは使い方が異なる点がある。
      • 各カラムの情報を設定するために、columnsプロパティにmx.controls.dataGridClasses?.DataGridColumn?クラスの配列を指定する必要がある。
      • DataGridColumn?ではheaderTextプロパティにヘッダ行に表示するテキスト、dataFieldプロパティ(labelFieldではないので要注意)にどのフィールドの値を表示するかを指定する。
        dataFieldプロパティに指定した値は、表示だけでなくソートのキーとしても使用される。 (後述のレンダラーやラベルファンクションを指定する場合にも効いてくるので重要)
    • columsプロパティの指定は、下記の例のようにタグで記述すると簡単に行える。
          <mx:DataGrid>
              <!-- データグリッドの各カラム(列)の情報を指定 -->
              <mx:columns>
                  <mx:DataGridColumn headerText="ヘッダ行に表示するテキスト1" dataField="対象フィールド1" />
                  <mx:DataGridColumn headerText="ヘッダ行に表示するテキスト2" dataField="対象フィールド2" />
                  <mx:DataGridColumn headerText="ヘッダ行に表示するテキスト3" dataField="対象フィールド3" />
              </mx:columns>
          </mx:DataGrid>
  2. XMLと連携する
    • XMLデータをFlexで読み込むには色々な方法があるが、最も手っ取り早くて確実なのが<mx:XML>タグを使う方法である。
    • プロジェクト内のXMLファイルを<mx:XML>タグを使って読み込む場合は、sourceプロパティにMXMLファイルの位置からの相対パスで指定する。
      この場合、対象のXMLファイルはコンパイル時にswfファイルに組み込まれ、初期化時にはXMLのパースまで終了した状態になっているので、読み込み完了まで待つという処理を行う必要がない。
      さらに、コンパイル時にXMLファイルの存在チェックや、正しい形式のXMLかどうかのチェックまで行ってくれるので、他の方法に比べて非常におすすめ。
    • XMLをデータプロバイダに指定する場合は、コンポーネントのdataProviderプロパティに対象のXMLオブジェクトの繰り返し部分のノードを指定する。
      (注)このとき、ルートノードの要素はデータプロバイダの記述に含めないので要注意。
    • labelFieldプロパティやdataFieldプロパティに指定する値は、dataProviderプロパティに指定したノードからの相対パスで指定する。
    • (注)データプロバイダにXMLを指定する場合は、各要素の値はデータバインディング可能にできないので注意。
      (デバッグ実行時に警告が大量に発生する)
       
    • サンプルプログラムで使用する対象のXMLデータ - filexml/data.xml
      <?xml version="1.0" encoding="utf-8"?>
      <root>
          <person>
              <lastName>山田</lastName>
              <firstName>太郎</firstName>
              <age>21</age>
              <tel>000-111-222</tel>
              <email>aaa@hoge.com</email>
              <gender></gender>
          </person>
          <person>
              <lastName>佐藤</lastName>
              <firstName>花子</firstName>
              <age>25</age>
              <tel>111-222-333</tel>
              <email>bbb@hoge.com</email>
              <gender></gender>
          </person>
          <person>
              <lastName>スミス</lastName>
              <firstName>ジョン</firstName>
              <age>41</age>
              <tel>999-111-222</tel>
              <email>ccc@hoge.com</email>
              <gender></gender>
          </person>
          <person>
              <lastName>斉藤</lastName>
              <firstName>次郎</firstName>
              <age>22</age>
              <tel>555-111-222</tel>
              <email>ddd@hoge.com</email>
              <gender></gender>
          </person>
          <person>
              <lastName>鈴木</lastName>
              <firstName>さくら</firstName>
              <age>15</age>
              <tel>666-111-222</tel>
              <email>eee@hoge.com</email>
              <gender></gender>
          </person>
      </root>
       
    • サンプルプログラム - リストのデータプロバイダにXMLのデータを指定  (実行画面はこちら)
      fileListXMLDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
          <!-- 対象のXMLデータ -->
          <mx:XML id="xmlData" source="xml/data.xml" />
          
          <mx:VBox width="100%" height="100%">
              <!-- リストのデータプロバイダにXMLデータを指定 -->
              <!-- (表示対象のフィールド(labelField)にはlastName(姓)を指定) -->
              <mx:List 
                  dataProvider="{this.xmlData.person}" 
                  labelField="lastName" 
              />
          </mx:VBox>
      </mx:Application>
       
    • サンプルプログラム - データグリッドのデータプロバイダにXMLのデータを指定  (実行画面はこちら)
      fileDataGridXMLDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
          <!-- 対象のXMLデータ -->
          <mx:XML id="xmlData" source="xml/data.xml" />
          
          <mx:VBox width="100%" height="100%">
              <!-- データグリッドのデータプロバイダにXMLデータを指定 -->
              <mx:DataGrid dataProvider="{this.xmlData.person}">
                  <!-- データグリッドの各カラム(列)の情報を指定 -->
                  <mx:columns>
                      <mx:DataGridColumn headerText="" dataField="lastName" />
                      <mx:DataGridColumn headerText="" dataField="firstName" />
                      <mx:DataGridColumn headerText="年齢" dataField="age" />
                      <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                      <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                      <mx:DataGridColumn headerText="性別" dataField="gender" />
                  </mx:columns>
              </mx:DataGrid>
          </mx:VBox>
      </mx:Application>
  3. Arrayと連携する
    • 配列(Array)データをデータプロバイダに指定する場合は、配列に格納するオブジェクトは生のObjectクラス(無名オブジェクト)を使う方法と、DTOクラスを使う方法がある。
    • 無名オブジェクトを使う方法の場合は、あらかじめクラスを定義しなくても自由なプロパティを持つオブジェクトを手っ取り早く作ることができる。
      ただし、XMLの場合と同じく各要素の値はデータバインディング可能にできないので注意。
      (デバッグ実行時に警告が大量に発生する)
    • DTOクラスを使う方法の場合は、あらかじめDTOクラスを定義する必要があるので他の方法に比べて手間がかかる。
      しかし、DTOクラスは読み取り専用のGetterプロパティを定義したり、サーバー側との連携に使ったりすることもできるなど、色々とメリットがあるので最もおすすめの方法である。
       
    • サンプルプログラム - リストのデータプロバイダに配列のデータを指定  (実行画面はこちら)
      fileListArrayDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
          <mx:Script>
              <![CDATA[
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = 
                  [
                      {
                          lastName: "山田",
                          firstName: "太郎",
                          age: 21,
                          tel: "000-111-222",
                          email: "aaa@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "佐藤",
                          firstName: "花子",
                          age: 25,
                          tel: "111-222-333",
                          email: "bbb@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "スミス",
                          firstName: "ジョン",
                          age: 41,
                          tel: "999-111-222",
                          email: "ccc@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "斉藤",
                          firstName: "次郎",
                          age: 22,
                          tel: "555-111-222",
                          email: "ddd@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "鈴木",
                          firstName: "さくら",
                          age: 15,
                          tel: "666-111-222",
                          email: "eee@hoge.com",
                          gender: ""
                      }
                  ];
              ]]>
          </mx:Script>
      
          <mx:VBox width="100%" height="100%">
              <!-- リストのデータプロバイダに対象データの配列を指定 -->
              <mx:List 
                  dataProvider="{this.dataArray}" 
                  labelField="lastName" 
              />
          </mx:VBox>
      </mx:Application>
       
    • サンプルプログラム - データグリッドのデータプロバイダに配列のデータを指定  (実行画面はこちら)
      fileDataGridArrayDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
          <mx:Script>
              <![CDATA[
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = 
                  [
                      {
                          lastName: "山田",
                          firstName: "太郎",
                          age: 21,
                          tel: "000-111-222",
                          email: "aaa@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "佐藤",
                          firstName: "花子",
                          age: 25,
                          tel: "111-222-333",
                          email: "bbb@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "スミス",
                          firstName: "ジョン",
                          age: 41,
                          tel: "999-111-222",
                          email: "ccc@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "斉藤",
                          firstName: "次郎",
                          age: 22,
                          tel: "555-111-222",
                          email: "ddd@hoge.com",
                          gender: ""
                      },
                      {
                          lastName: "鈴木",
                          firstName: "さくら",
                          age: 15,
                          tel: "666-111-222",
                          email: "eee@hoge.com",
                          gender: ""
                      }
                  ];
              ]]>
          </mx:Script>
          
          <mx:VBox width="100%" height="100%">
              <!-- データグリッドのデータプロバイダに対象データの配列を指定 -->
              <mx:DataGrid dataProvider="{this.dataArray}">
                  <!-- データグリッドの各カラム(列)の情報を指定 -->
                  <mx:columns>
                      <mx:DataGridColumn headerText="" dataField="lastName" />
                      <mx:DataGridColumn headerText="" dataField="firstName" />
                      <mx:DataGridColumn headerText="年齢" dataField="age" />
                      <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                      <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                      <mx:DataGridColumn headerText="性別" dataField="gender" />
                  </mx:columns>
              </mx:DataGrid>
          </mx:VBox>
      </mx:Application>
       
    • サンプルプログラム - データグリッドのデータプロバイダにDTOの配列のデータを指定  (実行画面はこちら)
      fileDataGridArrayDtoDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
          creationComplete="onCreationComplete()"
          >
          <mx:Script>
              <![CDATA[
                  import dto.PersonDto;
                  
                  //==========================================================
                  //フィールド
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = new Array();
                  
                  
                  //==========================================================
                  //メソッド
                  
                  /**
                   * 初期化処理を行います。
                   */
                  private function onCreationComplete() :void
                  {
                      //==========================================================
                      //DTOベースのデータを配列に設定
                      this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                      this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                      this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                      this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                      this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
      
                      //データグリッドのデータプロバイダに対象データの配列を指定
                      this.arrayDataGrid.dataProvider = this.dataArray;
                  }
              ]]>
          </mx:Script>
          
          <mx:VBox width="100%" height="100%">
              <!-- データグリッド -->
              <!-- (ここで対象データの配列をバインディングしても、初期化前には配列のデータがないため何も表示されないので注意) -->
              <mx:DataGrid id="arrayDataGrid">
                  <!-- データグリッドの各カラム(列)の情報を指定 -->
                  <mx:columns>
                      <mx:DataGridColumn headerText="" dataField="lastName" />
                      <mx:DataGridColumn headerText="" dataField="firstName" />
                      <mx:DataGridColumn headerText="年齢" dataField="age" />
                      <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                      <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                      <mx:DataGridColumn headerText="性別" dataField="gender" />
                  </mx:columns>
              </mx:DataGrid>
          </mx:VBox>
      </mx:Application>
      filedto.PersonDto.as
      package dto
      {
          /**
           * 個人情報用DTOクラス。
           */
          [Bindable]
          public class PersonDto
          {
              //==========================================================
              //フィールド
              
              /**
               * 姓
               */
              public var lastName :String = null;
              
              /**
               * 名
               */
              public var firstName :String = null;
              
              /**
               * 年齢
               */
              public var age :int = 0;
              
              /**
               * 電話番号
               */
              public var tel :String = null;
              
              /**
               * メールアドレス
               */
              public var email :String = null;
              
              /**
               * 性別
               */
              public var gender :String = null;
              
              
              //==========================================================
              //メソッド
              
              //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
              //コンストラクタ
              
              /**
               * コンストラクタです。
               * 
               * @param lastName 姓
               * @param firstName 名
               * @param age 年齢
               * @param tel 電話番号
               * @param email メールアドレス
               * @param gender 性別
               */
              public function PersonDto(lastName :String = null, firstName :String = null, age :int = 0, tel :String = null, email :String = null, gender :String = null)
              {
                  //引数の値をフィールドに設定
                  this.lastName = lastName;
                  this.firstName = firstName;
                  this.age = age;
                  this.tel = tel;
                  this.email = email;
                  this.gender = gender;
              }
      
          }
      }
  4. ArrayとArrayCollection?の違い
    • 単純な配列(Arrayクラス)をデータプロバイダに指定した場合は、配列に要素を追加・削除しても変更が反映されない。
      これに対して、Arrayクラスをラッピングしたmx.collections.ArrayCollection?クラスをデータプロバイダに指定した場合は、配列に要素を追加・削除した場合も変更が反映される。
    • ArrayCollection?に配列を関連付けるには、コンストラクタで指定するか、ArrayCollection?のsourceプロパティに配列を指定する。
    • ArrayCollection?への要素の追加はaddItem()メソッド、要素の削除はremoveItemAt?()メソッドを使って行う。
      (注)中身の配列へ直接要素の追加・削除を行ってもよいが、その場合はArrayCollection?のrefresh()メソッドを呼ばないと変更が反映されないので注意。
    • ArrayのラッピングクラスにArrayCollection?クラスがあるように、XMLの場合はmx.collections.XMLListCollection?というラッピングクラスがある。
    • データプロバイダにArrayやXMLを指定した場合は、実際には裏でArrayCollection?やXMLListCollection?のインスタンスが生成されて、そちらがデータプロバイダに割り当てられる。
       
    • サンプルプログラム - データグリッドのデータプロバイダにArrayとArrayCollection?を指定した場合の動作の違い  (実行画面はこちら)
      fileDataGridArrayCollectionDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
          creationComplete="onCreationComplete()"
          >
          <mx:Script>
              <![CDATA[
                  import mx.collections.ArrayCollection;
                  import dto.PersonDto;
                  
                  //==========================================================
                  //フィールド
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = new Array();
                  
                  /**
                   * 対象データのArrayCollection
                   */
                  [Bindable]
                  private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                  
                  
                  //==========================================================
                  //メソッド
                  
                  /**
                   * 初期化処理を行います。
                   */
                  private function onCreationComplete() :void
                  {
                      //==========================================================
                      //DTOベースのデータを配列に設定
                      this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                      this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
      
                      //ArrayCollectionに配列を関連づける
                      this.dataArrayCollection.source = this.dataArray;
                  }
                  
                  /**
                   * Arrayにデータ追加ボタンが押された場合のイベント処理を行います。
                   */
                  private function onAddArrayButtonClick() :void
                  {
                      //対象データの配列にデータを追加
                      this.dataArray.push(new PersonDto("Arrayに", "追加", 88, "888-111-222", "array@hoge.com", ""));
                  }
      
                  /**
                   * Arrayにデータ追加(Refresh付き)ボタンが押された場合のイベント処理を行います。
                   */
                  private function onAddArrayWithRefreshButtonClick() :void
                  {
                      //対象データの配列にデータを追加
                      this.dataArray.push(new PersonDto("Arrayに", "追加(Refresh付き)", 89, "889-111-222", "arrayRefresh@hoge.com", ""));
                      
                      //対象データのArrayCollectionをリフレッシュ
                      this.dataArrayCollection.refresh();
                  }
      
                  /**
                   * ArrayCollectionにデータ追加ボタンが押された場合のイベント処理を行います。
                   */
                  private function onAddArrayCollectionButtonClick() :void
                  {
                      //対象データのArrayCollectionにデータを追加
                      this.dataArrayCollection.addItem(new PersonDto("ArrayCollectionに", "追加", 99, "999-111-222", "arrayCollection@hoge.com", ""));
                  }
                  
                  /**
                   * dataProviderをリセットボタンが押された場合のイベント処理を行います。
                   */
                  private function onDataProviderResetButtonClick() :void
                  {
                      //データグリッドのデータプロバイダに対象データの配列を指定
                      this.arrayDataGrid.dataProvider = this.dataArray;
                      
                      //データグリッドのデータプロバイダに対象データのArrayCollectionを指定
                      this.arrayCollectionDataGrid.dataProvider = this.dataArrayCollection;
                  }
              ]]>
          </mx:Script>
          
          <mx:VBox width="100%" height="100%">
              <!-- Arrayの場合 -->
              <mx:Panel width="100%" height="100%" title="Arrayをデータプロバイダに設定">
                  <!-- データグリッドのデータプロバイダに対象データの配列を指定 -->
                  <mx:DataGrid id="arrayDataGrid" dataProvider="{this.dataArray}" width="100%" height="100%">
                      <!-- データグリッドの各カラム(列)の情報を指定 -->
                      <mx:columns>
                          <mx:DataGridColumn headerText="" dataField="lastName" />
                          <mx:DataGridColumn headerText="" dataField="firstName" />
                          <mx:DataGridColumn headerText="年齢" dataField="age" />
                          <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                          <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                          <mx:DataGridColumn headerText="性別" dataField="gender" />
                      </mx:columns>
                  </mx:DataGrid>
              </mx:Panel>
      
              <!-- ArrayCollectionの場合 -->
              <mx:Panel width="100%" height="100%" title="ArrayCollectionをデータプロバイダに設定">
                  <!-- データグリッドのデータプロバイダに対象データのArrayCollectionを指定 -->
                  <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%" height="100%">
                      <!-- データグリッドの各カラム(列)の情報を指定 -->
                      <mx:columns>
                          <mx:DataGridColumn headerText="" dataField="lastName" />
                          <mx:DataGridColumn headerText="" dataField="firstName" />
                          <mx:DataGridColumn headerText="年齢" dataField="age" />
                          <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                          <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                          <mx:DataGridColumn headerText="性別" dataField="gender" />
                      </mx:columns>
                  </mx:DataGrid>
              </mx:Panel>
      
              <mx:Button label="Arrayにデータ追加" click="onAddArrayButtonClick()" />
              <mx:Button label="Arrayにデータ追加(Refresh付き)" click="onAddArrayWithRefreshButtonClick()" />
              <mx:Button label="ArrayCollectionにデータ追加" click="onAddArrayCollectionButtonClick()" />
              <mx:Button label="dataProviderをリセット" click="onDataProviderResetButtonClick()" />
          </mx:VBox>
      </mx:Application>
  5. ソート順の指定
    • データグリッドのソート順は、実はデータグリッドコントロールではなく、データプロバイダに指定したデータ側に設定されている。
      (XMLでデータを指定した場合はXMLListCollection?, 配列でデータを指定した場合はArrayCollection?)
    • XMLListCollection?ArrayCollection?のsortプロパティを使えば、スクリプトでソート順の取得・変更を行うことができる。
    • ソート順は、mx.collections.Sortクラスとその要素クラスであるmx.collections.SortField?クラスによって表現される。
    • スクリプトでsortプロパティの値を変更した場合は、必ずrefresh()メソッドを呼び出して変更を反映させる必要がある。
       
    • サンプルプログラム - データグリッドのソート順をスクリプトで変更  (実行画面はこちら)
      fileDataGridSortSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
          creationComplete="onCreationComplete()"
          >
          <mx:Script>
              <![CDATA[
                  import mx.collections.SortField;
                  import mx.collections.Sort;
                  import mx.collections.ArrayCollection;
                  import dto.PersonDto;
                  
                  //==========================================================
                  //フィールド
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = new Array();
                  
                  /**
                   * 対象データのArrayCollection
                   */
                  [Bindable]
                  private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                  
                  
                  //==========================================================
                  //メソッド
                  
                  /**
                   * 初期化処理を行います。
                   */
                  private function onCreationComplete() :void
                  {
                      //==========================================================
                      //DTOベースのデータを配列に設定
                      this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                      this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                      this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                      this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                      this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
      
                      //ArrayCollectionに配列を関連づける
                      this.dataArrayCollection.source = this.dataArray;
                      
                      
                      //==========================================================
                      //初期のソート順を設定
      
                      //ソートオブジェクトを生成
                      var sort :Sort = new Sort();
                      
                      //ソート順にtel(電話番号)の昇順を指定
                      sort.fields = [new SortField("tel")];
                      
                      //ArrayCollectionのソート順を変更
                      this.dataArrayCollection.sort = sort;
                      
                      //ArrayCollectionをリフレッシュ
                      //(これをしないとソート順の変更が反映されない)
                      this.dataArrayCollection.refresh();
                  }
                  
                  /**
                   * 姓の降順でソートボタンが押された場合のイベント処理を行います。
                   */
                  private function onLastNameSortButtonClick() :void
                  {
                      //ソートオブジェクトを生成
                      var sort :Sort = new Sort();
                      
                      //ソート順にlastName(姓)の降順を指定
                      //(昇順・降順は第3引数で指定する:true=降順, false=昇順(デフォルト))
                      //(第2引数は大文字・小文字の違いを無視するかどうかのフラグ: true=無視する, false=無視しない(デフォルト))
                      //(第4引数はアルファベット順ではなく数字として比較するかどうかのフラグ: true=数字として比較する, false=アルファベット順で比較する(デフォルト))
                      sort.fields = [new SortField("lastName", false, true, false)];
                      
                      //ArrayCollectionのソート順を変更
                      this.dataArrayCollection.sort = sort;
                      
                      //ArrayCollectionをリフレッシュ
                      //(これをしないとソート順の変更が反映されない)
                      this.dataArrayCollection.refresh();
                  }
      
                  /**
                   * 複数カラムでソートボタンが押された場合のイベント処理を行います。
                   */
                  private function onMultiSortButtonClick() :void
                  {
                      //ソートオブジェクトを生成
                      var sort :Sort = new Sort();
                      
                      //ソート順にgender(性別)の昇順, email(メールアドレス)の昇順を指定
                      sort.fields = [new SortField("gender"), new SortField("email")];
                      
                      //ArrayCollectionのソート順を変更
                      this.dataArrayCollection.sort = sort;
                      
                      //ArrayCollectionをリフレッシュ
                      //(これをしないとソート順の変更が反映されない)
                      this.dataArrayCollection.refresh();
                  }
              ]]>
          </mx:Script>
          
          <mx:VBox width="100%" height="100%">
              <!-- データグリッドのデータプロバイダに対象データのArrayCollectionを指定 -->
              <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}">
                  <!-- データグリッドの各カラム(列)の情報を指定 -->
                  <mx:columns>
                      <mx:DataGridColumn headerText="" dataField="lastName" />
                      <mx:DataGridColumn headerText="" dataField="firstName" />
                      <mx:DataGridColumn headerText="年齢" dataField="age" />
                      <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                      <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                      <mx:DataGridColumn headerText="性別" dataField="gender" />
                  </mx:columns>
              </mx:DataGrid>
      
              <mx:Button label="姓の降順でソート" click="onLastNameSortButtonClick()" />
              <mx:Button label="複数カラムでソート" click="onMultiSortButtonClick()" />
          </mx:VBox>
      </mx:Application>
  6. ツリーの表示
    • ツリーに表示するデータを設定する場合も、リストと同じようにデータプロバイダで行う。
    • ツリー構造のXMLをdataProviderに指定する方法が一般的で、世間に出回っているサンプルにもほとんどその方法しか載っていないが、DTOの配列を指定する方法もある。
      (むしろ、そちらの方が応用範囲が広がるのでおすすめ)
    • DTOの配列を指定する場合は、「children」という名前のArray型(ArrayCollection?でも可)のプロパティに配下の要素を格納する必要がある。
      (注)「children」以外の名前だと配下の要素と認識されないので注意。
    • サーバー側のオブジェクトのマッピングの都合などで配下の要素のプロパティ名を「children」にできない場合は、下記の例のように読み取り専用プロパティとして「children」を用意して、他のArray型のフィールドの値をそのまま返すという荒技で対処することができる。
          //配下の要素を格納するフィールド
          public var subElementArray :Array;
      
          /**
           * childrenプロパティのGetter
           */
          public function get children() :Array
          {
              //他のフィールドの値をそのまま返す
              return this.subElementArray;
          }
    • XMLで指定する場合は、配下の要素を持つ場合のみブランチノードと見なされるので、中身のないブランチノードを作ることはできない。
    • DTOの配列で指定する場合は、childrenプロパティがnullのオブジェクトがリーフノード、それ以外のオブジェクトがブランチノードと見なされるので、childrenプロパティに空配列を指定すれば中身のないブランチノードを作ることもできる。
       
    • サンプルプログラム - ツリーのデータプロバイダにXMLのデータを指定  (実行画面はこちら)
      fileTreeXMLDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
          <!-- 対象のXMLデータ -->
          <mx:XML id="xmlData" source="xml/treeData.xml" />
          
          <mx:VBox width="100%" height="100%">
              <!-- ツリーのデータプロバイダにXMLデータを指定 -->
              <!-- (表示対象のフィールド(labelField)にはname属性を指定(属性なので@をつける)) -->
              <mx:Tree width="100%" height="100%"
                  dataProvider="{this.xmlData.node}" 
                  labelField="@name" 
              />
          </mx:VBox>
      </mx:Application>
      対象のXMLデータ - filexml/treeData.xml
      <?xml version="1.0" encoding="utf-8"?>
      <root>
          <node name="1">
              <node name="1-1" />
              <node name="1-2">
                  <node name="1-2-1" />
                  <node name="1-2-2" />
              </node>
              <node name="1-3" />
          </node>
          <node name="2" />
          <node name="3">
              <node name="3-1" />
              <node name="3-2" />
          </node>
      </root>
       
    • サンプルプログラム - ツリーのデータプロバイダにDTOの配列のデータを指定  (実行画面はこちら)
      fileTreeDtoArrayDataProviderSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
          creationComplete="onCreationComplete()"
          >
          <mx:Script>
              <![CDATA[
                  import mx.collections.ArrayCollection;
                  import dto.TreeDataDto;
                  //==========================================================
                  //フィールド
                  
                  /**
                   * 対象データの配列
                   */
                  [Bindable]
                  private var dataArray :Array = new Array();
                  
                  /**
                   * 対象データのArrayCollection
                   */
                  [Bindable]
                  private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                  
                  
                  //==========================================================
                  //メソッド
                  
                  /**
                   * 初期化処理を行います。
                   */
                  private function onCreationComplete() :void
                  {
                      //==========================================================
                      //DTOベースのデータを配列に設定
                      
                      //ノード1のツリー構造を生成
                      var node1 :TreeDataDto = 
                          new TreeDataDto("1", 
                          [
                              new TreeDataDto("1-1"),
                              new TreeDataDto("1-2", 
                              [
                                  new TreeDataDto("1-2-1"),
                                  new TreeDataDto("1-2-2")
                              ]),
                              new TreeDataDto("1-3(childrenに空配列を指定)", new Array()) //childrenに空配列を指定するとnullとは違って子供のあるノードと認識される
                          ]
                      );
                      
                      //ノード2のツリー構造を生成
                      var node2 :TreeDataDto = new TreeDataDto("2"); 
      
                      //ノード3のツリー構造を生成
                      var node3 :TreeDataDto = 
                          new TreeDataDto("3", 
                          [
                              new TreeDataDto("3-1"),
                              new TreeDataDto("3-2")
                          ]
                      );
                      
                      //作成したノードを配列に設定
                      this.dataArray = [node1, node2, node3];
      
                      //ArrayCollectionに配列を関連づける
                      this.dataArrayCollection.source = this.dataArray;
                  }
              ]]>
          </mx:Script>
          
          <mx:VBox width="100%" height="100%">
              <!-- ツリーのデータプロバイダに対象データのArrayCollectionを指定 -->
              <!-- (表示対象のフィールド(labelField)にはnameを指定) -->
              <mx:Tree width="100%" height="100%"
                  dataProvider="{this.dataArrayCollection}" 
                  labelField="name" 
              />
          </mx:VBox>
      </mx:Application>
      filedto.TreeDataDto.as
      package dto
      {
          /**
           * ツリー情報用DTOクラス。
           */
          [Bindable]
          public class TreeDataDto
          {
              //==========================================================
              //フィールド
              
              /**
               * 名前
               */
              public var name :String = null;
              
              /**
               * 配下のノードの配列
               * (childrenという名前でないとツリーコントロールが反応しないので要注意)
               */
              public var children :Array = null;
              
              
              //==========================================================
              //メソッド
              
              //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
              //コンストラクタ
              
              /**
               * コンストラクタです。
               * 
               * @param name 名前
               * @param children 配下のノードの配列
               */
              public function TreeDataDto(name :String = null, children :Array = null)
              {
                  //引数の値をフィールドに設定
                  this.name = name;
                  this.children = children;
              }
      
          }
      }

レンダラーとラベルファンクション (P287 ~ P290)

  1. レンダラーとラベルファンクションの基礎知識
    • レンダラーとラベルファンクションは共に表示方法をカスタマイズするための仕組み。
    • ラベルファンクションは、表示される文字列のみをカスタマイズすることができる。
      できることは限られているが、シンプルゆえに使いやすい。
    • レンダラーは、文字列の代わりに任意のコンポーネントを表示することができる。
      これを使えば、データグリッドの列の中に画像やチェックボックスを表示することもできる。
      簡単なレンダラーを作成するのはそれほど難しくないが、高度にカスタマイズされたレンダラーを作成するにはかなりの知識を必要とするので奥が深い。
    • レンダラーとラベルファンクションの使い分けは以下のように行うと良い。
      • 単純なフォーマット変換 (カンマ区切りで表示、日付フォーマット変換など) → ラベルファンクション
      • 複数のデータを1列にまとめて表示したい → レンダラー
      • 表示をラベルではなくリンクにしたい → レンダラー
      • 列の中にボタンやチェックボックスを表示したい → レンダラー
  2. ラベルファンクション
    1. リスト系コントロール用のラベルファンクション
      • コントロールのlabelFunctionプロパティに、フォーマット変換を行うメソッドのFunctionオブジェクトを指定する。
        (注)Functionオブジェクトを指定する場合は、メソッド名の後ろに「()」をつけてはいけないので注意。
      • 指定できるメソッドの形式は下記の形式と決まっている。
        (注)引数の数・型が合わないメソッドをラベルファンクションに指定した場合は、コンパイル時ではなく実行時にエラーになるので注意。
            /**
             * リスト用のラベルファンクション。
             * 
             * @param item 対象オブジェクト
             * @return フォーマット変換後の文字列
             */
            private function myListLabelFunction(item :Object) :String {}
      • labelFieldで指定したフィールドの値は表示されず、labelFunctionに指定した関数からの戻り値が実際に表示される文字列となる。
         
      • サンプルプログラム - リストにラベルファンクションを指定  (実行画面はこちら)
        fileListLabelFunctionSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                    /**
                     * 年齢のフォーマット変換を行います。(リスト用のラベルファンクション)
                     * 
                     * @param item 対象オブジェクト
                     * @return フォーマット変換後の文字列
                     */
                    private function formatAge(item :Object) :String
                    {
                        //対象のオブジェクトを元の型にキャスト
                        var person :PersonDto = item as PersonDto;
                        
                        //年齢に「歳」をつけて返す
                        return person.age + "";
                    }
                    
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- リスト -->
                <!-- (ラベルファンクションを指定) -->
                <mx:List 
                    dataProvider="{this.dataArrayCollection}" 
                    labelFunction="formatAge"
                />
            </mx:VBox>
        </mx:Application>
    2. データグリッド用のラベルファンクション
      • 指定できるメソッドの形式は下記の形式と決まっている。
        (注)データグリッド用のラベルファンクションは、リスト系コントロール用のものとはメソッドの引数の形式が違うので要注意。
            /**
             * データグリッド用のラベルファンクション。
             * 
             * @param item DataGridアイテムオブジェクト
             * @param column DataGrid列
             * @return フォーマット変換後の文字列
             */
            private function myDataGridLabelFunction(item :Object, column :DataGridColumn) :String {}
      • dataFieldに指定したフィールドの値は、下記の例のようにすると取得できる。
            //対象のフィールドの値を取得
            var targetObj :Object = item[column.dataField];
        
            //型がわかっている場合は、このようにObject型ではなく具体的な型で取得しても良い
            var targetStr :String = item[column.dataField];
         
      • サンプルプログラム - データグリッドにラベルファンクションを指定  (実行画面はこちら)
        fileDataGridLabelFunctionSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                    /**
                     * 年齢のフォーマット変換を行います。(データグリッド用のラベルファンクション)
                     * 
                     * @param item DataGridアイテムオブジェクト
                     * @param column DataGrid列
                     * @return フォーマット変換後の文字列
                     */
                    private function formatAge(item :Object, column :DataGridColumn) :String
                    {
                        //対象のフィールドの値を取得
                        var targetStr :String = item[column.dataField];
                        
                        //対象のフィールドの値に「歳」をつけて返す
                        return targetStr + "";
                    }
                    
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%">
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" labelFunction="formatAge" /> <!-- ラベルファンクションを指定 -->
                        <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                        <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                        <mx:DataGridColumn headerText="性別" dataField="gender" />
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    3. 指定するのはあくまでもFunctionオブジェクト
      • ラベルファンクションに指定するのはあくまでも単なるFunctionオブジェクトなので、同じクラス内のメソッドでなくても指定できる。
      • そこで、数値をカンマ区切りに変換したり、日付フォーマットを行ったり汎用的なフォーマッタはユーティリティクラスにstaticなメソッドとして定義しておくと、どの画面からも共通のラベルファンクションとして使用できるので便利である。
      • ユーティリティクラスにラベルファンクションを定義する場合は、リスト系コントロール用のものと、データグリッド用のものを両方定義しておくと良い。
      • ラベルファンクションでは渡されたデータと全然関係のない文字列を返しても良いが、あまり意味がないのでおそらくそんなことをすることはない(はず)
    4. DTOの読み取り専用プロパティで代用
      • データプロバイダにDTOの配列を使用する場合は、ラベルファンクションを用意する代わりに、DTO側にフォーマット用の読み取り専用プロパティを用意してその値を表示することもできる。
      • もちろん、ラベルファンクションと併用して使用することもできる。
      • この方法は、リスト系のコンポーネントとデータグリッドのラベルファンクションのメソッドの形式の違いに影響されないのでおすすめ。
         
      • サンプルプログラム - ラベルファンクションの代わりにDTOの読み取り専用プロパティを使って表示文字列をカスタマイズ  (実行画面はこちら)
        fileDataGridDtoGetterSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonMk2Dto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonMk2Dto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonMk2Dto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonMk2Dto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonMk2Dto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonMk2Dto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                    /**
                     * 年齢のフォーマット変換を行います。(データグリッド用のラベルファンクション)
                     * 
                     * @param item DataGridアイテムオブジェクト
                     * @param column DataGrid列
                     * @return フォーマット変換後の文字列
                     */
                    private function formatAge(item :Object, column :DataGridColumn) :String
                    {
                        //対象のフィールドの値を取得
                        var targetStr :String = item[column.dataField];
                        
                        //対象のフィールドの値に「歳」をつけて返す
                        return targetStr + "";
                    }
                    
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%">
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="フルネーム" dataField="fullName" /> <!-- dataFieldに読み取り専用プロパティを指定 -->
                        <mx:DataGridColumn headerText="年齢(ラベルファンクション)" dataField="age" labelFunction="formatAge" /> <!-- ラベルファンクションを指定 -->
                        <mx:DataGridColumn headerText="年齢(Getter)" dataField="formattedAge" /> <!-- dataFieldに読み取り専用プロパティを指定 -->
                        <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                        <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                        <mx:DataGridColumn headerText="性別" dataField="gender" />
                        <mx:DataGridColumn headerText="性別マーク" dataField="genderMark" /> <!-- dataFieldに読み取り専用プロパティを指定 -->
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
        filedto.PersonMk2Dto.as
        package dto
        {
            /**
             * 個人情報用DTOクラス改。
             * (フォーマット用の読み取り専用プロパティも定義している)
             */
            [Bindable]
            public class PersonMk2Dto
            {
                //==========================================================
                //フィールド
                
                /**
                 * 姓
                 */
                public var lastName :String = null;
                
                /**
                 * 名
                 */
                public var firstName :String = null;
                
                /**
                 * 年齢
                 */
                public var age :int = 0;
                
                /**
                 * 電話番号
                 */
                public var tel :String = null;
                
                /**
                 * メールアドレス
                 */
                public var email :String = null;
                
                /**
                 * 性別
                 */
                public var gender :String = null;
                
                
                //==========================================================
                //メソッド
                
                //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
                //コンストラクタ
                
                /**
                 * コンストラクタです。
                 * 
                 * @param lastName 姓
                 * @param firstName 名
                 * @param age 年齢
                 * @param tel 電話番号
                 * @param email メールアドレス
                 * @param gender 性別
                 */
                public function PersonMk2Dto(lastName :String = null, firstName :String = null, age :int = 0, tel :String = null, email :String = null, gender :String = null)
                {
                    //引数の値をフィールドに設定
                    this.lastName = lastName;
                    this.firstName = firstName;
                    this.age = age;
                    this.tel = tel;
                    this.email = email;
                    this.gender = gender;
                }
        
                //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
                //Getter(読み取り専用プロパティ)
                
                /**
                 * フルネームを取得します。
                 * 
                 * @return フルネーム
                 */
                public function get fullName() :String
                {
                    //姓と名を半角スペースで結合して返す
                    return this.lastName + " " + this.firstName;
                }
        
                /**
                 * フォーマット済みの年齢を取得します。
                 * 
                 * @return フォーマット済みの年齢
                 */
                public function get formattedAge() :String
                {
                    //年齢の後ろに「才」をつけて返す
                    return this.age + "";
                }
        
                /**
                 * 性別のマークを取得します。
                 * 
                 * @return 性別のマーク
                 */
                public function get genderMark() :String
                {
                    //性別が男の場合
                    if(this.gender == "")
                    {
                        //男のマークを返す
                        return ""
                    }
                    //それ以外の場合
                    else
                    {
                        //女のマークを返す
                        return "";
                    }
                }
            }
        }
  3. レンダラー
    1. 既存のコントロールをレンダラーに指定
      • コントロールのitemRendererプロパティに表示したいコントロールのクラス名を、「mx.controls.Image」のようにパッケージも含めた完全クラス名で指定すると、文字列の代わりに指定したコントロールが表示される。
      • データグリッドの場合は、データグリッド本体ではなくDataGridColumn?のitemRendererプロパティに指定する。
         
      • サンプルプログラム - レンダラーにImageコントロールを指定  (実行画面はこちら)
        fileDataGridImageRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = 
                    [
                        {
                            name :"AX-2000-R",
                            color :"レッド",
                            image :"http://www.sharp.co.jp/products/kitchen/w_oven/prod01/ax2000r/images/ax2000r===04.jpg"
                        },
                        {
                            name :"AX-2000-B",
                            color :"ブラック",
                            image :"http://www.sharp.co.jp/products/kitchen/w_oven/prod01/ax2000b/images/ax2000b===04.jpg"
                        },
                        {
                            name :"AX-HC4-R",
                            color :"レッド",
                            image :"http://www.sharp.co.jp/products/kitchen/w_oven/prod01/axhc4r/images/axhc4r===04.jpg"
                        },
                        {
                            name :"AX-HC4-S",
                            color :"シルバー",
                            image :"http://www.sharp.co.jp/products/kitchen/w_oven/prod01/axhc4s/images/axhc4s===04.jpg"
                        },
                        {
                            name :"AX-HT4-C",
                            color :"ベージュ",
                            image :"http://www.sharp.co.jp/products/kitchen/w_oven/prod01/axht4c/images/axht4c===04.jpg"
                        },
                    ];
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <!-- (rowHeightを調整しておかないと1行分の情報しか表示されないので注意) -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%" height="100%" rowHeight="150">
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="形名" dataField="name" />
                        <mx:DataGridColumn headerText="" dataField="color" />
                        <mx:DataGridColumn headerText="画像" dataField="image" itemRenderer="mx.controls.Image" /> <!-- レンダラーにImageコントロールを指定 -->
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    2. インラインでレンダラーを記述
      • コントロールのitemRendererプロパティを記述する代わりに、下記の例のように<mx:itemRenderer>というタグを入れ子で記述すると、自由なコンポーネントを表示できる。
        (注)このとき、なぜか<mx:Component>というタグをワンクッション挟む必要があるので注意。
            <!-- リストの場合 -->
            <mx:List>
                <mx:itemRenderer>
                    <mx:Component>
                        <!-- この中に表示したい内容を記述する -->
                    </mx:Component>
                </mx:itemRenderer>
            </mxList>
        
            <!-- データグリッドの場合 -->
            <mx:DataGrid> 
                <mx:columns>
                    <mx:DataGridColumn>
                        <mx:itemRenderer>
                            <mx:Component>
                                <!-- この中に表示したい内容を記述する -->
                            </mx:Component>
                        </mx:itemRenderer>
                    </mx:DataGridColumn>
                </mx:columns>
            </mx:DataGrid>
      • 単純なコントロールだけでなく、コンテナも表示できるのでかなり自由度が高い。
      • レンダラーの中で現在処理対象となっているデータには「data」でアクセスできる。
         
      • サンプルプログラム - インラインでレンダラーを記述  (実行画面はこちら)
        fileDataGridInlineRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <!-- (rowHeightを調整しておかないと1行分の情報しか表示されないので注意) -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%" rowHeight="80"> 
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" />
                        <!-- インラインでレンダラーを記述 -->
                        <mx:DataGridColumn headerText="その他もろもろ">
                            <mx:itemRenderer>
                                <mx:Component>
                                    <mx:VBox>
                                        <mx:Label text="電話番号: {data.tel}" />
                                        <mx:Label text="メールアドレス: {data.email}" />
                                        <mx:CheckBox label="男性" selected="{data.gender == '男'}" />
                                    </mx:VBox>
                                </mx:Component>
                            </mx:itemRenderer>
                        </mx:DataGridColumn>
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    3. MXMLでレンダラークラスを作成
      • 独自にMXMLファイルで作成したクラスも、既存のコントロールと同じようにitemRendererプロパティにパッケージも含めた完全クラス名で指定することにより表示できる。
      • インラインで記述するレンダラーをそのまま独立したMXMLファイルに分離するような感じなので、記述する内容はインラインの場合とほとんど変わらない。
         
      • サンプルプログラム - MXMLで作成したレンダラーを指定  (実行画面はこちら)
        MXMLで作成したレンダラー - filerenderer.MXMLRenderer.mxml
        <?xml version="1.0"?>
        <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml">
            <mx:Label text="電話番号: {data.tel}" />
            <mx:Label text="メールアドレス: {data.email}" />
            <mx:CheckBox label="男性" selected="{data.gender == '男'}" />
        </mx:VBox>
        レンダラーを使用する側 - fileDataGridMXMLRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <!-- (rowHeightを調整しておかないと1行分の情報しか表示されないので注意) -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%" rowHeight="80"> 
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" />
                        <mx:DataGridColumn headerText="その他もろもろ" itemRenderer="renderer.MXMLRenderer" /> <!-- 自分で作成したレンダラーを指定 -->
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    4. ActionScript?でレンダラークラスを作成
      • ActionScript?でレンダラークラスを作成する場合は、MXMLで作成する場合とは異なり、コントロールに応じたレンダラークラスを継承したクラスを作成する必要がある。
        リスト → mx.controls.listClasses.ListItemRenderer
        データグリッド → mx.controls.dataGridClasses.DataGridItemRenderer
        ツリー → mx.controls.treeClasses.TreeItemRenderer
        etc...
      • 親のレンダラークラスの何らかのメソッドをオーバーライドして、独自の処理も追加で行うように記述することが多い。
        オーバーライドする候補のメソッドには、「set data」や「updateDisplayList?」などがある。
        (注)オーバーライドする場合は、必ずメソッドの最初に「super」で親の処理を呼び出すようにしておかないと、必要な処理が行われずに予期せぬ動作になることが多いので要注意。
      • ActionScript?でレンダラークラスを作成する場合は、条件に応じてスタイルを変更したりする用途に使用することが多い。
         
      • 【マニアックだが重要な知識】
        レンダラーのインスタンスは、メモリの効率化のために実際に表示されている範囲の分だけしか作成されない。
        そのため、スクロールすると以前に表示されていた部分のレンダラーのインスタンスが使い回されることになる。
        レンダラーでスタイルを変更する場合は、必ず条件に合わない場合に元のスタイルに戻す処理も併せて記述しておかないと、関係のないデータまでスタイルが変更されてしまうという予期せぬ動作になることが多いので要注意。
        この話はActionScript?で作成したレンダラークラスだけでなく、インラインのレンダラーやMXMLで作成したレンダラーの場合にも当てはまる。
        (本当かどうかを確かめたい場合は、スクロールバーが出るぐらいまでデータ量を増やして、レンダラーの中のスタイルを元に戻す部分の処理をコメントアウトして実行してみると良い。)
         
      • サンプルプログラム - ActionScript?で作成したレンダラーを指定  (実行画面はこちら)
        ActionScript?で作成したレンダラー - filerenderer.MyDataGridItemRenderer.as
        package renderer
        {
            import dto.PersonDto;
            
            import mx.controls.dataGridClasses.DataGridItemRenderer;
        
            /**
             * 自作したデータグリッド用のアイテムレンダラー。
             * 境界とする年齢を超えている場合、フォントを太字にして色を変えます。
             */
            public class MyDataGridItemRenderer extends DataGridItemRenderer
            {
                //==========================================================
                //フィールド
        
                /**
                 * 色
                 * (デフォルト値は赤)
                 */
                public var color :uint = 0xFF0000;
        
                /**
                 * 境界とする年齢
                 * (デフォルト値は30)
                 */
                public var borderAge :int = 30;
        
         
                //==========================================================
                //メソッド
        
                /**
                 * dataのSetterをオーバーライドします。
                 * 
                 * @param value 値
                 */
                override public function set data(value: Object) :void 
                {
                    //==========================================================
                    //親クラスの処理を先に呼び出す
                    //(これを忘れるとひどいことになるので注意)
                    super.data = value;
        
         
                    //==========================================================
                    //有効なデータかどうかチェック
                    
                    //データが存在しない場合
                    //(このチェックを入れておかないとNullPointerでエラーになることがある)
                    if(super.data == null)
                    {
                        //以降の処理を行わない
                        return;
                    }
                    
                    //データが想定している型と異なる場合
                    //(データグリッド全体にレンダラーを適用する場合はヘッダ行も対象となるので、このチェックによってヘッダ行を対象から除外する必要がある)
                    if(!(super.data is PersonDto))
                    {
                        //以降の処理を行わない
                        return;
                    }
                    
                    
                    //==========================================================
                    //データの内容に応じて処理を切り替える
        
                    //データを実際の型にキャスト
                    var person :PersonDto = super.data as PersonDto;
                    
                    //境界とする年齢を超えている場合
                    if(person.age > this.borderAge)
                    {
                        //太字で表示する
                        setStyle("fontWeight", 'bold');
                        
                        //色を変える
                        setStyle("color", this.color);
                    }
                    //それ以外の場合
                    //(こちらのスタイルを元に戻す処理は一見書かなくても良いように思えるが、忘れると意図せぬ挙動になってしまうので注意)
                    else
                    {
                        //フォントの太さを通常に戻す
                        setStyle("fontWeight", 'normal');
                        
                        //色を黒に戻す
                        setStyle("color", 0x000000);
                    }
                    
                }
            }
        }
        レンダラーを使用する側 - fileDataGridASRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%"> 
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" itemRenderer="renderer.MyDataGridItemRenderer" /> <!-- 自分で作成したレンダラーを指定 -->
                        <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                        <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                        <mx:DataGridColumn headerText="性別" dataField="gender" />
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    5. データグリッド全体にレンダラーを適用
      • データグリッドのカラムではなく、データグリッド本体にitemRendererを設定するとデータグリッドの全ての列に対してレンダラーを指定したのと同じ状態になる。
        ただし、副作用としてデータ行だけでなくヘッダ行も対象になってしまうので、レンダラーの中でヘッダ行を対象から除外する処理を記述しておく必要がある。
      • ヘッダ行だけにレンダラーを適用したい場合は、DataGridColumn?のheaderRendererプロパティにレンダラーを指定すると良い。
         
      • サンプルプログラム - データグリッド全体にレンダラーを適用  (実行画面はこちら)
        fileDataGridAllRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <!-- データグリッド全体に自分で作成したレンダラーを指定 -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%" itemRenderer="renderer.MyDataGridItemRenderer"> 
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" />
                        <mx:DataGridColumn headerText="電話番号" dataField="tel" />
                        <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                        <mx:DataGridColumn headerText="性別" dataField="gender" />
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>
    6. ClassFactory?をレンダラーに指定
      • レンダラーにはクラス名ではなく、mx.core.ClassFactory?クラスのインスタンスを指定することもできる。
      • スクリプトで記述する場合は、itemRendererプロパティの型がmx.core.IFactory(ClassFactory?のインターフェース)なので、この方法でしか設定できない。
      • タグでitemRendererプロパティにレンダラーのクラス名を指定した場合も、実際には裏でClassFactory?のインスタンスが生成されてそちらが指定されている。
      • ClassFactory?とは、指定されたクラスのインスタンスを生成するためのファクトリークラスである。
      • この方法の利点としては、ClassFactory?のpropertiesプロパティに初期化用オブジェクトを指定することにより、レンダラーのインスタンスを生成する際のプロパティを指定することができる。
        これを使えば、レンダラーによって変化させる色などのスタイルを変更したり、レンダラー適用の条件を変更したりすることもできるので、レンダラーの応用範囲がさらに広がる。
         
      • サンプルプログラム - ClassFactory?をレンダラーに指定  (実行画面はこちら)
        fileDataGridClassFactoryRendererSample.mxml
        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
            creationComplete="onCreationComplete()"
            >
            <mx:Script>
                <![CDATA[
                    import renderer.MyDataGridItemRenderer;
                    import mx.collections.ArrayCollection;
                    import dto.PersonDto;
                    
                    //==========================================================
                    //フィールド
                    
                    /**
                     * 対象データの配列
                     */
                    [Bindable]
                    private var dataArray :Array = new Array();
                    
                    /**
                     * 対象データのArrayCollection
                     */
                    [Bindable]
                    private var dataArrayCollection :ArrayCollection = new ArrayCollection();
                    
                    /**
                     * レンダラー指定用のClassFactory
                     * (ここでインスタンスを生成すると、バインディングする場合にpropertiesの設定の前に表示されてしまうので注意)
                     */
                    [Bindable]
                    private var myDataGridItemRenderer :ClassFactory = null;
                    
                    
                    //==========================================================
                    //メソッド
                    
                    /**
                     * 初期化処理を行います。
                     */
                    private function onCreationComplete() :void
                    {
                        //==========================================================
                        //レンダラー指定用のClassFactoryの設定
        
                        //レンダラー指定用のClassFactoryのインスタンスを生成
                        //(このタイミングでインスタンスを生成すると、バインディングする場合もpropertiesの設定後の状態で表示されるので安心)
                        this.myDataGridItemRenderer = new ClassFactory(MyDataGridItemRenderer);
                        
                        //レンダラーのインスタンス生成時に設定するプロパティを設定
                        this.myDataGridItemRenderer.properties = 
                        {
                            color :0x0000FF, //色を青くする
                            borderAge: 20 //境界の年齢を20にする
                        };
        
                        //バインディングしない場合は、このようにスクリプトで直接データグリッドカラムにレンダラーを設定しても良い
                        this.telColumn.itemRenderer = this.myDataGridItemRenderer;
        
         
                        //==========================================================
                        //DTOベースのデータを配列に設定
                        this.dataArray.push(new PersonDto("山田", "太郎", 21, "000-111-222", "aaa@hoge.com", ""));
                        this.dataArray.push(new PersonDto("佐藤", "花子", 25, "111-222-333", "bbb@hoge.com", ""));
                        this.dataArray.push(new PersonDto("スミス", "ジョン", 41, "999-111-222", "ccc@hoge.com", ""));
                        this.dataArray.push(new PersonDto("斉藤", "次郎", 22, "555-111-222", "ddd@hoge.com", ""));
                        this.dataArray.push(new PersonDto("鈴木", "さくら", 15, "666-111-222", "eee@hoge.com", ""));
        
                        //ArrayCollectionに配列を関連づける
                        this.dataArrayCollection.source = this.dataArray;
                    }
        
                ]]>
            </mx:Script>
            
            <mx:VBox width="100%" height="100%">
                <!-- データグリッド -->
                <mx:DataGrid id="arrayCollectionDataGrid" dataProvider="{this.dataArrayCollection}" width="100%"> 
                    <!-- データグリッドの各カラム(列)の情報を指定 -->
                    <mx:columns>
                        <mx:DataGridColumn headerText="" dataField="lastName" />
                        <mx:DataGridColumn headerText="" dataField="firstName" />
                        <mx:DataGridColumn headerText="年齢" dataField="age" itemRenderer="{this.myDataGridItemRenderer}" /> <!-- レンダラーにClassFactoryのインスタンスを指定 -->
                        <mx:DataGridColumn id="telColumn" headerText="電話番号" dataField="tel" />
                        <mx:DataGridColumn headerText="メールアドレス" dataField="email" />
                        <mx:DataGridColumn headerText="性別" dataField="gender" />
                    </mx:columns>
                </mx:DataGrid>
            </mx:VBox>
        </mx:Application>

ViewStack?TabNavigator? (P305 ~ P307)

  1. ViewStack?
    • 1つの領域の中で、条件に応じて複数のコンテナを切り替えて表示することができるViewStack?(mx.containers.ViewStack?)コンテナというものが存在する。
    • 中身に直接入れられるのはコンテナだけなので、コントロールを直接入れるとおかしくなる。
    • ViewStack?の中にViewStack?を入れ子にすることもできる。
    • 初期状態では、一番最初に記述した中身のコンテナが表示対象となる。
    • ViewStack?自体に表示対象のコンテナを切り替える機能は備わっていないため、以下のいずれかの方法と組み合わせる必要がある。
      1. selectedIndexプロパティを変更する。
        スクリプトでViewStack?のselectedIndexプロパティに中身のコンテナのインデックスを指定すると、そのコンテナがアクティブになる。
        (注)インデックスは1からではなく、0から始まるので注意。
        (注)<mx:ViewStack?>タグの初期値でselectedIndexを指定してもうまく効かないので、初期化時に変更したい場合はcreationCompleteイベントで行う方が良い。
      2. selectedChildプロパティを変更する。
        スクリプトでViewStack?のselectedChildプロパティに中身のコンテナのインスタンスを指定すると、そのコンテナがアクティブになる。
        当然だが、ViewStack?の中身のコンテナ以外を指定するとエラーになる。
        (注)初期化時はまだ中身のコンテナのインスタンスがViewStack?に関連づけられていないため、<mx:ViewStack?>タグの初期値でselectedChildを指定すると実行時エラーになってしまうので要注意。
      3. LinkButtonBar?ToggleButtonBar?と関連づける。
        LinkButtonBar?ToggleButtonBar?のデータプロバイダにViewStack?のインスタンスを指定すると、それだけでViewStack?を切り替えるための仕組みを作ることができる。
        ボタンに表示される名称には、中身のコンテナのlabelプロパティの値が使用される。
        中身のコンテナにiconプロパティの値が指定されていると、ボタンに画像も表示される。
    • デフォルトの設定だと、中身のコンテナはアクティブになるまで初期化処理が行われない。
      最初から中身のコンテナの初期化処理を行いたい場合は、creationPolicyプロパティに「all」を指定する必要がある。
      (意図せぬバグを未然に防ぐためには、必ずcreationPolicyプロパティに「all」を指定しておくのが無難。)
      (参考URL: http://www.adobe.com/livedocs/flex/201_jp/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=layoutperformance_119_07.html )
    • resizeToContent?プロパティにtrueを指定すると、中身のコンテナのサイズに応じてViewStack?自体のサイズも変化するようになる。
      (resizeToContent?プロパティのデフォルト値はfalse)
       
    • サンプルプログラム - ViewStack?コンテナの使用例  (実行画面はこちら)
      fileViewStackSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:containers="containers.*">
          <mx:VBox width="100%" height="100%">
              <mx:HBox width="100%">
                  <mx:Label text="ViewStackと関連づけたLinkBar: " />
                  <mx:LinkBar dataProvider="{this.mainViewStack}" />
              </mx:HBox>
      
              <mx:HBox width="100%">
                  <mx:Label text="ViewStackと関連づけたToggleButtonBar: " />
                  <mx:ToggleButtonBar dataProvider="{this.mainViewStack}" />
              </mx:HBox>
              
              <mx:HBox width="100%">
                  <mx:Label text="ボタンでViewStackを切り替え: " />
                  <mx:Button label="selectedIndexを2に変更" click="this.mainViewStack.selectedIndex = 2" />
                  <mx:Button label="selectedChildをcontent2に変更" click="this.mainViewStack.selectedChild = this.content2" />
              </mx:HBox>
      
              <!-- ViewStack -->
              <!-- (creationPolicy="all"にしておかないと、アクティブになるまで中身のコンテナの初期化処理が行われないので注意) -->
              <mx:ViewStack id="mainViewStack" 
                  width="100%" height="100%" 
                  backgroundColor="#FFFFFF"
                  creationPolicy="all"
                  >
                  
                  <!-- 中身のコンテナとしてVBoxを指定 -->
                  <!-- (labelを指定しておかないと、LinkBarやToggleButtonBarに表示されないので注意) -->
                  <mx:VBox id="content1" width="100%" height="100%" label="中身その1">
                      <mx:Label text="中身その1の内容です" />
                      <mx:TextInput />
                  </mx:VBox>
              
                  <!-- 中身のコンテナとしてPanelを指定 -->
                  <!-- (labelとtitleは別物なので間違わないように注意) -->
                  <mx:Panel id="content2" width="100%" height="100%" label="中身その2" title="パネルです">
                      <mx:Label id="myLabel" text="中身その2の内容です" />
                      <mx:CheckBox label="チェックボックス" />
                  </mx:Panel>
                  
                  <!-- 自分で作ったコンテナを指定することもできる -->
                  <!-- (画面ごとにMXMLファイルを分けることが多いので、こちらの方が一般的) -->
                  <containers:MyContainer id="content3" width="100%" height="100%" label="自分で作ったコンテナ" />
              
                  <!-- ViewStackにはコンテナ以外は入れられないので、コントロールを直接入れるとおかしくなる -->
                  <!-- 
                      <mx:Label text="これはダメ" /> 
                  -->
                  
                  <!-- ViewStackを入れ子にすることもできる -->
                  <mx:ViewStack id="subViewStack" 
                      width="100%" height="100%" 
                      label="入れ子のViewStack"
                      creationPolicy="all"
                      >
                      
                      <mx:VBox width="100%" height="100%" label="入れ子のViewStackの中身その1">
                          <mx:Label text="入れ子のViewStackの中身その1の内容です" />
                          <mx:Button label="次のページ" click="this.subViewStack.selectedIndex = 1" />
                      </mx:VBox>
                      
                      <mx:VBox width="100%" height="100%" label="入れ子のViewStackの中身その2">
                          <mx:Label text="入れ子のViewStackの中身その2の内容です" />
                          <mx:Button label="前のページ" click="this.subViewStack.selectedIndex = 0" />
                      </mx:VBox>
                  </mx:ViewStack>
                  
              </mx:ViewStack>
          </mx:VBox>
      </mx:Application>
      ViewStack?の中身に入れられている自作のコンテナクラス - filecontainers.MyContainer.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
          creationComplete="onCreationComplete()"
          >
          <mx:Script>
              <![CDATA[
                  import mx.controls.Alert;
                  
                  //==========================================================
                  //メソッド
                  
                  /**
                   * 初期化処理を行います。
                   */
                  private function onCreationComplete() :void
                  {
                      //メッセージを表示
                      Alert.show("自分で作ったコンテナクラスが初期化されました");
                  }
              ]]>
          </mx:Script>
          
          <mx:Label text="自分で作ったコンテナクラス" />
          <mx:TextArea text="あいうえお" />
      </mx:VBox>
  2. TabNavigator?
    • ViewStack?にタブをつけて、自分自身に中身のコンテナの切り替え機能を備えたTabNavigator?(mx.containers.TabNavigator?)コンテナというものが存在する。
    • タブ部分をクリックするとビューが切り替わる。
    • タブに表示される名称には、中身のコンテナのlabelプロパティの値が使用される。
    • ViewStack?を継承しているので同じインターフェースで使用できる。
       
    • サンプルプログラム - TabNavigator?コンテナの使用例  (実行画面はこちら)
      fileTabNavigatorSample.mxml
      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:containers="containers.*">
          <mx:VBox width="100%" height="100%">
              <mx:HBox width="100%">
                  <mx:Label text="TabNavigatorと関連づけたLinkBar: " />
                  <mx:LinkBar dataProvider="{this.mainTabNavigator}" />
              </mx:HBox>
      
              <mx:HBox width="100%">
                  <mx:Label text="TabNavigatorと関連づけたToggleButtonBar: " />
                  <mx:ToggleButtonBar dataProvider="{this.mainTabNavigator}" />
              </mx:HBox>
              
              <mx:HBox width="100%">
                  <mx:Label text="ボタンでTabNavigatorを切り替え: " />
                  <mx:Button label="selectedIndexを2に変更" click="this.mainTabNavigator.selectedIndex = 2" />
                  <mx:Button label="selectedChildをcontent2に変更" click="this.mainTabNavigator.selectedChild = this.content2" />
              </mx:HBox>
      
              <!-- TabNavigator -->
              <!-- (creationPolicy="all"にしておかないと、アクティブになるまで中身のコンテナの初期化処理が行われないので注意) -->
              <mx:TabNavigator id="mainTabNavigator" 
                  width="100%" height="100%" 
                  backgroundColor="#FFFFFF"
                  creationPolicy="all"
                  >
                  
                  <!-- 中身のコンテナとしてVBoxを指定 -->
                  <!-- (labelを指定しておかないと、LinkBarやToggleButtonBarに表示されないので注意) -->
                  <mx:VBox id="content1" width="100%" height="100%" label="中身その1">
                      <mx:Label text="中身その1の内容です" />
                      <mx:TextInput />
                  </mx:VBox>
              
                  <!-- 中身のコンテナとしてPanelを指定 -->
                  <!-- (labelとtitleは別物なので間違わないように注意) -->
                  <mx:Panel id="content2" width="100%" height="100%" label="中身その2" title="パネルです">
                      <mx:Label id="myLabel" text="中身その2の内容です" />
                      <mx:CheckBox label="チェックボックス" />
                  </mx:Panel>
                  
                  <!-- 自分で作ったコンテナを指定することもできる -->
                  <!-- (画面ごとにMXMLファイルを分けることが多いので、こちらの方が一般的) -->
                  <containers:MyContainer id="content3" width="100%" height="100%" label="自分で作ったコンテナ" />
              
                  <!-- TabNavigatorにはコンテナ以外は入れられないので、コントロールを直接入れるとおかしくなる -->
                  <!-- 
                      <mx:Label text="これはダメ" /> 
                  -->
                  
                  <!-- TabNavigatorを入れ子にすることもできる -->
                  <mx:TabNavigator id="subTabNavigator" 
                      width="100%" height="100%" 
                      label="入れ子のTabNavigator"
                      creationPolicy="all"
                      >
                      
                      <mx:VBox width="100%" height="100%" label="入れ子のTabNavigatorの中身その1">
                          <mx:Label text="入れ子のTabNavigatorの中身その1の内容です" />
                          <mx:Button label="次のページ" click="this.subTabNavigator.selectedIndex = 1" />
                      </mx:VBox>
                      
                      <mx:VBox width="100%" height="100%" label="入れ子のTabNavigatorの中身その2">
                          <mx:Label text="入れ子のTabNavigatorの中身その2の内容です" />
                          <mx:Button label="前のページ" click="this.subTabNavigator.selectedIndex = 0" />
                      </mx:VBox>
                  </mx:TabNavigator>
                  
              </mx:TabNavigator>
          </mx:VBox>
      </