当前位置: 动力学知识库 > 问答 > 编程问答 >

flex - 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.

网友答案:

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;
}
网友答案:

There are a few things. First off, if you have a value object that you want to be set, then I would generally do it in my set data code.

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

But that is relatively small beans compared to what I think the problem really is. The brackets means that the property is bound to that object/object chain. So we have to ask, what is the object bound to in this statement ?

"{p.active ? 'normal' : FontStyle.ITALIC}"

I'm not saying it shouldn't work, but we want to smoke out as many bugs as possible. So if I were you, my code would look like this.

[Bindable] public var fonstStyle:String;
[Bindable] public var color:int;
[Bindable] public var name:String;
private var _p:MyProduct;

override public function set data( value:OBject ):void
{
  super.data = value;
  _p = value as MyProduct;
  fonstStyle = _p.active ? 'normal' : FontStyle.ITALIC;
  color = _p.active ? Constants.BLACK : Constants.DISABLED_COLOR;
  name = _p.name;
}

I would also get rid of that 'creationComplete' event listener. When working with ItemRenderers, any setting of data-based properties should be done through the 'set data' function.

Now that I look at your code, your renderer is probably setting those variables after being created through the 'creationComplete', and then they aren't being updated.

分享给朋友:
您可能感兴趣的文章:
随机阅读: