Adobe Flex 3: Multi-FilterFunction auf mx:ArrayCollection

Aufgabenstellung

Es wird eine Datenstruktur benötigt, die mehrere FilterFunctions unterstützt und mit der mx:ArrayCollection kompatibel ist.

Problem

mx:ArrayCollection besitzt nur die Eigenschaft für eine einzige Filter-Funktion. Möchte man mehrere Filter setzen, muss man komplexe Funktionen mit Filter-Logik implementieren.

Ansatz

Durch die Erweiterung der mx:ArrayCollection wird eine Methode filterFunctions implementiert, welche mehrere Filter entgegennehmen kann. Die erweiterte BjoernsArrayCollection kann in ArrayCollection gecastet oder ggfs. (z.B. durch eine Schleife) befüllt werden.

Lösung

Folgende Klasse erweritert die normale ArrayCollection um mehrere Filter-Funktionen:

package components
{
  import mx.collections.ArrayCollection;
 
  public class BjoernsArrayCollection extends ArrayCollection
  {
      private var _filterFunctions:Array;
 
      public function BjoernsArrayCollection( source:Array = null )
      {
         super(source);
      }
	
       public function set filterFunctions( filtersArray:Array ):void
       {
         _filterFunctions = filtersArray;
         this.filterFunction = complexFilter;
        }
		
       public function get filterFunctions():Array
       {
         return _filterFunctions;
       }
 
       protected function complexFilter( item:Object ):Boolean
       {
         var filterFlag:Boolean = true;
         var filter:Function;

         for each(filter in filterFunctions)
         {
            filterFlag = filter( item );
            if( !filterFlag ) break;
         }
         return filterFlag;
      }
    }
}

Der Filterfunktionen werden so deklariert:

// Result-Methode von Service liefert eine mx:ArrayCollection, die 
// anhand mehrerer Kriterien gefiltert wird.
public function getResetableOrganizationsHandler(event:ResultEvent):void
{
   // Instanzieren des neuen Objektes
   resetableorgas = new BjoernsArrayCollection();

   // Deklaration der Filter 
   resetableorgas.filterFunctions = 
   [
       filterByProductGroup,
       filterByCompcode,
       filterBySalesdiv,
       filterByMarket
   ];	
		
    // Umsortierung in BjoernsArrayCollection
    resetableorgas.removeAll();
			
    for each(var item:ResetableOrganizationsVO in event.result)
    {
       resetableorgas.addItem(item);				
    }
    
     resetableorgas.refresh();	
}

Der Aufbau der Filter-Funktion:

...
// Rückgabe ist true wenn der Vergleich des Eingegebenen (txtCompcode.text) 
// mit einem Element der ArrayCollection (item.compcode) passt
private function filterByCompcode( item:Object ):Boolean
{
   if( String(item.compcode).indexOf(txtCompcode.text)>-1 )return true;
   return false;
}
...

Ggfs. (z.B. in einem mx:TextInput) die Refresh-Methode aufrufen:

     <mx:TextInput change="{resetableorgas.refresh()}" id="txtCompcode" width="100%"/>

Adobe Flex 3: Rekursive Iteration über alle Controls eines Canvas

Aufgabenstellung

Gelegentlich ist es nötig über alle Komponenten eines mx:Canvas-Elements, einem Container oder einer UIComponent zu iterieren.

Beispiele:
* Deaktivieren von allen Controls eines bestimmten Typs (alle Textfelder ausgrauen)
* Neuschriftung von allen Labels
* Deaktivieren aller Reiter

Ansatz

Durch den Typecast in einen DisplayObjectContainer lässt sich über jedes UI-Element iterieren. Eine Startmethode übergibt das Canvas, bzw. das UI-Urelement. Die Rekursionsmethode castet in den kompatiblen Supertyp DisplayObjectContainer und verfügt über Möglichkeiten der Iteration über seine Eigenschaften.

Lösung

// Startmethode übergibt Urelement der Rekursion
public function startSearch():void
{
searchRecursion(this);
}

// Rekursionsmethode ruft sich selbst auf wenn Child-Elemente v.h.
public function searchRecursion(current:DisplayObjectContainer):void
{
for ( var i:Number=0; i< current.numChildren; i++) { var child:DisplayObject = current.getChildAt(i); trace(getQualifiedClassName(child)); var childContainer:DisplayObjectContainer = child as DisplayObjectContainer; if(childContainer) { searchRecursion(childContainer); } } } [/javascript]