フレックス:カスタムコンポーネントのCollectionEventをリッスンします
-
29-09-2019 - |
質問
(編集:私はそれをよりシンプルにするために私の質問を編集しました、いくつかの答えが文脈から外れている場合は申し訳ありません)
私は自分の質問のために削減されたテストケースを準備しました:
サーバーからの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プロパティを設定することである場合、リスナーは必要ありません。