フレックス:カスタムコンポーネントのCollectionEventをリッスンします

StackOverflow https://stackoverflow.com/questions/3517298

  •  29-09-2019
  •  | 
  •  

質問

(編集:私はそれをよりシンプルにするために私の質問を編集しました、いくつかの答えが文脈から外れている場合は申し訳ありません)

私は自分の質問のために削減されたテストケースを準備しました:

alt text

サーバーからのXMLデータが供給されているカスタムコンポーネントを作成しようとしています。私の問題は、CollectionEventリスナーが解雇されないため、ラベルが更新されないことです -

games.mxml (リスナーとのカスタムコンポーネント):

<mx:Script>
    <![CDATA[
        import mx.events.*;

        private var _xlist:XMLList;

        [Bindable]
        public function get xlist():XMLList {
            return _xlist;
        }

        public function set xlist(x:XMLList):void {
            _xlist = x;
            trace("set(" + x +")");
            list.dataProvider = x;
            list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, xlistChanged);                
        }

        private function gameLabel(item:Object):String {
            return "game: " + item.@label;
        }

        private function xlistChanged(event:CollectionEvent):void {
            trace("xlistChanged(" + event +")");
            all.text = "All games: " + _xlist.game.length();
            full.text = "Full games: " + _xlist.game.(user.length() == 3).length();
            vacant.text = "Vacant games: " + _xlist.game.(user.length() < 3).length();
        }
    ]]>
</mx:Script>

<mx:Label id="all" text="All games"/>
<mx:Label id="full" text="Full games"/>
<mx:Label id="vacant" text="Vacant games"/>

<mx:List id="list" labelFunction="gameLabel"/>

mytest.mxml (ボタンをクリックしてXMLを変更します):

        private function changeXML1():void {
            games = <games>
                        <game label="1">
                            <user/>
                            <user/>
                            <user/>
                        </game>
                        <game label="2">
                            <user/>
                            <user/>
                        </game>
                        <game label="3">
                            <user/>
                            <user/>
                            <user/>
                        </game>
                    </games>;                   
        }

        private function changeXML2():void {
            games = <games>
                        <game label="A">
                            <user/>
                            <user/>
                            <user/>
                        </game>
                        <game label="B">
                            <user/>
                            <user/>
                        </game>
                        <game label="C">
                        </game>
                    </games>;                   
        }
    ]]>
</mx:Script>

<mx:XML id="games">
    <games>
        <game label="X">
            <user/>
            <user/>
        </game>
        <game label="Y">
            <user/>
            <user/>
        </game>
    </games>
</mx:XML>

<mx:Button label="Change XML 1" click="changeXML1()"/>
<mx:Button label="Change XML 2" click="changeXML2()"/>
<my:Games xlist="{games.game}"/>

何が悪いのかアドバイスしてください。

よろしく、アレックス

アップデート: ClownBabyが提案したように編集されたgames.mxml-まだ機能していません(xlistchangedは呼び出されません):

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" 
         xmlns:my="*" creationComplete="onCreationComplete(event)">

    <mx:Script>
        <![CDATA[
            import mx.events.*;

            private var _xlist:XMLList;

            [Bindable]
            public function get xlist():XMLList {
                return _xlist;
            }

            public function set xlist(x:XMLList):void {
                _xlist = x;
                list.dataProvider = x;
                trace("\n set: " + x);
            }

            private function gameLabel(item:Object):String {
                return "game: " + item.@label;
            }

            private function onCreationComplete(event:FlexEvent):void {
                list.dataProvider.addEventListener(CollectionEvent.COLLECTION_CHANGE, xlistChanged);
            }

            private function xlistChanged(event:CollectionEvent):void {
                all.text = "All games: " + xlist.length();
                full.text = "Full games: " + xlist.(user.length() == 3).length();
                vacant.text = "Vacant games: " + xlist.(user.length() < 3).length();
            }
        ]]>
    </mx:Script>

    <mx:Label id="all" text="All games"/>
    <mx:Label id="full" text="Full games"/>
    <mx:Label id="vacant" text="Vacant games"/>

    <mx:List id="list" labelFunction="gameLabel"/>

</mx:VBox>
役に立ちましたか?

解決

2つのこと:

1)あなたのイベントが解雇されていない理由は、あなたが設定した後にリスナーを追加しているからです _xlist.

2)とにかくセッター内にイベントリスナーを追加しないでください。 Vboxコンポーネントの初期化またはCreationCompleteイベントに追加する必要があります。

編集

さて、あなたのコードをもう一度見た後、私は問題を見ることができます...それで、もう少しいくつかのことです。

3)なぜメソッドに名前を付けているのですか init, 、それが呼ばれるとき creationComplete?方法を適切に命名する習慣に陥る必要があります。たとえば、呼び出される方法 creationComplete 名前を付ける必要があります: onCreationComplete, 、 また handleCreationComplete そうすれば、あなたのコードが6か月先に何をしているのかを知るでしょう。

4)これがあなたの主な問題です:あなたは適切にゲッター /セッターを使用しています。セッターがある場合は、ゲッターも実装する必要があります(書き込みのみのフィールドがない限り)。さらに重要なことは、あなたがすべきです 使用する ゲッターはあなたのデータにアクセスします。あなたの中で xListChanged あなたが定義したセッターを使用していない方法、したがって、何も言われていません _xlist 実際に変更されました。そのため、コードを次のように変更する必要があります。

private var _xlist:XMLListCollection;

[Bindable]
public function get xlist():XMLListCollection { return this._xlist; }
public function set xlist(value:XMLListCollection):void
{
    this._xlist = value;
}

アクセスしたいときはいつでも _xlist, 、ゲッターを使用します。たとえば、あなたのデータプロバイダーを変更します List あるコンポーネント {xlist}. 。そしてその xListChanged メソッドはゲッターを使用する必要があります。 xlist メンバーに直接アクセスする代わりに _xlist.

他のヒント

これをしてみませんか:

パブリック関数セットxlist(x:xmllist):void {

   _xlist = new XMLListCollection(x);
   _all.label = 'All (' + _xlist.length + ')';

   var full:XMLList = _xlist.source.game.(user.length() == 3);
   _full.label = 'Full (' + full.length() + ')';

   var free:XMLList = _xlist.source.game.(user.length() < 3);
   _free.label = 'Free (' + free.length() + ')';

}

ローカル_xList変数を設定する唯一の方法がXLISTプロパティを設定することである場合、リスナーは必要ありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top