Search code examples
apache-flexflex4behavioritemrenderer

Spark ItemRenderer "shorthand" causing strange behaviour


I have a simple ItemRenderer that is causing strange behaviour when I use it in a Spark List of products. It is defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
  xmlns:s="library://ns.adobe.com/flex/spark" 
  xmlns:mx="library://ns.adobe.com/flex/mx"
  creationComplete="setProduct()">

  <fx:Script>
    <![CDATA[

      [Bindable]
      private var p:MyProduct;

      private function setProduct():void
      {
        p = data as MyProduct;
      }

    ]]>
  </fx:Script>

  <s:Label text="{p.name}" paddingTop="6" paddingBottom="4"
    color="{p.active ? Constants.BLACK : Constants.DISABLED_COLOR}"
    fontStyle="{p.active ? 'normal' : FontStyle.ITALIC}"/>

</s:ItemRenderer>

It's basically the same as the default ItemRenderer for a List. I decided to use the variable p so that I wouldn't have to write (data as MyProduct) over-and-over within the Label bindings (this is especially cumbersome in larger, more complex ItemRenderers).

The behaviour it causes seems to "reverse" the items that get displayed, but the actual order of the items remains the same. This happens when a product gets updated with new values. For example, I'll have a list of products A B C D. If I update the properties of any one of them, the List will change the order to show D C B A. But if I click on product D in this reversed list, it will still "load" product A. This post describes a similar problem, but there is no code included, so I'm not sure if it's exactly the same issue.

I tracked this bug down to using the variable p. If I just use (data as MyProduct) within the Label bindings, it works fine. If I take the example from the above link and run the setProduct() method on the dataChange event, the bug goes away and works as expected. However, I'm not convinced that this isn't just coincidental.

Has anyone else experienced something like this? Is the problem directly related to using the creationComplete event? I was thinking that maybe creationComplete was only firing once and throwing everything out of whack. Not sure what any of this has to do with the List reversing the displayed products though.


Solution

  • This is probably due to item renderers being recycled. I would override the data setter instead of using creationComplete, that way you'll be sure you catch changes to data.

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