Lucrul cu structurile de date Flex DataGrid și cu structuri de date învechite

Se întâmplă adesea ca datele care trebuie să fie vizualizate / prezentate într-un Flex DataGrid provin dintr-un fișier XML sau JSON cu mai mult de un nivel de cuibărit. Din nefericire, în mod implicit, FlexDataGrid vă permite să afișați numai matrice de obiecte cu un singur nivel.

Acest tutorial arată cum puteți extinde clasa Flex DataGrid pentru a acomoda structuri de date mai complicate. Acesta vă va arăta, de asemenea, cum să faceți toate coloanele în ordine, chiar și atunci când utilizați structuri de date imbricate.




Introducere

Acest tutorial presupune că cunoașteți elementele de bază ale Flex, cum să utilizați Flex Builder și cum să scrieți fișiere MXML. Ar trebui să aveți o copie a Flex Builder instalată pe sistemul dvs..

Pasul 1: Configurați proiectul Flex

Primul pas este de a configura proiectul în Flex Builder. Creați un nou proiect în Flex Builder cu Denumirea proiectului ca "NestedDataGrid" și Tip de aplicație ca "aplicație Web (rulează în Flash Player)". Lăsați toate celelalte opțiuni la valorile lor implicite și faceți clic pe Terminare.

Pasul 2: Importați date de probă

Datele pe care le vom afișa în DataGrid sunt obținute dintr-un fișier XML. Creați un dosar în dosarul "src" numit "active" și puneți datele prezentate mai jos într-un fișier numit "meetings.xml". Alternativ, puteți să descărcați fișierul XML de aici și să îl plasați în dosarul "active".

    înalt  Lisa Green [email protected] +330-7593  12 iulie 2009  Cameră 405   mediu  Christopher Martin [email protected] +330-7553  14 iulie 2009  Cameră 405   înalt  George Rodriguez [email protected] +330-7502  18 iulie 2009  Cameră 771   înalt  Jennifer Parker [email protected] +330-5380  20 august 2009  Cameră 562  

Pasul 3: Faceți interfața

Iată o defalcare rapidă a construirii interfeței pentru a afișa datele și valorile corespunzătoare ID necesare pentru cod în acest tutorial:

  1. Deschideți fișierul NestedDataGrid.mxml și mergeți la vizualizarea de proiectare
  2. Glisați și plasați un panou din vizualizarea Componente. Stabiliți ID-ul său la "meetingsPanel" și titlul la "Meeting"
  3. Setați înălțimea și lățimea panoului la 500 și setați valorile X și Y la 0
  4. Trageți și plasați un "DataGrid" pe panou
  5. Setați valorile X și Y la 10
  6. Setați lățimea la meetingsPanel.width-40 și înălțimea la 45%
  7. Mergeți la vizualizarea sursă și, în eticheta "mx: Appication", adăugați aspectul atributului = "vertical"

Interfața dvs. ar trebui să arate similar cu cea din imaginea de mai jos:

MXML din vizualizarea sursă ar trebui să arate astfel:

            

Citirea în fișierul XML

În următorii trei pași, vom crea o componentă HTTPService, vom citi datele din fișierul XML și vom stoca într-o variabilă locală. Acest lucru se realizează în trei etape:

Pasul 4: Creați componenta HTTPService

Treceți la vizualizarea Sursă a fișierului MXML și adăugați următorul cod chiar sub mx: Cerere etichetă:

 

Funcția httpResultHandler () va fi apelată când datele au fost preluate. Dacă apare o eroare la preluarea datelor, este apelată funcția httpFaultHandler (). Rețineți că aceasta creează numai obiectul HTTPService, datele trebuie să fie preluate printr-un apel explicit al funcției (a se vedea sub-pasul 3)

Pasul 5: httpResultHandler () și httpFaultHandler ()

