1

I have an item renderer in a list, when I try to use the override method to setup the list items how I want them they are invisible.

When I try to use the function to set them up, every time I scroll the list consuming the renderer, it starts giving serious redraw problems.

When I combine both methods the Labels redraw correctly but the images ghost them selves up and down as I scroll.

Here is the code:

http://pastebin.com/FkjRBT3G

Please and thank you to any help you can give.

Edit most recent code

    <?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="setupControls();"  autoDrawBackground="true" contentBackgroundAlpha="1.0" contentBackgroundColor="#000000">

    <fx:Script>
        <![CDATA[
            import flash.display.*;
            import flash.ui.ContextMenu;
            import flash.ui.ContextMenuBuiltInItems;
            import flash.ui.ContextMenuItem;

            import mx.controls.Alert;
            import mx.core.FlexGlobals;

        /*  override public function set data(value:Object):void{
                if(value != null)  {
                    super.data = value;
                    theLabel.text = value.UserName;
                    if (value.IsGroup == true){
                        imgGroup.visible=true;
                        theLabel.x = 24;
                        theLabel.setStyle("fontWeight", "bold")
                    }

                    if (value.IsGroup  == false){
                        imgUser.visible=true;
                        theLabel.x = 34;
                    }
                }
            }  */

        private function setupControls():void{
                    theLabel.text = data.UserName;
                    theLabel.y = 4;
                    if (data.IsGroup == 'true'){
                        imgGroup.visible=true;
                        theLabel.x = 24;
                        theLabel.setStyle("fontWeight", "bold")
                    }

                    if (data.IsGroup  == 'false'){
                        imgUser.visible=true;
                        theLabel.x = 34;
                    }

                    var availableFieldMenu:ContextMenu = new ContextMenu();
                    var chartSubTypeFieldMenu:ContextMenuItem = new ContextMenuItem("Add, Edit, Delete",false,true,true);
                    availableFieldMenu.customItems.push(chartSubTypeFieldMenu);
                    chartSubTypeFieldMenu.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, menuItemHandler);
                    availableFieldMenu.hideBuiltInItems();
                    this.contextMenu = availableFieldMenu;
                }   


        public function menuItemHandler(event:ContextMenuEvent) : void{
            if (event.currentTarget.caption=="Add, Edit, Delete"){
                Alert.show('Right Click Just Happened!');
            }
        }




        ]]>
    </fx:Script>


    <s:Label y="4" id="theLabel" color="#000000"/><mx:Image id="imgGroup" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  width="16" height="16" x="3" visible="false" buttonMode="true"/><mx:Image id="imgUser" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" width="16" height="16" x="13" visible="false"/>

</s:ItemRenderer>

Regards Craig

zero323
  • 322,348
  • 103
  • 959
  • 935
Craig Mc
  • 505
  • 1
  • 13
  • 30
  • Can you post just the list / item renderer code here? – Jason Towne Jul 07 '11 at 15:14
  • Hi Jason: This is the most recent version it gives the least buggy redraw, there are about 3 different ways it breaks depending entirely on if they list needs to be scrolled, and depending if I use override or creation complete. Override for example fails to draw the label controls. creation complete has ghosting redraw of the images if virtual layout is enabled. – Craig Mc Jul 14 '11 at 07:48
  • Autodraw background has always had an influence when using the overide method. But in conjuction with a specified background it started to work a little better with creationComplete. I need to stress, that the issue is inconsistent rendering behaviour. Either one of the methods should have in theory worked, but simply didn't work consistently. Dragging a value in and then refreshing the data provider also can bork the list, but only some times, even when testing the same drag again and again. – Craig Mc Jul 14 '11 at 07:52
  • I'm having the same issue in Apache SDK 4.9.0, Spark List, Custom List Skin, Item Renderer & Custom VScrollBar. I have no idea if there's a bug reference for it, so please help me with a link if you got it. The only convenient solution I found so far is executing these next lines of code while scrolling: var _itemRenderer:IFactory = itemRenderer; itemRenderer = null; itemRenderer = _itemRenderer ; What it does is simply making the list to redraw all of its items. The downside of this workaround is that it's effecting the smooth scrolling experience by having too much refreshes while scrolling. –  Mar 31 '13 at 16:52

