Werken met de Flex DataGrid en geneste gegevensstructuren

Het komt vaak voor dat de gegevens die moeten worden bekeken / gepresenteerd in een Flex DataGrid afkomstig zijn van een XML-bestand of JSON met meer dan één nestniveau. Helaas kunt u met de Flex DataGrid standaard alleen geneste objectarrays op één niveau weergeven.

Deze zelfstudie laat zien hoe u de klasse Flex DataGrid kunt uitbreiden om meer gecompliceerde gegevensstructuren te kunnen opnemen. Het zal u ook laten zien hoe u alle kolommen sorteerbaar kunt maken, zelfs wanneer u geneste gegevensstructuren gebruikt.




Invoering

Deze tutorial gaat ervan uit dat je de basisprincipes van Flex kent, hoe je Flex Builder gebruikt en hoe je MXML-bestanden schrijft. U moet een kopie van Flex Builder op uw systeem hebben geïnstalleerd.

Stap 1: Stel het Flex-project in

De eerste stap is het opzetten van het project in Flex Builder. Maak een nieuw project in Flex Builder met Naam van het project als "NestedDataGrid" en Applicatie type als "Webtoepassing (wordt uitgevoerd in Flash Player)". Laat alle andere opties op hun standaardwaarden staan ​​en klik op Voltooien.

Stap 2: Voorbeeldgegevens importeren

De gegevens die we in de DataGrid zullen laten zien, zijn afkomstig van een XML-bestand. Maak een map in uw 'src' map genaamd 'assets' en zet de onderstaande gegevens in een bestand met de naam 'meetings.xml'. Als alternatief kunt u het XML-bestand hier downloaden en in de map 'assets' plaatsen.

    hoog  Lisa Green [email protected] +330-7593  12 juli 2009  Kamer 405   medium  Christopher Martin [email protected] +330-7553  14 juli 2009  Kamer 405   hoog  George Rodriguez [email protected] +330-7502  18 juli 2009  Kamer 771   hoog  Jennifer Parker [email protected] +330-5380  20 augustus 2009  Kamer 562  

Stap 3: Maak de interface

Hier volgt een korte samenvatting van het bouwen van de interface om de gegevens en de juiste ID-waarden weer te geven die voor de code in deze zelfstudie zijn vereist:

  1. Open het bestand NestedDataGrid.mxml en ga naar de ontwerpweergave
  2. Versleep een 'paneel' vanuit de weergave Componenten. Stel zijn ID in op "meetingsPanel" en titel op "Vergaderingen"
  3. Stel de hoogte en breedte van het paneel in op 500 en stel de X- en Y-waarden in op 0
  4. Versleep een 'DataGrid' naar het paneel
  5. Stel de X- en Y-waarden in op 10
  6. Stel de breedte in op meetingsPanel.width-40 en de hoogte op 45%
  7. Ga naar de bronweergave en voeg in de tag 'mx: Appication' het attribuut layout = "vertical" toe

Uw interface moet er ongeveer zo uitzien als in de afbeelding hieronder:

De MXML in de bronweergave zou er als volgt uit moeten zien:

            

Het lezen van het XML-bestand

In de volgende drie stappen maken we een HTTPService-component, lezen we de gegevens uit het XML-bestand en slaan deze op in een lokale variabele. Dit gebeurt in drie fasen:

Stap 4: Maak de HTTPService-component

Schakel over naar de bronweergave van het MXML-bestand en voeg de volgende code direct onder de mx: Application label:

 

De httpResultHandler () -functie wordt aangeroepen wanneer de gegevens zijn opgehaald. Als er een fout optreedt bij het ophalen van de gegevens, wordt de functie httpFaultHandler () aangeroepen. Merk op dat dit alleen het HTTPService-object maakt, de gegevens moeten worden opgehaald door een expliciete functieaanroep (zie subparagraaf 3)

Stap 5: httpResultHandler () en httpFaultHandler ()

Voeg een toe mx: Script tag net onder de mx: Application label. Daarbinnen definieert u de variabele die de inkomende gegevens vasthoudt en de functies om de gebeurtenissen van de HTTPService-component af te handelen. De code om dat te doen ziet er als volgt uit:

 import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.collections.ArrayCollection; import mx.controls.Alert; [Bindbaar] public var dataForGrid: ArrayCollection; private function httpResultHandler (event: ResultEvent): void dataForGrid = event.result.meetings.meeting;  private function httpFaultHandler (event: FaultEvent): void Alert.show ("Fout opgetreden bij het ophalen van een string"); 