Adăugați un mx: Script eticheta chiar sub mx: Cerere etichetă. În interiorul acestuia, definiți variabila care va menține datele primite și funcțiile pentru a gestiona evenimentele de la componenta HTTPService. Codul de a face acest lucru arata astfel:

 import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.collections.ArrayCollection; import mx.controls.Alert; [Bindable] publică var dataForGrid: ArrayCollection; funcția privată httpResultHandler (eveniment: ResultEvent): void dataForGrid = event.result.meetings.meeting;  funcția privată httpFaultHandler (eveniment: FaultEvent): void Alert.show ("Eroare în obținerea șirului"); 

Variabila 'dataForGrid' păstrează datele pe care le vom citi. Eticheta [Bindable] ("Bindable") vă asigură că, de fiecare dată când datele se schimbă (atunci când este citită), DataGrid este actualizat corespunzător. XML-ul este citit ca un obiect care este trecut prin evenimentul 'ResultEvent', iar 'event.result.meetings.meeting' accesează obiectele ArrayCollection din 'meeting'.

Pasul 6: Obțineți datele din fișierul XML

În acest pas, apelul funcției reale pentru a obține datele XML se face. O funcție de intializare este atribuită evenimentului care este declanșat de fiecare dată când încărcarea aplicației - evenimentul "creationComplete". Adăugați atributul creationComplete = "getData ()" la eticheta "mx: Application" și definiți funcția 'getData ()', după cum urmează (se adaugă după funcția 'httpFaultHandler'):

 funcția privată getData (): void readXML.send (); 

Acest lucru face ca obiectul HTTPService să obțină datele din fișier. Odată ce datele sunt preluate, evenimentul "rezultat" este declanșat, care apelează funcția "httpResultHandler ()". Dacă apare o problemă la obținerea datelor, se declanșează evenimentul "defecțiune", care apelează funcția httpFaultHandler ().

Pasul 7: Piatra de hotar

În acest moment, NestedDataGrid.mxml ar trebui să arate astfel:

                

Pasul 8: DataGrid cu date neinvestite

Vreau doar să subliniez pentru scurt timp motivele imobilelor care prezintă probleme în afișare, demonstrând mai întâi modul în care afișați datele neimpozitate. Spuneți, din fișierul XML de mai sus, doriți doar să afișați data, locul și prioritatea întâlnirilor (și nu informațiile prezentatoare). Codul de mai jos va putea fi afisat fara probleme (continutul fisierului "mx: Panel" aratat aici).

        

Rezultatul acestui lucru ar fi următoarea cerere:


Rețineți că atributul dataProvider al DataGrid poate fi atribuit direct ArrayCollection "dataForGrid", iar fiecare DataGridColumn în interiorul său este dat un atribut dataField care corespunde direct cu numele proprietății. Cu toate acestea, să presupunem că doriți să accesați informațiile despre numele prezentatorului, acesta poate fi accesat ca "presenter.name". Dacă încercați să dați această valoare "dataField" veți primi o eroare. Acest lucru se datorează faptului că Flex nu acceptă implicit obiecte imbricate. Citiți mai departe pentru a afla cum să rezolvați această problemă prin extinderea clasei DataGridColumn și scrierea propriului cod pentru a rezolva acest caz.

Pasul 9: Crearea clasei NestedDataGridColumn

Noi redefinim anumite funcții din clasa de coloane DataGrid pentru a ocoli problema prezentată mai sus. Mai întâi creați un director din directorul "src" numit "clase". Creați o nouă "clasă ActionScript" în acel folder, denumită "NestedDataGridColumn". În câmpul "Superclass", faceți clic pe "Răsfoiți ..." și selectați "DataGridColumn" din lista care apare. Lăsați tot restul la valorile implicite și dați clic pe "Finalizați". Un nou fișier ar fi trebuit creat și populat cu următorul cod:

 pachete clase import mx.controls.dataGridClasses.DataGridColumn; clasa publică NestedDataGridColumn extinde DataGridColumn funcția publică NestedDataGridColumn (columnName: String = null) super (columnName); 

Pasul 10: Declarația proprietății "nestedDataField"