5 Answers5

1

I fixed it by turning off use virtual layout, the context menus work well actually ;)

The list it self is bound to an xml list using a {}

Craig Mc
  • 505
  • 1
  • 13
  • 30
  • Turning off virtual layout *is not* a fix. It's a workaround, and a bad one at that. – J_A_X Jul 11 '11 at 13:31
  • Ok so what do recommend for a an item that does not render consistently. Baring in mind I tried your code and it also rendered incorrectly. Most of the code has been done around fixing what appears to be a stupid glitch in the rendering. Example it works, unless you scroll. in other scenarios, if you drag into the list it miss draws and shows both images for no reason. I should mention I'm using flex builder 4 not flex builder 4.5, 4.5 does not exhibit this behaviour at all. I do agree none of it is ideal, but there is no reason for it to redraw incorrectly in the first place. – Craig Mc Jul 14 '11 at 07:38
  • The key thing to mention here is, most times the redraw is fine. well maybe 55% of the time. Even when its asked to do the same task twice it will sometimes draw the list right other times not. – Craig Mc Jul 14 '11 at 07:39
  • I also agree that all the code used was various attempts at taking an irrational bug and just patching the code to make it work, and noticing that each of the approaches yielding different rendering glitches. I just want something that works. – Craig Mc Jul 14 '11 at 07:41
  • The data provider for the list control is set to {new XMLListCollection(XMLList(GetAssignedUsersPerRuleCondition.lastResult).UserDetail)} When ever a change is made I simply call GetAssignedUsersPerRuleCondition.send(); – Craig Mc Jul 14 '11 at 07:42
0

I had the same issue and fixed it the following way:

Decomposed my data to properties and passed property by property to the renderer, so the overridden data function removed, used setters for each data property (decomposed(extracted) from the data).

SchmitzIT
  • 9,227
  • 9
  • 65
  • 92
0

Question is pretty old, but it seems that the issue still persists in Flex 4.13. I'm struggling with the same issue and I do override the data setter. 2 methods that I use to work around this issue:

  1. use mx:Label instead of Spark's Label
  2. remove the virtual layout in case the list is known to be very small and mostly visible

Also, I did notice that this issue occurs in Spark's DataGrid as well as in List

Ofir
  • 1,565
  • 3
  • 23
  • 41
0

You can't use a context menu in an item renderer.

Why are you creating all these things on creation complete if it isn't needed right away? Don't use creation complete event, there are new functions for that kind of stuff (for better recycling) like 'prepare'. From what I can see, your whole creation complete function isn't needed.

Bindable is not needed on the data set function.

Here's the cleaned up, untested version:

<?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">

    <fx:Script>
        <![CDATA[
            import flash.display.*;
            import flash.ui.ContextMenu;
            import flash.ui.ContextMenuBuiltInItems;
            import flash.ui.ContextMenuItem;

            import mx.controls.Alert;
            import mx.core.FlexGlobals;

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

                if (value.IsGroup)
                {
                    currentState = 'group';
                }else{
                    currentState = 'user';
                }
            }  

            private function onMenu():void
            {
                // TODO: add code to add the menu.  
                // Can't use right click to do this as right click is only for 
                // context menu on top level component. should create 'menu' button
            }  
        ]]>
    </fx:Script>
    <s:layout>
        <s:VerticalLayout gap="0" />
    </s:layout>
    <s:states>
        <s:State name="group" />
        <s:State name="user" />
    </s:states>
    <mx:Image width="16" height="16" buttonMode="true" includeIn="group"
        source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  />
    <mx:Image width="16" height="16" includeIn="user"
        source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" />
    <s:Label id="label" color="#000000" fontWeight.group="bold"/>
