0

(编辑:我已经编辑了我的问题以使其更简单,如果某些答案脱离上下文,对不起)

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

替代文字

我正在尝试创建一个自定义组件,该组件正在接收来自服务器的 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>
4

2 回答 2

1

两件事情:

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

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

编辑

好吧,再次查看您的代码后,我可以看到问题......所以还有一些事情。

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

4)这是您的主要问题:您正在适当地使用getter / setter。如果你有一个 setter,你还应该实现一个 getter(除非你有一个只写字段)。更重要的是,您应该使用getter 来访问您的数据。在您的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时,请使用 GETTER。例如,将List组件的 dataProvider 更改为{xlist}. 并且该xListChanged方法应该使用 getter:xlist而不是直接访问 member _xlist

于 2010-08-19T01:54:40.943 回答
0

你为什么不这样做:

公共函数集 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 属性,则不需要侦听器。

于 2010-08-18T22:44:47.090 回答