Arbetar med Flex DataGrid och Nested Data Structures

Det händer ofta att de data som behöver ses / presenteras i en Flex DataGrid kommer från en XML-fil eller JSON med mer än en nestnivå. Olyckligtvis tillåter Flex DataGrid som standard att du endast visar nollställda objektrader.

Denna handledning visar hur du kan utöka Flex DataGrid-klassen för att rymma mer komplicerade datastrukturer. Det kommer också att visa dig hur du kan sortera alla kolumner, även när du använder inbyggda datastrukturer.




Introduktion

Denna handledning förutsätter att du känner till grunderna för Flex, hur man använder Flex Builder och hur man skriver MXML-filer. Du bör ha en kopia av Flex Builder installerad på ditt system.

Steg 1: Konfigurera Flexprojektet

Det första steget är att installera projektet i Flex Builder. Skapa ett nytt projekt i Flex Builder med Projektnamn som "NestedDataGrid" och ansökningstyp som "Webapplikation (körs i Flash Player)". Lämna alla andra alternativ till standardvärdena och klicka på Slutför.

Steg 2: Importera provdata

De data som vi ska visa i DataGrid erhålls från en XML-fil. Skapa en mapp i mappen "src" som heter "tillgångar" och sätt data nedan i en fil som heter "meetings.xml". Alternativt kan du ladda ner XML-filen härifrån och placera den i mappen "tillgångar".

    hög  Lisa Green [email protected] +330-7593  12 juli 2009  Rum 405   medium  Christopher Martin [email protected] +330-7553  14 juli 2009  Rum 405   hög  George Rodriguez [email protected] +330-7502  18 juli 2009  Rum 771   hög  Jennifer Parker [email protected] +330-5380  20 augusti 2009  Rum 562  

Steg 3: Gör gränssnittet

Här är en snabb sammanfattning av hur du bygger gränssnittet för att visa data och lämpliga ID-värden som krävs för koden i denna handledning:

  1. Öppna filen NestedDataGrid.mxml och gå till designvyn
  2. Dra och släpp en "Panel" från komponentens vy. Ange sitt ID till "meetingsPanel" och Titel till "Meetings"
  3. Ställ in panelens höjd och bredd till 500 och ställ in X och Y-värdena till 0
  4. Dra och släpp en "DataGrid" på panelen
  5. Ställ in X- och Y-värdena till 10
  6. Ställ in bredden till meetingsPanel.width-40 och höjden till 45%
  7. Gå till källvyn och lägg till attributlayouten = "vertikal" i "mx: Appication" -taggen

Ditt gränssnitt ska likna det som visas i bilden nedan:

MXML i källvyn bör se så här ut:

            

Läser i XML-filen

I de tre följande stegen skapar vi en HTTPService-komponent, läser data från XML-filen och lagrar den i en lokal variabel. Detta görs i tre steg:

Steg 4: Skapa HTTPService-komponenten

Byt till källvyn i MXML-filen och lägg till följande kod strax nedanför mx: Tillämpning märka:

 

Funktionen httpResultHandler () kommer att ringas när data har hämtats. Om det finns ett fel vid hämtning av data heter httpFaultHandler () -funktionen. Observera att detta endast skapar HTTPService-objektet, data måste hämtas av ett explicit funktionssamtal (se understeg 3)

Steg 5: httpResultHandler () och httpFaultHandler ()

Lägg till en mx: Script tag precis under mx: Tillämpning märka. Inne i det, definiera variabeln som håller inkommande data och funktionerna för att hantera händelserna från HTTPService-komponenten. Koden som gör det ser så här ut:

 importera mx.rpc.events.FaultEvent; importera mx.rpc.events.ResultEvent; importera mx.collections.ArrayCollection; importera mx.controls.Alert; [Bindable] public var dataForGrid: ArrayCollection; privat funktion httpResultHandler (händelse: ResultEvent): void dataForGrid = event.result.meetings.meeting;  privat funktion httpFaultHandler (händelse: FaultEvent): void Alert.show ("Fel inträffade vid att få sträng"); 

Variabeln 'dataForGrid' innehåller de data som vi ska läsa in. Den 'Bindable' -taggen ser till att när data ändras (när den läses in) uppdateras DataGrid i enlighet därmed. XML läses in som ett objekt som passeras genom "ResultEvent" -händelsen, och "event.result.meetings.meeting" öppnar ArrayCollection av "meeting" -objekten.

Steg 6: Hämta data från XML-filen

I det här steget görs det faktiska funktionssamtalet för att få XML-data. En intialiseringsfunktion tilldelas händelsen som utlöses varje gång programmet laddas - "creationComplete" -händelsen. Lägg till attributet creationComplete = "getData ()" till 'mx: Application' -taggen och definiera funktionen 'getData ()' som nedan (som ska läggas till efter funktionen httpFaultHandler):

 privat funktion getData (): void readXML.send (); 