</s:ItemRenderer>

You should also post how the data provider/list is created and updated because I'm sure there's other issues.

J_A_X
  • 12,857
  • 1
  • 25
  • 31
  • I originally used the overrride of set, but that gave a rendering issue if background was not redrawn. Then I tried the on creation complete, that gave a different ghost, I then combined them which gave a better but still messy redraw. Turning off virtual layout solved the problem. I do agree either one or the other would have worked, I tried an over kill approach out of frustration. – Craig Mc Jul 09 '11 at 13:47
  • Interesting approach using states, its nice to see a totally different take on the same code ;) Thanks for that :) – Craig Mc Jul 09 '11 at 13:49
  • Just an update, Flex 4 and flex 4.5 have a bug where by the renderer will be kicked to the normal state. I used a series of over rides to solve this. – Craig Mc Sep 27 '11 at 12:21
0

setupControls is probably redundant now and useVirtualLayout can be true in this instance:

<?xml version="1.0" encoding="utf-8"?>

<fx:Script>
    <![CDATA[
        import flash.display.*;
        import flash.ui.ContextMenu;
        import flash.ui.ContextMenuBuiltInItems;
        import flash.ui.ContextMenuItem;

        import mx.controls.Alert;
        import mx.core.FlexGlobals;

        [Bindable] public var TheState:String=''; 

        override public function set data(value:Object):void{

            if(value != null)  {
                super.data = value;
                if (value.IsGroup == true){
                    TheState = 'group';
                    currentState = 'group';
                    //theLabel.x = 24;
                    //theLabel.setStyle("fontWeight", "bold")
                }

                if (value.IsGroup  == false){
                    TheState  = 'user';
                    currentState = 'user';
                    //theLabel.x = 34;
                }
            }
            //super.invalidateDisplayList();
        }  

        private function setupControls():void{  
            if (String(data.IsGroup)=='true'){

                TheState='group';
            }else {
                TheState='user';
            }
            //Alert.show('' + TheState);
            if (TheState  == 'group'){
                currentState = 'group';
            }

            if (TheState == 'user'){
                currentState = 'user';              
            }   
        }   

        override public function set currentState(value:String):void
        {
            super.currentState = value;

            //if (value != 'normal' && value != 'hovered' && value != 'selected')
            //{
                this.TheState = TheState;
            //}
        }

        override protected function getCurrentRendererState():String
        {
            var state:String = super.getCurrentRendererState();

            state = TheState;
            return state;
        }


    ]]>
</fx:Script>
<s:states>
    <s:State name="default" basedOn="{TheState}" />
    <s:State name="normal" basedOn="{TheState}" />
    <s:State name="hovered" basedOn="{TheState}" />
    <s:State name="selected" basedOn="{TheState}" /> 
    <s:State name="up" basedOn="{TheState}"/>
    <s:State name="over" basedOn="{TheState}"/>
    <s:State name="down" basedOn="{TheState}"/>
    <s:State name="disabled" basedOn="{TheState}"/>  

    <s:State name="user" />
    <s:State name="group" />

</s:states>


<s:Label y="4" x="34" id="theUserLabel" text="{data.UserName}" color="#000000" includeIn="user"/><s:Label text="{data.UserName}"  y="4" x="24" id="theGroupLabel" color="#000000" includeIn="group" fontWeight="bold"/><mx:Image id="imgGroup" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0071-16.png')"  width="16" height="16" x="3" visible="true" buttonMode="true" includeIn="group"/><mx:Image id="imgUser" source="@Embed(source='file:/D:/Work/RapidReport/Images/nd0032-48.png')" width="16" height="16" x="13" visible="true" includeIn="user"/>

Craig Mc
  • 505
  • 1
  • 13
  • 30