În clasa NestedDataGridColumn, adăugați o variabilă publică bindable numită "nestedDataField". Vom folosi acest lucru în locul proprietății implicite 'dataField' pentru a transmite numele câmpului. Acest lucru este vital, deoarece dacă se utilizează proprietatea implicită "dataField", o eroare care spune Eroare: criteriile de căutare trebuie să conțină cel puțin o valoare a câmpului de sortare. va apărea când încercăm să sortăm DataGrid după ce am definit mai târziu funcția sortare personalizată.

Pasul 11: Redefinirea funcției "itemToLabel"

După cum puteți vedea, noua clasă pe care am creat-o a fost deja populată cu un constructor. Lăsați constructorul așa cum este și sub acesta adăugați următoarea funcție:

 suprascrie funcția publică itemToLabel (date: Object): String var fields: Array; var etichetă: String; var dataFieldSplit: String = nestedDataField; var currentData: Object = date; // verificați dacă valoarea nestedDataField conține o valoare '.' (adică accesează o valoare imbricată) dacă (nestedDataField.indexOf (".")! = -1) // obține toate câmpurile care trebuie să fie accesate fields = dataFieldSplit.split ("."); pentru fiecare (var f: String în câmpuri) / // bifați câmpurile unul câte unul și obțineți valoarea finală, mergând câte un câmp adânc în fiecare iterație curentData = currentData [f]; dacă (currentData este String) // returnează returul valorii finale String (currentData);  // dacă nu există nici o cuibare implicată altceva if (dataFieldSplit! = "") currentData = currentData [dataFieldSplit];  // dacă metoda noastră nu a funcționat așa cum era de așteptat, apelează la apelarea funcției implicite încercați label = currentData.toString ();  captură (e: eroare) label = super.itemToLabel (date);  // returnați eticheta returnării rezultatelor; 

Redenumirea funcției 'itemToLabel' este cheia pentru a putea accesa date imbricate în DataGrid. Funcția itemToLabel controlează ceea ce se arată în rândurile DataGrid. Deci, o folosim aici pentru a cere Flex să afișeze datele imbricate în modul pe care l-am specificat.

După cum puteți vedea, definiția funcției începe cu cuvântul cheie "suprascrie", ceea ce înseamnă că funcția predefinită prestabilită cu același nume este înlocuită în favoarea funcției pe care ați definit-o. Fiecare declarație este explicată în comentarii. Pe scurt, ceea ce face funcția este să verificați dacă sunt accesate câmpurile de date imbricate (dacă este prezentă o "."). Dacă este, obțineți fiecare nume de domeniu de date și iterați prin intermediul furnizorului de date, mergeți mai adânc la fiecare pas accesând câmpul copil.

Funcția 'itemToLabel' este numită de Flex cu un argument care conține ArrayCollection care a fost specificat ca datProvider la dataGrid. Toate atributele NestedDataGridColumn (atunci când sunt utilizate în fișierul mxml) sunt direct accesibile, iar orice proprietate publică definită în această clasă poate fi atribuită unei valori în MXML. În fișierul nostru NestedDataGrid.mxml, înlocuiți componentele "mx: DataGridColumn" cu componenta "classes: NestedDataGridColumn" și atribuiți elementele specifice pe care dorim să le afișăm în coloane la atributul "nestedDataField" (care a fost declarat în secțiunea " Fișierul NestedDataGridColumn.as "). Acum, DataGridColumn ar trebui să arate astfel:

          

Rețineți că specific direct proprietatea "nestedDataField" ca "prezenter.name" și "prezentator.fon" aici. De asemenea, am adăugat lățimi coloanelor și am setat lățimea componentei "mx: Panel" la 600 de pixeli pentru o afișare mai bună. Am adaugat ca proprietatile "de randament" sa fie false la cele doua noi coloane. Dacă eliminați acest lucru (sau îl setați la adevărat) și executați programul, coloana nu se va sorta. Vom rezolva acest lucru în pasul următor prin definirea funcției noastre de sortare proprie. Pentru moment, aplicația ar trebui să arate astfel:


Pasul 12: Scrierea funcției Custom Sort

