2009-03-14 9 views
4

In der ersten Zeile von Flex DataGrid wird der itemRenderer zweimal initialisiert. Die Verfolgung der Ergebnisse zeigt, dass das Flex-Framework möglicherweise zwei Instanzen des itemRenderer der ersten Zeile erstellt. In einer komplexeren Anwendung, in der der itemRenderer einen datengebundenen ColorPicker enthält, tritt aufgrund dieses Problems eine Endlosschleife auf. Nur der itemRenderer der ersten Zeile wird zweimal initialisiert. Gibt es eine Möglichkeit, das Verhalten von flex zu übergehen und dies zu verhindern? Der folgende Code demonstriert das Problem:Wie verhindere ich, dass der itemRenderer in der ersten Zeile eines Datagrids zweimal instanziiert/hinzugefügt/initialisiert wird usw.?

Hauptanwendung:

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

Verkürzte Ausgabe:

initialize: event.target = ItemRenderers0.dg ... SimpleItemRenderer12 .textInput, null initialisieren: event.target = ItemRenderers0.dg ... SimpleItemRenderer24.textInput, null creationComplete: event.target = ElementRenderers0.dg ... SimpleItemRenderer24.textInput, Element 1 initialisieren: event.target = ItemRenderers0.dg ... SimpleItemRenderer29.textInput, null creationComplete: event.target = ItemRenderers0.dg ... SimpleItemRenderer29.textInput Punkt 2 creationComplete-: event.target = ItemRenderers0.dg ... SimpleItemRenderer12.textInput, Punkt 1

+0

Ich sehe drei verschiedene Objekte erstellt werden. Sind Sie sicher, dass der erste Artikel dupliziert ist? – dirkgently

+0

Können Sie die Ausgabe der Spuren bereitstellen? – ForYourOwnGood

+0

Was wirklich hilfreich wäre, ist, dass Sie einen Haltepunkt in der Initialisierungsmethode löschen und die entsprechenden Stapel für beide Läufe sehen. Das könnte einen Einblick geben, wie oder warum die Init zweimal stattfindet. –

Antwort

1

Ihre itemRenderer nicht wirklich richtig umgesetzt wird, und dies könnte die Ursache Ihrer Probleme sein

Die überschriebene set data-Methode sollte super.data = value festlegen. Sie müssen keine eigene Eigenschaft _data implementieren, da die Flex Container IDataRenderer implementieren und bereits vorhanden sind. Ich denke, ohne Ihren Code laufen zu lassen, dass Sie auf ein Problem mit dem Cache/Recycling stoßen.

Was ich im Allgemeinen bevorzuge, ist ein [Bindable] private myProperty erstellen: Objekt (in der Regel eine benutzerdefinierte MyObjectVO, die EventDispatcher erweitert). Dann setze ich in meiner Set-Datenmethode super.data = Wert, gefolgt von if (Wert! = Null) myProperty = Wert.

Dadurch kann ich meine tatsächlichen Daten stark eingeben, die Mechanismen in Bezug auf die IDataRenderer-Schnittstelle intakt lassen, die von Canvas (oder einem anderen Container) implementiert wird, und stellt sicher, dass die Daten ordnungsgemäß wiederverwendet werden.

Initialize ad creationComplete sind schlechte events in itemRenderers, weil sie tatsächlich recycelt werden und diese Methoden sich nicht so verhalten, wie man es erwartet oder möchte.

Ich kann nicht ausdrücken, wie vorteilhaft this series by Peter Ent on itemRenders war für mich.

+0

"Initialize ad creationComplete sind schlechte evets in itemRenderers, weil sie tatsächlich recycelt werden und diese Methoden nicht so verhalten, wie man es erwarten könnte oder will." Welche Alternative gibt es? – Amalgovinus