1

我目前正在尝试实现 ArrayCollection 对象的 2 路绑定。但是,COLLECTION_CHANGE 事件没有触发。

应用程序.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               xmlns:components="components.*"
               creationComplete="handleCreationComplete(event)">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            [Bindable]
            public var booths:ArrayCollection;              

            public function handleCreationComplete(event:Event):void
            {
                // ADD SOME BOOTHS
                booths = new ArrayCollection();
                booths.addItem( "item1" );
                booths.addItem( "item2" );
            }

        ]]>
    </fx:Script>

    <components:FloorplanGrid id="grid" width="400" height="300" booths="{booths}" />
</s:Application>

FloorplanGrid.as

package components
{       
    import mx.collections.ArrayCollection;
    import mx.events.CollectionEvent;

    import spark.components.Group;

    [Event(name="collectionChanged", type="events.CollectionEvent")]

    public class FloorplanGrid extends Group
    {
        [Bindable]
        public var booths:ArrayCollection = new ArrayCollection();

        public function FloorplanGrid()
        {
            booths.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothsChange);
            super();
        }

        private function handleBoothsChange(event:CollectionEvent):void
        {
            trace("HANDLE BOOTHS CHANGE");
            /* draw booths */
        }
    }
}

我正在尝试使用Booths变量实现双向绑定。但是,即使我在 App.mxml 的 Booths 变量中添加 2 个新项目,COLLECTION_CHANGE 事件也不会触发

4

3 回答 3

2

我认为问题不在于事件没有触发。相反,我认为正在发生的事情是您正在收听您在变量声明中设置的原始 ArrayCollection,而不是通过应用程序中的绑定传入的那个。

使用 getter/setter 对:

protectect var _booths:ArrayCollection;

[Bindable]
public function get booths():ArrayCollection {
     return _booths;
}

public function set booths(value:ArrayCollection):void {
    if (value != _booths) {
        if (_booths != null) {
            _booths.removeEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothChange);
        }
        _booths=value;
        if (_booths != null) {
            _booths.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothChange);
        }
        handleBoothChange(null);
    }
}

请注意,如果您手动处理集合更改,您可能不需要将此设置为可绑定。

如果您使用的是 FB 4.5,您可能需要考虑将其设置为模板——我使用这种类型的逻辑足够多,因此我有自己的模板。make getter/setter 对是可以的,但它没有检查从旧实例中删除侦听器并添加新的 onw。

于 2011-08-25T13:19:52.607 回答
1

我不知道从哪里开始...

绑定适用于 Flex 事件系统;因此,当绑定更新时,它不是即时/同步的。查看这些代码段:

        public function handleCreationComplete(event:Event):void
        {
            booths = new ArrayCollection();
            booths.addItem( "item1" );
            booths.addItem( "item2" );
        }

<components:FloorplanGrid id="grid" width="400" height="300" booths="{booths}" />

因此,您创建了亭 ArrayCollection 并向其中添加了两个项目。这是同步代码,因此这三个项目紧随其后。展位 ArrayCollection 绑定到 FloorplanGrid 上的展位属性。此更新将异步发生;所以会有延迟。

因此,在 FloorplanGrid 上的 bolts 属性包含新值之前,这些项目很可能已添加到 ArrayCollection。因此,集合更改事件永远不会从 FloorplanGrid 中触发。

此外,您正在 FloorplanGrid 的构造函数中为收集更改事件设置事件侦听器:

    public function FloorplanGrid()
    {
        booths.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothsChange);
        super();
    }

因此,您正在侦听组件内创建的“new ArrayCollection()”对象上的事件。当您更改 puts 属性时,您尚未将事件侦听器添加到新值;因此,您没有在播放的事件侦听器。

您可能希望将您的展位属性更改为获取/设置属性。像这样:

        private var _booths:ArrayCollection;  
        [Bindable]
        public function get booths():ArrayCollection{
            return _booths;
        }
        public function set booths(value:ArrayCollection):void{
           if(_booths){
           _booths.removeEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothsChange);
           }
           _booths = value;
           if(_booths){
            _booths.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleBoothsChange);
           }
        }

删除事件侦听器并重新添加将有助于防止应用程序中的内存泄漏。因为您的应用程序中不会有错误的侦听器阻止旧值被垃圾收集。

于 2011-08-25T13:21:25.243 回答
0

问题是你订阅collectionChange了这个集合的事件:

public var booths:ArrayCollection = new ArrayCollection();

但是之后:

<components:FloorplanGrid id="grid" width="400" height="300" booths="{booths}" />

您已经传递了其他未订阅事件的集合。

您可以将代码更改为以下内容:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               xmlns:components="components.*"
               creationComplete="handleCreationComplete(event)">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            public function handleCreationComplete(event:Event):void
            {
                // ADD SOME BOOTHS
                grid.booths.addItem( "item1" );
                grid.booths.addItem( "item2" );
            }

        ]]>
    </fx:Script>

    <components:FloorplanGrid id="grid" width="400" height="300" />
</s:Application>

或者在 a 侧创建带有订阅/取消订阅逻辑的 getter FloorplanGrid

于 2011-08-25T13:18:07.397 回答