I am working on a datagrid with custom itemRenderer & [Bindable]xmllist as dataprovider. Now the changes done in xmllist are not reflected on datagrid UI until unless I re-assign the dataprovider as the same xmllist.
As the dataprovider is Bindable so re-assigning is not required.
But it was not working so I re-assigned the xmllist to the dataprovider of datagrid. It worked.
Now my problem is when I re-assign the dataprovider my datagrid flicker(refreshes). It should not happen.
1) Is there any way out to avoid re-assigning of dataprovider?
2) Is there any way to stop flickering of datagrid on re-assigning the dataprovider?
Thanks in advance.
I think xmlList, along with xml are not able to be bound for whatever reason, so binding doesn't work with them. You could convert your xmlList to an arrayCollection and bind to that. The flicker would probably have something to do with your custom itemRenderer, but I think we would need to see the code to know more.
Related
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.
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
I have a class named Student, it has several properties along with the property "isSelected:Boolean"and the class is defined Bindable.
[Bindable]
[RemoteClass(alias="portal::Student")]
public class Student
In an mxml application I have a datagrid in which its dataprovider has been set to an ArrayCollection of Students. I have a column of checkboxex for the datagrid along with a headerItemRenderer checkbox which is supposed to select all the students (all checkboxes in rows should be selected or deselected).
I have defined a handler for the click event of the checkbox in the header which sets the isSelected property of each Student object in dataProvider to false or true. But on click of this check box in the header, I get the warning: unable to bind to property 'isSelected' on class 'Student' and therefore check boxes in rows do not get updated.
I don't get why the binding does not work here and don't know what to do to fix this issue. Any help is greatly appreciated.
It depends, i guess you have somewhere in the code a reference to the student instance, you want to bind on. This reference has to be declared [Bindable] as well, in order to get the binding chain to work.
Also, when you not depend on ActionScript to get the binding to work, you don't have to extend EventDispatcher, because MXML will generate that code for you (with regards to Cosma's comment).
Do you define an inline renderer? This is not the optimum in my opinion, since a component is generated and debugging gets a lil fuzzy, since you might run into scope problems. I'd recommend implementing a new component, implement IDataRenderer and propagate the data to the children through the live cycle or implement the component in MXML. Why IDataRenderer? This interface is necessary.
Also, i'm not sure on that one, but shouldn't it be
[Bindable]
[RemoteClass(alias="portal.Student")]
public class Student {}
?
Let your actionscript class extends EventDispatcher (binding is based on event dispatching).
You need to make sure that your ItemRenderer saves the incoming data in a property marked as [Bindable]. You'll want to pass the entire Student in, rather than just "isSelected"...
I have a case where the SelectedItem isn't called after the data provider changes for
a dropdownlist.
is there a way to detect if such a change occurred?
Thanks
Just about every public property in the Flex Framework has a 'propertyChanged' event that is dispatched from the properties set method. They are used primarily for binding purposes, but not usually formally documented.
The dataProvider set method of a DropDownList does indeed dispatch a dataProviderChanged event. The code is several layers up in the hierarchy, as part of SkinnableDataContainer or if the skin for your 'SkinnableDataContainer' has a dataGroup it is dispatched from the DataGroup.
But, this event will probably will not be exposed via code hinting in MXML. You'll have to listen for it in ActionScript:
myList.addEventListener('dataProviderChanged', onDataProviderChanged);
Keep in mind this event will always be dispatched when the dataProvider changes, regardless of what happens to the selectedItem property.
You can listen to changes in the selectedItem in a DropDownList through the IndexChangeEvent, illustrated by the code below:
<s:DropDownList id="dl_mydl"
dataProvider="{dataProvider}"
change="dropDownListChangeHandler(event)"
/>
protected function dropDownListChangeHandler(event:IndexChangeEvent) : void
{
//DO SOMETHING
}
I have a itemrenderer in datagrid and I am trying to get the instance of itemrender in datagrid keypressevent as follows
var col:DataGridColumn = _datagrid.columns[_datagrid.selectedCells[0].columnIndex];
var myItemrend:MyItemrender = col.itemRenderer as MyItemrender;
But the above myItemrend instance is null. How can I get the itemrenderer instance.
Please help.
Thanks,
Rejeev.
I have an itemrenderer in Datagrid and it is used as itemeditor also by rendererIsEditor=true. My itemrenderer has a textinput and a list, where I open the list, for editing, when a focusin event is occurred in textinput, this happens while clicking the cell.
I need the same editing to happen while I enter using the keyboard(Enter), so I am trying to get the instance of the itemrender in Keyboard.ENTER and using this I can dispatch the textinput focusin event.
Thanks,
Rejeev.