De variabele 'dataForGrid' bevat de gegevens die we gaan inlezen. De tag '[Bindbaar]' zorgt ervoor dat wanneer de gegevens veranderen (wanneer deze wordt ingelezen), de DataGrid overeenkomstig wordt bijgewerkt. De XML wordt ingelezen als een object dat wordt doorgegeven aan de gebeurtenis 'ResultEvent' en 'event.result.meetings.meeting' maakt toegang tot de ArrayCollection of 'meeting' -objecten.

Stap 6: Verkrijg de gegevens uit het XML-bestand

In deze stap wordt de eigenlijke functieaanroep gedaan om de XML-gegevens te ontvangen. Er is een initialisatie-functie toegewezen aan de gebeurtenis die wordt geactiveerd telkens wanneer de toepassing wordt geladen - de gebeurtenis 'creationComplete'. Voeg het kenmerk toe creationComplete = "getData ()" naar de tag 'mx: Application' en definieer de functie 'getData ()' zoals hieronder (toe te voegen na de functie 'httpFaultHandler'):

 private function getData (): void readXML.send (); 

Hierdoor krijgt het HTTPService-object de gegevens uit het bestand. Nadat de gegevens zijn opgehaald, wordt de gebeurtenis 'result' geactiveerd die de functie 'httpResultHandler ()' aanroept. Als er een probleem is bij het ophalen van de gegevens, wordt de 'fault'-gebeurtenis geactiveerd, die de httpFaultHandler () -functie oproept.

Stap 7: mijlpaal

Op dit punt zou uw NestedDataGrid.mxml er als volgt uit moeten zien:

                

Stap 8: DataGrid met niet-geneste gegevens

Ik zal even kort uitleggen waarom geneste gegevens problemen opleveren bij weergave, door eerst te laten zien hoe je niet-geneste gegevens weergeeft. Stel dat u in het bovenstaande XML-bestand alleen de datum, plaats en prioriteit van de vergaderingen wilde weergeven (en niet de informatie van de presentator). De onderstaande code kan het zonder problemen weergeven (de inhoud van 'mx: Panel' wordt hier weergegeven. Alle andere codes zijn hetzelfde):

        

Het resultaat hiervan zou de volgende applicatie zijn:


Merk op dat het kenmerk dataProvider van de DataGrid direct kan worden toegewezen aan de array 'DataForGrid' van ArrayCollection en dat elke DataGridColumn aan de binnenkant een kenmerk dataField krijgt dat direct overeenkomt met de naam van de eigenschap. Stel dat u toegang wilt hebben tot de naaminformatie van de presentator, deze is toegankelijk als "presenter.name". Als u probeert deze waarde aan het 'gegevensveld' te geven, krijgt u een foutmelding. Dit komt omdat Flex standaard geneste objecten niet ondersteunt. Lees verder om te leren hoe dit probleem op te lossen door de DataGridColumn-klasse uit te breiden en uw eigen code te schrijven om deze kwestie af te handelen.

Stap 9: De klasse NestedDataGridColumn maken

We herdefiniëren enkele functies in de kolom DataGrid om het hierboven geschetste probleem te omzeilen. Maak eerst een map in de 'src' map genaamd 'classes'. Maak een nieuwe 'ActionScript-klasse' in die map met de naam 'NestedDataGridColumn'. Klik in het veld 'Superclass' op 'Bladeren ...' en selecteer 'DataGridColumn' in de lijst die verschijnt. Laat al het andere op de standaardwaarden staan ​​en klik op 'Voltooien'. Er zou een nieuw bestand moeten zijn gemaakt en gevuld met de volgende code:

 pakket klassen import mx.controls.dataGridClasses.DataGridColumn; public class NestedDataGridColumn breidt DataGridColumn uit openbare functie NestedDataGridColumn (columnName: String = null) super (columnName); 

Stap 10: Declaratie van de eigenschap 'nestedDataField'

