2009-03-14 6 views
4

Dans une première ligne de Flex DataGrid, itemRenderer s'initialise deux fois. Le suivi des résultats révèle que l'infrastructure flexible crée éventuellement deux instances de itemRenderer de la première ligne. Dans une application plus complexe, où itemRenderer contient un ColorPicker lié aux données, une boucle infinie se produit à cause de ce problème. Seule la propriété itemRenderer de la première ligne est initialisée deux fois. Existe-t-il un moyen de contourner le comportement de flex et d'empêcher que cela se produise? Le code suivant illustre le problème:Comment arrêter deux fois la propriété itemRenderer de la première ligne de la grille de données d'instancier/ajouter/initialiser/etc?

Application principale:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="on_initialize(event);"> 
<mx:Script> 
<![CDATA[ 
/** 
* This experiment shows how the first row's itemrenderer is instantiated/added/initialized twice. 
* We've never even noticed this before we found that a data-bound ColorPicker enters a infinite 
* loop when it is within an itemRenderer. 
*/ 
    import mx.collections.ArrayCollection; 
    import mx.events.FlexEvent; 

    private var dg_array:Array; 
    private var dg_arrayCollection:ArrayCollection; 

    private function on_initialize(event:FlexEvent):void { 
     dg_array = new Array(); 
     dg_arrayCollection = new ArrayCollection(); 
     dg_arrayCollection.addItem("item 1"); 
     dg_arrayCollection.addItem("item 2"); 

     dg.dataProvider = dg_arrayCollection; 
    } 
]]> 
</mx:Script> 
<mx:DataGrid id="dg" width="100%" height="100%" rowCount="5"> 
    <mx:columns> 
     <mx:DataGridColumn headerText="Name" itemRenderer="SimpleItemRenderer"/> 
    </mx:columns> 
</mx:DataGrid> 
</mx:Application> 

SimpleItemRenderer:

<?xml version="1.0" encoding="utf-8"?> 
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" initialize="//on_initialize(event);"> 
<mx:Script> 
    <![CDATA[ 
     import mx.events.FlexEvent; 

     [Bindable] 
     override public function set data(value:Object):void { _data = value; }     
     override public function get data():Object { return _data; } 
     private var _data:Object; 

     private function on_initialize_textInput(event:FlexEvent):void { 
      trace("initialize:event.target="+event.target+", " + _data); // runs twice, for the first item only 

     } 

     private function on_creationComplete_textInput(event:FlexEvent):void { 
      trace("creationComplete:event.target="+event.target+", " + _data); // runs twice, for the first item only 
     } 
    ]]> 
</mx:Script> 
<mx:TextInput text="{data}" id="textInput" initialize="on_initialize_textInput(event);" creationComplete="on_creationComplete_textInput(event);"/> 
</mx:Canvas> 

sortie abrégée:

initialize: event.target = ItemRenderers0.dg ... SimpleItemRenderer12 .textInput, null initialize: event.target = ItemRenderers0.dg ... SimpleItemRenderer24.textInput, null creationComplete: event.target = ItemRenderers0.dg ... SimpleItemRenderer24.textInput, élément 1 initialize: event.target = ItemRenderers0.dg ... SimpleItemRenderer29.textInput, null creationComplete: événement.target = ItemRenderers0.dg ... SimpleItemRenderer29.textInput, point 2 creationComplete: event.target = ItemRenderers0.dg ... SimpleItemRenderer12.textInput, point 1

+0

Je vois trois objets différents en cours de création. Êtes-vous sûr que le premier élément est dupliqué? – dirkgently

+0

Pouvez-vous fournir la sortie des traces? – ForYourOwnGood

+0

Ce qui serait vraiment utile, c'est de laisser tomber un point d'arrêt dans la méthode initialize et de voir les piles correspondantes pour les deux exécutions. Cela pourrait donner un aperçu de comment ou pourquoi l'init se produit deux fois. –

Répondre

1

Votre itemRenderer est pas vraiment mis en œuvre correctement, et cela pourrait être la cause de vos problèmes

La méthode des données d'ensemble substituées doit définir super.data = value. Vous n'avez pas besoin d'implémenter votre propre propriété _data car les conteneurs Flex implémentent IDataRenderer et l'ont déjà. Je pense, sans exécuter votre code, que vous rencontrez un problème avec le cache/recyclage.

Ce que je préfère généralement est de créer un [Bindable] private myProperty: Object (généralement un MyObjectVO personnalisé qui étend EventDispatcher). Ensuite, dans ma méthode set data, je vais définir super.data = valeur suivi de if (value! = Null) myProperty = valeur. Cela me permet de taper fortement mes données réelles, de laisser les mécanismes intacts en ce qui concerne l'interface IDataRenderer implémentée par le canevas (ou autre conteneur) et d'assurer que les données sont correctement recyclées.

Initialiser la création d'annoncesComplete sont de mauvais éléments dans itemRenderers car ils sont réellement recyclés et ces méthodes ne se comportent pas comme on pourrait s'y attendre ou le souhaiter.

Je ne peux pas exprimer comment bénéfique this series by Peter Ent on itemRenders était pour moi.

+0

"Initialiser la création d'annoncesComplete sont de mauvais éléments dans itemRenderers car ils sont réellement recyclés et ces méthodes ne se comportent pas comme on pourrait s'y attendre ou le souhaiter." Quelle alternative y a-t-il? – Amalgovinus