クリックイベンドでListに入ったCheckBoxの値を変更する


ListをクリックしたタイミングでCheckBoxの値を変更するやり方。動作のイメージは上のような感じ。

まず、Listの各項目に対してCheckBoxを表示させるにはitemRendererを使います。itemRendererを使えば好きなレイアウトを行う事ができます。mx:Componentタグでレンダラを定義して、それをListのプロパティに設定します。これでひとまずCheckBoxをリストの中に表示する事ができます。

<mx:Panel width="100%" height="100%">
        <mx:List id="commentList" itemRenderer="{userRenderer}" height="100%" width="100%" click="select(event)" dataProvider="{users}"/>
        <mx:Button label="選択ユーザ確認" click="show();"/>
</mx:Panel>

<mx:Component id="userRenderer">
        <mx:HBox>
                <mx:CheckBox selected="{data.selected}"/>
                <mx:Label text="{data.name}"/>
        </mx:HBox>
</mx:Component>

次に、リストの項目をクリックしたときにクリックされた部分のチェックボックスに対応するデータプロバイダの値がとれれば良いのですが、直接取る事はできません。クリックしたItemの選択されたIndexを取得し、そのキーをもとにArrayCollectionからデータを取得します。また、dataProviderの値を変えただけでは反映されないので、itemUpdatedメソッドを使用して、値が更新された事を通知します。実はこのitemUpdatedがミソでこれをしらずにしばらくはまってしまいました。

private function select(event:MouseEvent):void {
    var selectedIndex:int = event.currentTarget.selectedIndex;
    var item:Object = users.getItemAt(selectedIndex);

    item.selected = !item.selected;
    users.setItemAt(item, selectedIndex);
    users.itemUpdated(item);
}

何故か、mx:Textを使ったときに文字列をクリックするとうまく選択できなかったんですが、なぜなんでしょう、、、ただのコーディングミスでした。
全てのソースは下に載せておきます。

<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
        <mx:Script>
        <![CDATA[
                import mx.collections.ArrayCollection;
                import mx.controls.Alert;

                private function select(event:MouseEvent):void {
                        var selectedIndex:int = event.currentTarget.selectedIndex;
                        var item:Object = users.getItemAt(selectedIndex);

                        item.selected = !item.selected;
                        users.setItemAt(item, selectedIndex);
                        users.itemUpdated(item);
                }

                private function show():void {
                        var ar:Array = users.toArray();
                        var filterd:Array = ar.filter(function(e:*):* {
                                return !!e.selected;
                        });
                        Alert.show(filterd.map(function(e:*):*{ return e.name }).join());
                }
        ]]>
        </mx:Script>

    <mx:ArrayCollection id="users">
                <mx:Object name="田中" selected="true"/>
                <mx:Object name="山田"/>
                <mx:Object name="斉藤"/>
                <mx:Object name="本田" selected="true"/>
                <mx:Object name="宮本"/>
                <mx:Object name="西条"/>
                <mx:Object name="榎本"/>
        </mx:ArrayCollection>
        <mx:Panel width="100%" height="100%">
                <mx:List id="commentList" itemRenderer="{userRenderer}" height="100%" width="100%" click="select(event)" dataProvider="{users}"/>
                <mx:Button label="選択ユーザ確認" click="show();"/>
        </mx:Panel>

        <mx:Component id="userRenderer">
                <mx:HBox>
                        <mx:CheckBox selected="{data.selected}"/>
                        <mx:Label text="{data.name}"/>
                </mx:HBox>
        </mx:Component>
</mx:Application>

追記
ListにはitemClickイベントというものがあるんですね。これを使うのが正しそうです。