Voeg in de klasse NestedDataGridColumn een openbare, bindbare variabele toe met de naam 'nestedDataField'. We zullen dit gebruiken in plaats van de standaard 'dataField' eigenschap om de veldnaam door te geven. Dit is van vitaal belang, omdat als de standaard 'dataField' eigenschap wordt gebruikt, een foutmelding wordt gegeven Fout: zoekcriteria moeten ten minste één sorteerveldwaarde bevatten. zal optreden wanneer we de DataGrid proberen te sorteren nadat de aangepaste sorteerfunctie later is gedefinieerd.

Stap 11: De 'itemToLabel'-functie opnieuw definiëren

Zoals u kunt zien, is de nieuwe klasse die we hebben gemaakt al gevuld met een constructor. Laat de constructor zoals deze is en onder die voeg de volgende functie toe:

 override public function itemToLabel (data: Object): String var fields: Array; var label: String; var dataFieldSplit: String = nestedDataField; var currentData: Object = data; // controleer of de waarde nestedDataField een '.' (d.w.z. is toegang tot een geneste waarde) if (nestedDataField.indexOf (".")! = -1) // haal alle velden op die moeten worden benaderd fields = dataFieldSplit.split ("."); voor elk (var f: String in velden) // doorloop de velden één voor één en verkrijg de definitieve waarde, één veld diep gaan elke iteratie currentData = currentData [f]; if (currentData is String) // retourneer de laatste waarde retour String (currentData);  // als er geen nesting is betrokken anders if (dataFieldSplit! = "") currentData = currentData [dataFieldSplit];  // als onze methode niet heeft gewerkt zoals verwacht, gebruik dan de standaardfunctie om label = currentData.toString ();  catch (e: Error) label = super.itemToLabel (data);  // retourneer het retourlabel van het resultaat; 

Het herdefiniëren van de 'itemToLabel'-functie is de sleutel tot toegang tot geneste gegevens in uw DataGrid. De itemTabel-functie bepaalt wat wordt weergegeven in de DataGrid-rijen. Dus we gebruiken het hier om Flex te vragen de geneste gegevens te tonen op de manier die we hebben opgegeven.

Zoals u kunt zien, begint de functiedefinitie met het sleutelwoord 'overschrijven', wat betekent dat de standaard vooraf gedefinieerde functie van dezelfde naam wordt overschreven ten gunste van de functie die u hebt gedefinieerd. Elke verklaring wordt uitgelegd in de opmerkingen. Kort gezegd, wat de functie doet, is controleren of geneste gegevensvelden worden gebruikt (als een '.' Aanwezig is). Als dit het geval is, haalt u de naam van elk gegevensveld op en doorloopt u de gegevensprovider, waarbij u elke stap dieper gaat in het toegang tot het onderliggende veld.

De functie 'itemTabel' wordt door Flex aangeroepen met een argument dat de ArrayCollection bevat die als de dataProvider voor de dataGrid is opgegeven. Alle kenmerken van de NestedDataGridColumn (wanneer deze wordt gebruikt in het mxml-bestand) zijn rechtstreeks toegankelijk en aan openbare eigenschappen die in deze klasse zijn gedefinieerd, kan een waarde in de MXML worden toegewezen. In ons NestedDataGrid.mxml-bestand vervangen we de componenten 'mx: DataGridColumn' door 'classes: NestedDataGridColumn' en wijzen we de specifieke elementen die we in de kolommen willen weergeven toe aan het kenmerk 'nestedDataField' (dat is gedeclareerd in de ' NestedDataGridColumn.as 'bestand). De DataGridColumn zou er nu als volgt moeten uitzien:

          

Merk op dat ik hier de eigenschap 'nestedDataField' rechtstreeks opgeeft als de 'presenter.name' en 'presenter.phone'. Ook heb ik breedtes aan de kolommen toegevoegd en de breedte van de component 'mx: Panel' ingesteld op 600px voor een betere weergave. Ik heb de eigenschap 'sortable' toegevoegd als false voor de twee nieuwe kolommen. Als u dit verwijdert (of instelt op true) en het programma uitvoert, wordt de kolom niet gesorteerd. We zullen dit in de volgende stap oplossen door onze eigen sorteerfunctie te definiëren. Voor nu zou de applicatie er als volgt uit moeten zien:


Stap 12: De aangepaste sorteerfunctie schrijven

