AdvancedDataGrid のデータ階層による編集状態切り替え

フォルダの中にデータが入るような構造を作れるのが AdvancedDataGrid の利点ですが、そこからデータを更新させるような場合見た目的にもフォルダが表示された列は入力を受け付けたくないものです。ところがこれがなかなかくせ者で困ったので、その辺をまとめ。

まず目を付けたのは itemClick イベントを用いる方法。

<mx:AdvancedDataGrid
  id="sampleDG"
  itemClick="checkEditable()"
  />
  <columns>
    <mx:AdvancedDataGridColumn
      id="column1"
      editable="false"
      />
  </columns>
</mx:AdvancedDataGrid>

こんな感じで itemClick イベントをセットして

private function checkEditable():void {
  var item:Object = sampleDG.selectedItem;
  if(item) {
    // 子ノードが存在する場合 children プロパティを持つ
    column1.editable = item.children ? false : true;
  }
}

これでいけるか、と思ったのですが、どうやら selectedItem プロパティの更新タイミングは内部的にはクリック終了後らしく、これだと直前に選択していたアイテムを参照してしまいます。

次に試したのは itemFocusIn イベント。先ほどのメソッドを少し書き換えて実装します。

private function checkEditable(e:AdvancedDataGridEvent):void {
  var item:Object = e.item;
  if(item) {
    // 子ノードが存在する場合 children プロパティを持つ
    column1.editable = item.children ? false : true;
  }
}

これなら確実にフォーカスされたアイテムを取得できるはず、と思いきや editable が false の場合そもそもイベントが発生しない事が発覚。

次にクリックした位置のインデックスから直接アイテムを指定しようと思ったのですが AdvancedDataGrid にはインデックスからアイテムを返すメソッドが存在しない様子。

仕方ないので最後に試したのがこれ。

<mx:AdvancedDataGrid
  id="sampleDG"
  enterFrame="checkEditable()"
  />
  <columns>
    <mx:AdvancedDataGridColumn
      id="column1"
      editable="false"
      />
  </columns>
</mx:AdvancedDataGrid>

きた!enterFrame きた!これで勝つる!

private function checkEditable():void {
  var item:Object = sampleDG.selectedItem;
  if(item) {
    // 子ノードが存在する場合 children プロパティを持つ
    column1.editable = item.children ? false : true;
  }
}

ひどい事に、これはきちんと動作してしまいます。フレーム毎に処理を行うため、圧倒的な効率の悪さを誇るのも問題。そして、これでもエンターキーで移動してしまうと入力制限がかかりません。

これを読んだあなた。真相を暴いてください。それだけが私の望みです。