Apache flex Flex:侦听自定义组件中的CollectionEvent

Apache flex Flex:侦听自定义组件中的CollectionEvent,apache-flex,e4x,xmllist,Apache Flex,E4x,Xmllist,(编辑:我对我的问题进行了编辑,使之更简单, 抱歉,如果某些答案不符合上下文) 我已经为我的问题准备了一个简化的测试用例: 我正在尝试创建一个自定义组件 正在接收来自服务器的XML数据。 我的问题是CollectionEvent侦听器 不会被解雇,因此标签不会更新- Games.mxml(我的带有侦听器的自定义组件): MyTest.mxml(单击按钮更改XML): 私有函数changeXML1():void{ 游戏= ; } 私有函数chan

(编辑:我对我的问题进行了编辑,使之更简单, 抱歉,如果某些答案不符合上下文)

我已经为我的问题准备了一个简化的测试用例:

我正在尝试创建一个自定义组件 正在接收来自服务器的XML数据。 我的问题是CollectionEvent侦听器 不会被解雇,因此标签不会更新-

Games.mxml(我的带有侦听器的自定义组件):


MyTest.mxml(单击按钮更改XML):

私有函数changeXML1():void{
游戏=
;                   
}
私有函数changeXML2():void{
游戏=
;                   
}
]]>

请告诉我怎么了

问候,, 亚历克斯

更新:按照小丑宝贝的建议编辑了Games.mxml-仍然不工作(永远不会调用xlistChanged):


为什么不这样做:

公共函数集xlist(x:XMLList):无效{

\u xlist=新的XMLListCollection(x);
_all.label='all(+uxlist.length+');
var full:XMLList=\u xlist.source.game.(user.length()==3);
_full.label='full('+full.length()+');
无变量:XMLList=xlist.source.game.(user.length()<3);
_free.label='free('+free.length()+');
}

如果设置本地xlist变量的唯一方法是设置xlist属性,则不需要侦听器。

两件事:

1) 事件未触发的原因是您在设置
\u xlist
后添加了侦听器

2) 无论如何,您都不应该在setter中添加事件侦听器。您应该将其添加到VBox组件的initialize或creationComplete事件中

编辑

好的,在再次查看您的代码后,我可以看到问题。。。还有几件事

3) 在
creationComplete
上调用方法时,为什么要命名方法
init
?您应该养成适当命名方法的习惯。例如,在
creationComplete
上调用的方法应命名为:
onCreationComplete
,或
handleCreationComplete
,这样,您将知道6个月后代码在做什么

4) 这是您的主要问题:您正在适当地使用getter/setter。如果您有一个setter,那么还应该实现一个getter(除非您有一个只写字段)。更重要的是,您应该使用getter来访问数据。在您的
xListChanged
方法中,您没有使用您定义的setter,因此没有人告诉您
\xlist
实际发生了变化。因此,您应该将代码更改为:

private var _xlist:XMLListCollection;

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

无论何时要访问
\u xlist
,请使用GETTER。例如,将
列表
组件的数据提供程序更改为
{xlist}
。而且
xListChanged
方法应该使用getter:
xlist
而不是直接访问成员
\u xlist

你好,John,如果我在setter方法中设置了_full.label和_free.label,那么它们将永远不会再次得到更新,它们将在每次设置游戏组件的xlist属性时得到更新。这是更改私有xlist变量的唯一方法。我已经移动了xlist.addEventListener(CollectionEvent.COLLECTION_change,xlistChanged);我在VBox的creationComplete=“init(event)”上调用了init(event:FlexEvent)方法,但这并没有解决这两个问题。那么这么早调用addEventListener有意义吗?而setter方法没有设置xlist?谢谢,但我不能像你建议的那样使用GETTER/setter,因为它是XMLListCollection,自定义组件得到一个XMLList作为参数:我用测试代码更新了我的问题,我正在尝试使用list.dataProvider.addEventListener()在那里。。。但仍然没有运气。如果我编辑的答案不够清楚,我道歉。。。但是你仍然没有听我说的话,那就是停止在你的代码中使用
\u xlist
,除非你是一个getter/setter。更新
xlistChanged
方法以使用
xlist
。看在上帝的份上,请不要在SETTER中添加事件侦听器。每次设置_xlist时,都会重新添加事件侦听器。这真的有必要吗?谢谢,我已经试过你的建议了-它仍然不起作用。请尝试MyTest.mxml和更新后的Games.mxml,您将看到它。好的,给您带来好消息。我今天早上设置了您的测试用例,并使其正常工作。如果您只需将
CollectionEvent.COLLECTION\u CHANGE
事件侦听器添加到
List
组件(而不是List.dataProvider),它将按预期启动。因此,在
onCreationComplete()
do中,
list.addEventListener(CollectionEvent.COLLECTION\u CHANGE,xlistchange)干杯。
        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}"/>
<?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>
   _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() + ')';
private var _xlist:XMLListCollection;

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