Singurul lucru pe care l-am lăsat acum este să definiți funcția de sortare personalizată, astfel încât sortarea să fie activată și în toate câmpurile (de exemplu, doriți să sortați numele de prezentator în ordine alfabetică). Adăugați funcția numită "mySortCompareFunction" sub funcția "itemToLabel" așa cum este prezentată:

 funcția privată mySortCompareFunction (obj1: Object, obj2: Object): int var fields: Array; var dataFieldSplit: String = nestedDataField; var currentData1: Object = obj1; var actualData2: obiect = obj2; dacă (nestedDataField.indexOf (".")! = -1) fields = dataFieldSplit.split ("."); pentru fiecare (var f: String în câmpuri) currentData1 = currentData1 [f]; actualData2 = actualData2 [f];  altceva if (dataFieldSplit! = "") currentData1 = currentData1 [dataFieldSplit]; actualData2 = actualData2 [dataFieldSplit];  dacă (actualData1 este int și& currentData2 este int) var int1: int = int (actualData1); var int2: int = int (actualData2); var rezultat: int = (int1> int2) - 1: 1; rezultatul retur;  dacă (actualData1 este String && currentData2 este String) currentData1 = String (actualData1); curentData2 = String (actualData2); retur (actualData1> actualData2)? - 1: 1;  dacă (actualData1 este Data && currentData2 este data) var date1: Date = currentData1 as Date; var date2: Date = actualData2 ca dată; var dată1Timestampă: Număr = actualData1.getTime (); var data2Timestamp: Numărul = actualData2.getTime (); retur (data1Timestamp> data2Timestamp)? - 1: 1;  retur 0; 

Această funcție va fi apelată de Flex cu două obiecte și este de așteptat să se întoarcă fie -1,0 sau 1 în funcție de faptul dacă primul obiect este mai mare decât, egal sau mai mic decât cel de-al doilea obiect. Flex se ocupă de sortarea efectivă.

Această funcție utilizează aceeași logică ca și funcția 'itemToLabel' pentru a obține valoarea imbricată corespunzătoare. Apoi, în funcție de tipul valorii (indiferent dacă este int, String sau Date) o compară corespunzător și întoarce -1 dacă 'currentData1' este mai mare decât 'currentData2', 0 dacă sunt egale și 1 dacă 'currentData2 'este mai mare decât' currentData1 '.

Pasul 13: Cuplarea funcției Custom Sort

Dacă ați observat, "customSortCompareFunction" nu este o funcție predefinită în clasa DataGridColumn pe care o înlocuim. Această funcție trebuie să fie atribuită ca funcție de sortare într-un mod diferit. Trebuie să atribuim variabilei predefinite 'sortCompareFunction' numele funcției de sortare, care este 'customSortCompareFunction' în cazul nostru. Acest lucru trebuie făcut în interiorul constructorului. Constructorul arată acum astfel:

 funcția publică NestedDataGridColumn (columnName: String = null) // funcția de sortare personalizată fiind atribuită variabilei predefinite sortCompareFunction = mySortCompareFunction; super-(ColumnName); 

Odată ce acest lucru este făcut, sunteți toți pregătiți. Acum aveți o clasă personalizată care poate gestiona date imbricate arbitrar pentru a fi afișate într-un DateGrid. Și puteți sorta grila așa cum doriți.

Concluzie

Astăzi ați învățat cum să ocoliți o limitare a clasei FlexDataGrid pentru a obține date imbricate arbitrar și a le arăta într-un DateGrid. De asemenea, ați învățat cum să definiți propria funcție de sortare astfel încât grilă să rămână în ordine. Acum puteți folosi acest NestedDataGridColumn în toate aplicațiile fără nicio cheltuială.

Puteți extinde în continuare funcția 'itemToLabel' pentru a include un alt format arbitrar de acces - să zicem, accesând matricele în interiorul obiectelor copil sau accesând atributele xml. De asemenea, puteți extinde funcția de sortare pentru a sorta alte tipuri de date. De asemenea, puteți adăuga alte funcții, cum ar fi colorarea rândurilor pe baza priorității întâlnirii și afișarea mai multor detalii despre prezentator făcând clic pe un rând.

Vă mulțumim pentru lectură :)

Cod