1

現在、ArrayCollection オブジェクトの双方向バインディングを実現しようとしています。ただし、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をリッスンしていると思います。

ゲッター/セッターのペアを使用します。

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 を作成し、それに 2 つの項目を追加します。これは同期コードであるため、これら 3 つの項目が次々に発生します。ブース ArrayCollection は、FloorplanGrid のブース プロパティにバインドされています。この更新は非同期で行われます。そのため遅延が発生します。

そのため、FloorplanGrid のブース プロパティに新しい値が含まれる前に、項目が ArrayCollection に追加される可能性があります。そのため、FloorplanGrid 内からコレクション変更イベントが発生することはありません。

さらに、FloorplanGrid のコンストラクター内で collect change イベントのイベント リスナーを設定しています。

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

そのため、コンポーネント内で作成された「new ArrayCollection()」オブジェクトのイベントをリッスンしています。ブース プロパティを変更すると、新しい値にイベント リスナーが追加されません。そのため、イベントリスナーはありません。

おそらく、ブース プロパティを 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);
           }
        }

イベント リスナーを削除して再度追加すると、アプリケーションでのメモリ リークを防ぐのに役立ちます。アプリに誤ったリスナーがなく、古い値がガベージ コレクションされるのを防ぐためです。

于 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>

または、 の側で購読/購読解除ロジックを使用して getter を作成しますFloorplanGrid

于 2011-08-25T13:18:07.397 に答える