Detta gör att HTTPService-objektet får data från filen. När data har hämtats utlöses "resultatet" -händelsen som kallar funktionen "httpResultHandler ()". Om det finns ett problem med att få data, utlöses händelsen "fel", som kallar funktionen httpFaultHandler ().

Steg 7: Milestone

Vid denna tidpunkt bör din NestedDataGrid.mxml se ut så här:

                

Steg 8: DataGrid med icke-nested data

Jag ska bara kort påpeka varför nestad data ställer problem i displayen, genom att först visa hur du visar icke-nestad data. Säg att du från XML-filen ovan bara ville visa datum, plats och prioritet för mötena (och inte presentatörsinformationen). Nedanstående kod kommer att kunna visa den utan några problem (innehållet i "mx: Panel" visas här. All annan kod är densamma):

        

Resultatet av detta skulle vara följande ansökan:


Observera att dataProvider-attributet för DataGrid kan tilldelas direkt till ArrayCollection 'dataForGrid', och varje DataGridColumn-insida får ett dataField-attribut som direkt motsvarar egenskapsnamnet. Antag emellertid att du vill få tillgång till presentatörens namninformation, den kan nås som "presentatörsnamn". Om du försöker ge detta värde till "dataField" får du ett fel. Detta beror på att Flex inte stöder nestade objekt som standard. Läs vidare för att lära dig hur du löser detta problem genom att utöka klassen DataGridColumn och skriva din egen kod för att hantera det här fallet.

Steg 9: Skapa NestedDataGridColumn Class

Vi omdefinierar några funktioner i DataGrid-kolumnklassen för att kringgå det ovan beskrivna problemet. Skapa först en mapp i katalogen 'src' som kallas 'klasser'. Skapa en ny "ActionScript Class" i den mappen, namngiven "NestedDataGridColumn". I fältet "Superclass" klickar du på "Bläddra ..." och väljer "DataGridColumn" från listan som dyker upp. Lämna allt annat till standardvärdena och klicka på "Slutför". En ny fil ska ha skapats och befolts med följande kod:

 paketklasser import mx.controls.dataGridClasses.DataGridColumn; public class NestedDataGridColumn utökar DataGridColumn public function NestedDataGridColumn (kolumnnamn: String = null) super (columnName); 

Steg 10: Deklarera egenskapen "nestedDataField"

I klassen NestedDataGridColumn lägger du till en offentlig bindbar variabel som heter 'nestedDataField'. Vi använder det här istället för standarddatatypen 'dataField' för att skicka fältnamnet. Detta är viktigt, för om standard egenskapen 'dataField' används, ett fel som säger Fel: Sök kriterier måste innehålla minst ett sorteringsfältvärde. kommer att inträffa när vi försöker sortera DataGrid efter att ha definierat den anpassade sorteringsfunktionen senare.

Steg 11: Omdefiniera 'itemToLabel' Funtion

Som du kan se har den nya klassen vi skapat redan befolts med en konstruktör. Lämna konstruktören som den är och nedanför som lägger till följande funktion:

 åsidosätta allmän funktion itemToLabel (data: Object): String var-fält: Array; Var etikett: String; var dataFieldSplit: String = nestedDataField; var currentData: Objekt = data; // kontrollera om värdet nestedDataField innehåller en '.' (dvs åtkomst till ett kapslade värde) om (nestedDataField.indexOf (".")! = -1) // få alla fält som behöver nås fält = dataFieldSplit.split ("."); för varje (var f: String i fält) // loop genom fälten en efter en och få det slutliga värdet, går ett fält djupt varje iteration currentData = currentData [f]; om (currentData är String) // returnera slutvärdesavkastningen String (currentData);  // om det inte finns någon nestning involverad annars if (dataFieldSplit! = "") currentData = currentData [dataFieldSplit];  // Om vår metod inte har fungerat som förväntat, vänta att ringa standardfunktionen försök label = currentData.toString ();  fångst (e: fel) label = super.itemToLabel (data);  // returnera resultatåtervändningsetiketten; 

Omdefiniera funktionen "itemToLabel" är nyckeln till att kunna få tillgång till kapslade data i din DataGrid. Funktionen itemToLabel styr vad som visas i DataGrid-raderna. Så vi använder det här för att be Flex att visa den kapslade data på det sätt som vi har angivit.

Som du kan se börjar funktionsdefinitionen med nyckelordet "åsidosätt", vilket innebär att den förinställda standardfunktionen med samma namn överstiger till förmån för den funktion du har definierat. Varje uttalande förklaras i kommentarerna. Kortfattat, vad funktionen gör är att kontrollera om nöda datafält är åtkomliga (om en '.' Är närvarande). Om det är, få varje datafält namn och iterera genom data Provider, gå djupare varje steg genom att komma till barnfältet.

