【问题标题】:Flex 4 COLLECTION_CHANGE event not firingFlex 4 COLLECTION_CHANGE 事件未触发
【发布时间】:2011-08-25 13:08:16
【问题描述】:

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

App.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 事件也不会触发

【问题讨论】:

    标签: apache-flex actionscript binding 2-way-object-databinding


    【解决方案1】:

    我认为问题不在于事件没有触发。相反,我认为正在发生的事情是您正在收听您在变量声明中设置的原始 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。

    【讨论】:

      【解决方案2】:

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

      绑定适用于 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 属性时,您尚未将事件侦听器添加到新值;因此,您没有在播放的事件侦听器。

      您可能希望将您的 bolts 属性更改为 get/set 属性。像这样:

              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);
                 }
              }
      

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

      【讨论】:

        【解决方案3】:

        问题是你订阅了这个集合的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>
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-01
          • 1970-01-01
          • 2018-04-13
          • 1970-01-01
          相关资源
          最近更新 更多