Avoid ItemRenders Caching in a Spark List in Flex 4 - actionscript-3

I have two Spark Lists with custom Item Renderers. I'm working on an application that enables users to drag these Item Renderers from one List to the other. When one of these IRs is dropped in a new position or in another List, I'm updating the dataproviders: I remove the object from one list's dataprovider and add it to the other's dataprovider. This is working ok.
The problem is that sometimes the IR is cached and it doesn't show the correct information, based on its data.
How can I force the Lists to never cache IRs, so that every time I modify the dataprovider all Item Renders re-create all IRs. Performance won't be an issue since I have few items on each list.

A few things..
1) ItemRenderers should always be cached [and reused]. This is one of the benefits of using a Flex list in the first place. I suspect your itemRenderer is implemented inorrectly as to not change when it's data changes. If you share some code for this it would be helpful. But, basically, your itemRenderer should listen to the dataChange event and when the data changes you should update the component's visual display with new data.
2) In Flex 3, I'd have sworn that dragging an item from one list to another automatically updated the relevant dataProviders. Are you sure you need to write manual code to make those changes? You will, though, need code to update your backend as relevant.

Flextras has some good points, but to answer your specific question, you can set useVirtualLayout to false on Spark Lists. This will ensure there is a renderer for every item in your list and thus avoiding the recycling issues. You should really only do this when you have a relatively short list of items though, otherwise you will have performance issues, which as Flextras noted, is the reason Flex recycles renderers.

I put a reset method in my set data to assure renderer variables are reinitialized
override public function set data(object:Object):void
{
if (object == null)
{
return;
}
reset(); // reset locals to their base. ie. x=0, y=0, counter=0
// set up renderer using data
}

Related

Reordering items in a GridView with a VariableSizedWrapGrid in WinRT