Het enige dat nu overblijft, is het definiëren van de aangepaste sorteerfunctie, zodat het sorteren ook in alle velden wordt ingeschakeld (bijvoorbeeld, u wilt de namen van de presentatoren alfabetisch sorteren). Voeg de functie met de naam 'mySortCompareFunction' onder de functie 'itemTabel' toe als gegeven:

 persoonlijke functie mySortCompareFunction (obj1: Object, obj2: Object): int var fields: Array; var dataFieldSplit: String = nestedDataField; var currentData1: Object = obj1; var currentData2: Object = obj2; if (nestedDataField.indexOf (".")! = -1) fields = dataFieldSplit.split ("."); voor elk (var f: String in velden) currentData1 = currentData1 [f]; currentData2 = currentData2 [f];  else if (dataFieldSplit! = "") currentData1 = currentData1 [dataFieldSplit]; currentData2 = currentData2 [dataFieldSplit];  if (currentData1 is int && currentData2 is int) var int1: int = int (currentData1); var int2: int = int (currentData2); var-resultaat: int = (int1> int2)? - 1: 1; terugkeer resultaat;  if (currentData1 is String && currentData2 is String) currentData1 = String (currentData1); currentData2 = String (currentData2); return (currentData1> currentData2)? - 1: 1;  if (currentData1 is Date && currentData2 is Date) var date1: Date = currentData1 as Date; var date2: Date = currentData2 as Date; var date1Timestamp: Number = currentData1.getTime (); var date2Timestamp: Number = currentData2.getTime (); return (date1Timestamp> date2Timestamp)? - 1: 1;  retourneer 0; 

Deze functie wordt door Flex met twee objecten aangeroepen, en deze zal naar verwachting -1.0 of 1 teruggeven, afhankelijk van of het eerste object groter is dan, gelijk is aan of kleiner is dan, respectievelijk, het tweede object. Flex zorgt voor de eigenlijke sortering.

Deze functie gebruikt dezelfde logica als de functie 'itemTabel' om de juiste geneste waarde te krijgen. Afhankelijk van het type van de waarde (of het nu int, String of Date is) vergelijkt het dit passend en geeft -1 als 'currentData1' groter is dan 'currentData2', 0 als ze gelijk zijn en 1 als 'currentData2 'is groter dan' currentData1 '.

Stap 13: Aansluiten van de Custom Sort Function

Als je hebt gemerkt, is 'customSortCompareFunction' geen vooraf gedefinieerde functie in de klasse DataGridColumn die we overschrijven. Deze functie moet op een andere manier als sorteerfunctie worden toegewezen. We moeten aan de vooraf gedefinieerde variabele 'sortCompareFunction' de naam van de sorteerfunctie toewijzen, die in dit geval 'customSortCompareFunction' is. Dit moet in de constructor worden gedaan. De constructeur ziet er nu als volgt uit:

 openbare functie NestedDataGridColumn (columnName: String = null) // de aangepaste sorteerfunctie wordt toegewezen aan de vooraf gedefinieerde variabele sortCompareFunction = mySortCompareFunction; super (columnName); 

Zodra dit is gebeurd, ben je helemaal klaar. U hebt nu een aangepaste klasse die willekeurig geneste gegevens kan verwerken in een DataGrid. En je kunt het rooster sorteren zoals je wilt.

Conclusie

Vandaag heb je geleerd om een ​​beperking van de FlexDataGrid-klasse te omzeilen om willekeurig geneste gegevens te krijgen en deze in een DataGrid te tonen. Je hebt ook geleerd hoe je je eigen sorteerfunctie definieert, zodat het raster sorteerbaar blijft. U kunt deze NestedDataGridColumn nu in al uw toepassingen zonder overhead gebruiken.

U kunt de functie 'itemTabel' verder uitbreiden met een ander willekeurig toegangsformaat - bijvoorbeeld toegang tot arrays binnen de onderliggende objecten of toegang tot xml-kenmerken. U kunt de sorteerfunctie ook uitbreiden om andere soorten gegevens te sorteren. U kunt ook andere functies toevoegen, zoals de rijen inkleuren op basis van de prioriteit van de vergadering en meer informatie over de presentator weergeven door op een rij te klikken.

Bedankt voor het lezen :)