Question

I don't understand why when we change data on dataprovider, all the itemRenderers of the impacted column are called ? Here is a little example of my problem :

application :

    <?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" minWidth="955" minHeight="600" creationComplete="application1_creationCompleteHandler(event)">

<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.events.FlexEvent;

        private var _ac:ArrayCollection = new ArrayCollection();

        protected function application1_creationCompleteHandler(event:FlexEvent):void
        {
            var i:int = 10;

            while(i >= 0)
            {
                _ac.addItem({fieldA:Math.random() * 100, fieldB:Math.random() * 100});
                i--;
            }

            dg.dataProvider = _ac;
            dg.requestedRowCount = _ac.length;
        }

        protected function button1_clickHandler(event:MouseEvent):void
        {
            _ac.getItemAt(0)["fieldA"] = Math.random() * 100;
            _ac.getItemAt(0)["fieldB"] = Math.random() * 100;
            _ac.refresh();
        }

    ]]>
</fx:Script>

<s:layout>
    <s:VerticalLayout />
</s:layout>

<s:Button label="change data" click="button1_clickHandler(event)" />

<s:DataGrid id="dg">
    <s:columns>
        <s:ArrayList>
            <s:GridColumn dataField="fieldA" itemRenderer="MyItemRenderer" />
            <s:GridColumn dataField="fieldB" />


    </s:ArrayList>
        </s:columns>
    </s:DataGrid>

</s:Application>

myItemRenderer :

 <?xml version="1.0" encoding="utf-8"?>
<s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                    xmlns:s="library://ns.adobe.com/flex/spark" 
                    xmlns:mx="library://ns.adobe.com/flex/mx" clipAndEnableScrolling="true">

    <fx:Declarations>
        <s:Sequence id="myAnimation" duration="2000" target="{col}" >
            <s:Fade alphaFrom="0.0" alphaTo="1.0"/>
            <s:Fade alphaFrom="1.0" alphaTo="0.0"/>
        </s:Sequence>                   
    </fx:Declarations>

    <fx:Script>
        <![CDATA[

            private var _data:Object;

            override public function set data(value:Object):void
            {
                super.data = value;

                _data = value;

                if(null != _data)
                {
                    display();
                }
            }

            private function display():void
            {
                lblData.text = _data[column.dataField];
                myAnimation.play();
            }

        ]]>
    </fx:Script>

    <s:Rect top="-2" left="0" right="0" bottom="-2">
        <s:fill>
            <s:SolidColor id="col" color="0xFF0000" />
        </s:fill>
    </s:Rect>

    <s:Label id="lblData" top="9" left="7"/>

</s:GridItemRenderer>

I just want to play animation on the impacted cell but each time, animation on each cell is fired. How can I code that please ?

Was it helpful?

Solution

The reason for all that recycling is this: you're calling the refresh method, hence you're explicitly asking for all this recycling. It will invalidate all the sorts and filters applied to your collection, hence all the positions of the items in the datagrid are invalidated and every item is recycled.

So you should remove this call. After that something like this should then do what you expect:

    private var colValue:String;

    override public function prepare(hasBeenRecycled:Boolean):void {
        if (data && colValue != data[column.dataField]) {
            colValue = data[column.dataField];
            lblData.text = colValue;
            myAnimation.play();
        }
    }

The prepare method will still be called every time, but your animation will only be played when the value has actually changed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top