I want to create VariableSizedWrapGrid like this
BUT, I also want the items to be draggable (the CanReorderItems property), according to this post this is not supported because the lack of 'some' interfaces..
I tried it and indeed the reordering stops working if I use the VariableSizedWrapGrid.
Could anybody point me in the right direction of the interfaces that are missing to get this done?
Flores,
You pretty much have to implement the drag events yourself.
Here's an excellent blog post detailing what you need to do:
http://www.renauddumont.be/en/2012/windows-8-csharp-xaml-drag-drop
However, the blog doesn't mention how to do the DragOver logic very well. Basically, you have to check what item you're over, and then depending on the direction (dragging up/down/left/right) you have to call the corresponding visual state to get the smooth animation.
So for example, if the dragged item was over an item below it (you can check based on the item's index in your collection), then you need to do something like:
VisualStateManager.GoToState((Control)containerOfItemBelow, "BottomReorderHint", true);
BTW, if you're using a GroupedDataSource, Drag & Drop would also be broken. I found that I can skirt the whole GroupedDataSource concept easily by nesting Gridviews & Listsviews.
HTH

Getting a list of the rendered items

I have my own custom component. This component extends from a basic container. I want to be able to access the itemRenderer instances that are being visualized. I know that the component mx:list has an internal getter that provides an array of Arrays containing the itemRenderer instances that render each data provider item. I want the same thing. Any idea how of how to do that?
To be more specific: I am setting the selected property of my dataProvider items to true or false. From the updateDisplayList funcion of my ItemRenderer I check for changes of the property and correct the border color of the selected ones. Unfortunately I have to force the updateDisplayList function. I already did this once on a ItemRenderer from a list. Only with the list it was practical because by making my own list I was able to get the list of items being rendered and therefore visualized (cannot be many). It was no overhead to go trough the rendered Items and updateDisplayList. But in this case I can have 100 items. Imagine checking and changing styles on so many items. Thanks
The Flex architects intentionally made this difficult to do, because they are properly encapsulating the component. In short, to even try to do this is a violation of good OOP principles.
That said, about 90% of the things you are probably trying to do can be done by manipulating the data item, and the remaining 10% can be done by using a ClassFactory for your itemRenderer that sets a custom property on your itemRenderer to a callback where you can look at the data available to the containing context and provide back a value based on that.
If you elaborate a bit more on your end goal, I can give you more specifics.
Edit in light of clarification:
You need to make your data object class dispatch an event when it changes (one way is to make it bindable, or just make the selected property bindable). Then, in your renderer, listen for the change event and take the appropriate action.
A second way to handle this would just be to refresh() the collection, storing the selectedItem first (if you care about that) and resetting it once the refresh has finished.
I believe you can access the itemRenderer instances through getChildAt method. Flex 3's container overrides "getChildAt", "numChildren", given that some children are logical children, while some are decorative children such as background, border and scrollbars.
Keep in mind that itemRenderer may not right away become available upon dataProvider assignment, as they may be created during the next component lifecycle. Check with the underlying container's documentation and find out which event to be listened when the renderers are surely created, so you can reliably access them.

Prevent Scaleform TileList from filling last row with disabled ItemListRenderer objects?

I'm using Actionscript 3 and Scaleform 4.1 to command an instance of a TileList in a Flash project (CS 5.5).
I have got the TileList populating with ListItemRenderer objects (basically buttons).
In my current situation, I need rows of 4, but I need to place 15 buttons (design requirement). The TileList automatically populates the final row with 3 buttons, and one Disabled state button (instead of a blank space).
So the question:
Can you prevent the TileList from placing Disabled buttons (ListItemRenderer) in remainder spaces?
Is the TileList required to fill a grid to capacity (with Disabled buttons if necessary)?
Can you force a TileList to leave remainder spaces empty?
Alternate solutions also welcome, i.e. can you add another state to the ListItemRenderer such as "blank"? If so, how would you force TileList to default to that instead of Disabled?
If there is good documentation available on this, I don't mind an RTFM reply with a link, but I haven't found anything after a couple days scrounging. Thanks!
It is certainly possible to extend or modify the TileList to suit your needs. That is why we've released CLIK's source. But to answer your question, by Default, the Tilelist is set up to use a blank/disabled renderer for empty tiles.
You can handle this without extending the tilelist, but instead the item renderer itself (much more common anyway for displaying your custom data). The 'disabled' renderer's will all get setdata(null) called on them. Thus just override setdata to toggle the visibility when that is the case:
if ( data != null )
{
//do stuff with data
visible = true;
}
else
{
visible = false;
}

Event once all the custom item renderers have been created/set

I'm using a custom item renderer in my datagrid, and need to make a button visible or invisible based on if there has been a negative value on any of the values in the renderer. So I'd like to set a flag to false when the first renderer is set off, turn it to true if there's any negative values, and at the end check for the value of the flag. I know I can dispatch a dataChange event for every time the data is changed in the renderer instances, but I was wondering if there is anyway I can know when all of them are done?
Thanks!
There is no such event.
Like any other Flex component, a renderer will dispatch a CREATION_COMPLETE after it's been created. ItemRenderers are generally recycled (the same object gets assigned new data to render), thus listening for CREATION_COMPLETE is not sufficient, unless you disable the recycling.
For a Spark List component, you can disable recycling by setting useVirtualLayout=false on the layout class. I'm not sure if the Spark DataGrid class support this or not. The MX DataGrid may have some other way to do this.
Disabling the recycling, however, can have performance implications. I think your idea w/the DATA_CHANGE event is the best solution:
determine the initial state of the data (ie: are there any negative values)
in the renderer, use the DATA_CHANGE event (or just override the setter for the renderer's data property) to know when the data has changed
When the data changes, dispatch a custom event class that will bubble. This event has a property that tells you if the value is negative or not.
Since your custom event from the renderers will bubble up to the grid, you can add one listener on the grid to handle changes from all the renderers.
You should have a look into RendererExistenceEvents. You should be able to tell when they are all created based on how many items you have in your list or at least how many should be in view at once.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/events/RendererExistenceEvent.html

AS3: strategy for adding sprites that animate sequentially

I am developing a component that can list files that users select from their filesystem. I'm using a (extended) FileReferenceList and (my own) FileReferenceDisplayList. The latter listens for events from the former.
If the FileReferenceDisplayList receives a FileReferenceListEvent.ADDED event, it should display the new item in the displaylist. However, when multiple files are added at once I want to animate them sequentially in stead of at the same time. What would be the best strategy for making sure the items are animated with small pauses between them?
I thought about putting newly added items in a queue and then polling the queue for existing items with an Event.ENTER_FRAME. But maybe you can suggest another method that doesn't need to make use of Event.ENTER_FRAME?
Edit
I guess I forgot to mention that the part that puzzles me the most how I can set some timeout if multiple files are added. Maybe I should use the queue's length to multiply the timeouts for the items? So, if a file is added, I set the animation timeout for that item to be multiplied by the current length of the queue? (Just thinking out loud here).
take a look at TimeLineLite from Greensock - http://blog.greensock.com/timelinelite/
insertMultiple() and appendMultiple()
provide some very powerful sequencing
tools, allowing you to add an Array of
tweens or timelines and optionally
align them with SEQUENCE or START
modes, and even stagger them if you
want.
You can use a Timer but why not stick with the ENTER_FRAME.