Funktionen "itemToLabel" kallas av Flex med ett argument som innehåller den ArrayCollection som specificerades som dataProvider till dataGrid. Alla attribut av NestedDataGridColumn (när den används i mxml-filen) är direkt tillgängliga, och alla offentliga egenskaper som definieras i den här klassen kan tilldelas ett värde i MXML. I vår NestedDataGrid.mxml-fil ersätter vi komponenterna 'mx: DataGridColumn' med 'classes: NestedDataGridColumn'-komponenten och tilldelar de specifika element som vi vill visa i kolumnerna till attributet nestedDataField (som deklarerades i " NestedDataGridColumn.as "-filen). DataGridColumn ska nu se ut så här:

          

Observera att jag direkt specificerar egenskapen 'nestedDataField' som "presentatörsnamn" och "presentatörs-telefon" här. Jag har också lagt till bredder i kolumnerna och satt bredden på komponenten 'mx: panel' till 600px för bättre visning. Jag har lagt till egenskapen "sortera" för att vara falsk mot de två nya kolumnerna. Om du tar bort det här (eller ställ det till sant) och kör programmet kommer kolumnen inte att sortera. Vi löser detta i nästa steg genom att definiera vår egen sorteringsfunktion. För tillfället ska applikationen se ut så här:


Steg 12: Skrivning av anpassad sorteringsfunktion

Det enda som kvarstår är att definiera den anpassade sorteringsfunktionen så att sorteringen också kommer att aktiveras i alla fält (t.ex., du vill sortera presentatörsnamnen alfabetiskt). Lägg till funktionen "mySortCompareFunction" under funktionen "itemToLabel" enligt följande:

 privat funktion mySortCompareFunction (obj1: Object, obj2: Object): int var-fält: Array; var dataFieldSplit: String = nestedDataField; var currentData1: Objekt = obj1; var currentData2: Objekt = obj2; om (nestedDataField.indexOf (".")! = -1) fält = dataFieldSplit.split ("."); för varje (var f: sträng i fält) currentData1 = currentData1 [f]; currentData2 = currentData2 [f];  annars if (dataFieldSplit! = "") currentData1 = currentData1 [dataFieldSplit]; currentData2 = currentData2 [dataFieldSplit];  om (currentData1 är int && currentData2 är int) var int1: int = int (currentData1); var int2: int = int (currentData2); var resultat: int = (int1> int2)? - 1: 1; returresultat;  om (currentData1 är String && currentData2 är String) currentData1 = String (currentData1); currentData2 = String (currentData2); returnera (currentData1> currentData2)? - 1: 1;  om (currentData1 är Date && currentData2 är Date) var date1: Date = currentData1 som Date; var date2: Date = currentData2 som Date; var date1Timestamp: Number = currentData1.getTime (); var date2Timestamp: Number = currentData2.getTime (); returnera (datum1Timestamp> datum2Timestamp)? - 1: 1;  returnera 0; 

Denna funktion kommer att kallas av Flex med två objekt och det förväntas returnera antingen -1,0 eller 1 beroende på om det första objektet är större än, lika med eller mindre än det andra objektet. Flex tar hand om själva sorteringen.

Denna funktion använder samma logik som funktionen 'itemToLabel' för att få det lämpliga kapslade värdet. Sedan beror det på typen av värdet (vare sig det är int, String eller Date) det jämför det på lämpligt sätt och returnerar -1 om 'currentData1' är större än 'currentData2', 0 om de är lika och 1 om 'currentData2 'är större än' currentData1 '.

Steg 13: Anslutning av anpassad sorteringsfunktion

Om du märkte, är 'customSortCompareFunction' inte en fördefinierad funktion i klassen DataGridColumn som vi åsidosätter. Denna funktion måste tilldelas som sorteringsfunktionen på ett annat sätt. Vi måste tilldela den fördefinierade variabeln 'sortCompareFunction' namnet på sorteringsfunktionen, som är 'customSortCompareFunction' i vårt fall. Detta bör göras inom konstruktören. Konstruktören ser nu ut så här:

 offentlig funktion NestedDataGridColumn (columnName: String = null) // den anpassade sorteringsfunktionen tilldelas den fördefinierade variabelen sortCompareFunction = mySortCompareFunction; super (column); 

När det här är klart är du helt klar. Du har nu en anpassad klass som kan hantera godtyckligt kapslade data som visas i en DataGrid. Och du kan sortera rutnätet som du vill.

Slutsats

Idag lärde du dig att kringgå en begränsning av FlexDataGrid-klassen för att få godtyckligt kapslade data och visa den i en DataGrid. Du lärde dig också att definiera din egen sorteringsfunktion så att nätet fortfarande kan sorteras. Du kan nu använda denna NestedDataGridColumn i alla dina applikationer utan några överliggande kostnader.

Du kan vidareutveckla funktionen "itemToLabel" för att inkludera andra godtyckliga åtkomstformar - säg, öppna arrayer i barnobjekten eller få åtkomst till xml-attribut. Du kan också förlänga sorteringsfunktionen för att sortera andra typer av data. Du kanske också kan lägga till andra funktioner som att färga raderna baserat på mötesprioriteten och visa mer information om presentatören genom att klicka på en rad.

Tack för att du läser :)