Arbeiten mit dem Flex-DataGrid und geschachtelten Datenstrukturen

Es kommt häufig vor, dass die Daten, die in einem Flex-DataGrid angezeigt / dargestellt werden müssen, aus einer XML-Datei oder JSON mit mehr als einer Schachtelungsebene stammen. Leider können Sie mit Flex DataGrid standardmäßig nur verschachtelte Objektarrays auf einer Ebene anzeigen.

In diesem Lernprogramm wird gezeigt, wie Sie die Flex-DataGrid-Klasse erweitern können, um kompliziertere Datenstrukturen aufzunehmen. Es zeigt Ihnen auch, wie Sie alle Spalten sortierbar machen, auch wenn Sie verschachtelte Datenstrukturen verwenden.




Einführung

In diesem Lernprogramm wird davon ausgegangen, dass Sie mit den Grundlagen von Flex, der Verwendung von Flex Builder und dem Schreiben von MXML-Dateien vertraut sind. Sie sollten eine Kopie von Flex Builder auf Ihrem System installiert haben.

Schritt 1: Richten Sie das Flex-Projekt ein

Der erste Schritt besteht darin, das Projekt in Flex Builder einzurichten. Erstellen Sie ein neues Projekt in Flex Builder mit Projektname als "NestedDataGrid" und Anwendungstyp als "Webanwendung (läuft in Flash Player)". Behalten Sie alle anderen Optionen bei ihren Standardwerten und klicken Sie auf Fertig stellen.

Schritt 2: Beispieldaten importieren

Die Daten, die im DataGrid angezeigt werden, werden aus einer XML-Datei abgerufen. Erstellen Sie in Ihrem 'src' -Ordner einen Ordner mit dem Namen 'assets' und legen Sie die unten gezeigten Daten in eine Datei mit dem Namen 'meetings.xml'. Alternativ können Sie die XML-Datei von hier herunterladen und im Ordner "Assets" ablegen.

    hoch  Lisa Green [email protected] +330-7593  12. Juli 2009  Raum 405   Mittel  Christopher Martin [email protected] +330-7553  14. Juli 2009  Raum 405   hoch  George Rodriguez [email protected] +330-7502  18. Juli 2009  Raum 771   hoch  Jennifer Parker [email protected] +330-5380  20. August 2009  Raum 562  

Schritt 3: Machen Sie die Schnittstelle

In diesem Abschnitt erfahren Sie, wie Sie die Schnittstelle erstellen, um die Daten und die entsprechenden ID-Werte anzuzeigen, die für den Code in diesem Lernprogramm erforderlich sind:

  1. Öffnen Sie die Datei NestedDataGrid.mxml und wechseln Sie in die Entwurfsansicht
  2. Ziehen Sie ein 'Panel' aus der Komponentenansicht. Setzen Sie die ID auf "meetingsPanel" und den Titel auf "Meetings".
  3. Stellen Sie die Höhe und Breite des Panels auf 500 ein und setzen Sie die X- und Y-Werte auf 0
  4. Ziehen Sie ein 'DataGrid' auf das Panel
  5. Setzen Sie die X- und Y-Werte auf 10
  6. Setzen Sie die Breite auf meetingsPanel.width-40 und die Höhe auf 45%.
  7. Gehen Sie zur Quellansicht und fügen Sie im Tag 'mx: Appication' das Attribut layout = "vertical" hinzu.

Ihre Benutzeroberfläche sollte ähnlich wie in der folgenden Abbildung aussehen:

Die MXML in der Quellansicht sollte folgendermaßen aussehen:

            

Einlesen der XML-Datei

In den nächsten drei Schritten erstellen wir eine HTTPService-Komponente, lesen die Daten aus der XML-Datei und speichern sie in einer lokalen Variablen. Dies erfolgt in drei Schritten:

Schritt 4: Erstellen Sie die HTTPService-Komponente

Wechseln Sie zur Quellansicht der MXML-Datei, und fügen Sie den folgenden Code direkt unter der Datei hinzu mx: Anwendung Etikett:

 

Die Funktion httpResultHandler () wird aufgerufen, wenn die Daten abgerufen wurden. Wenn beim Abrufen der Daten ein Fehler auftritt, wird die Funktion httpFaultHandler () aufgerufen. Beachten Sie, dass dadurch nur das HTTPService-Objekt erstellt wird. Die Daten müssen von einem expliziten Funktionsaufruf abgerufen werden (siehe unter Schritt 3).

Schritt 5: httpResultHandler () und httpFaultHandler ()

Fügen Sie eine hinzu mx: Skript Tag direkt unter dem mx: Anwendung Etikett. Definieren Sie darin die Variable, in der die eingehenden Daten gespeichert werden, sowie die Funktionen zur Verarbeitung der Ereignisse aus der HTTPService-Komponente. Der Code dafür sieht so aus:

 import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.collections.ArrayCollection; import mx.controls.Alert; [Bindbar] public var dataForGrid: ArrayCollection; private Funktion httpResultHandler (event: ResultEvent): void dataForGrid = event.result.meetings.meeting;  private Funktion httpFaultHandler (Ereignis: FaultEvent): void Alert.show ("Fehler beim Abrufen der Zeichenfolge"); 

Die Variable 'dataForGrid' enthält die Daten, die eingelesen werden sollen. Das '[Bindable]' - Tag stellt sicher, dass das DataGrid bei jeder Änderung der Daten (beim Einlesen) entsprechend aktualisiert wird. Das XML wird als ein Objekt eingelesen, das über das Ereignis 'ResultEvent' übergeben wird, und 'event.result.meetings.meeting' greift auf die ArrayCollection von 'meeting'-Objekten zu.

Schritt 6: Holen Sie die Daten aus der XML-Datei

In diesem Schritt wird der eigentliche Funktionsaufruf zum Abrufen der XML-Daten ausgeführt. Dem Ereignis wird eine Initialisierungsfunktion zugewiesen, die jedes Mal ausgelöst wird, wenn die Anwendung geladen wird - das Ereignis 'creationComplete'. Fügen Sie das Attribut hinzu creationComplete = "getData ()" zu dem Tag 'mx: Application' und definieren Sie die Funktion 'getData ()' wie folgt (wird nach der 'httpFaultHandler'-Funktion hinzugefügt):

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

Dadurch erhält das HTTPService-Objekt die Daten aus der Datei. Sobald die Daten abgerufen werden, wird das Ereignis 'result' ausgelöst, das die Funktion 'httpResultHandler ()' aufruft. Wenn beim Abrufen der Daten ein Problem auftritt, wird das Ereignis 'fault' ausgelöst, das die Funktion httpFaultHandler () aufruft.

Schritt 7: Meilenstein

An diesem Punkt sollte Ihre NestedDataGrid.mxml so aussehen:

                

Schritt 8: DataGrid mit nicht geschachtelten Daten

Ich möchte nur kurz aufzeigen, warum geschachtelte Daten Probleme bei der Anzeige verursachen, indem ich zuerst demonstriere, wie Sie nicht geschachtelte Daten anzeigen. Angenommen, Sie wollten in der obigen XML-Datei nur Datum, Ort und Priorität der Besprechungen anzeigen (und nicht die Informationen des Moderators). Mit dem folgenden Code können Sie ihn ohne Probleme anzeigen (Inhalt von 'mx: Panel' wird hier angezeigt. Alle anderen Codes sind gleich):

        

Das Ergebnis davon wäre die folgende Anwendung:


Beachten Sie, dass das dataProvider-Attribut des DataGrid direkt der ArrayCollection 'dataForGrid' zugewiesen werden kann, und dass jede DataGridColumn-Instanz ein dataField-Attribut erhält, das direkt dem Eigenschaftennamen entspricht. Wenn Sie jedoch auf die Informationen zum Namen des Präsentators zugreifen möchten, können Sie als "presenter.name" darauf zugreifen. Wenn Sie versuchen, diesen Wert an 'dataField' zu übergeben, wird eine Fehlermeldung angezeigt. Dies liegt daran, dass Flex standardmäßig keine verschachtelten Objekte unterstützt. Lesen Sie weiter, um zu erfahren, wie Sie dieses Problem lösen können, indem Sie die DataGridColumn-Klasse erweitern und eigenen Code schreiben, um diesen Fall zu behandeln.

Schritt 9: Erstellen der NestedDataGridColumn-Klasse

Wir haben einige Funktionen in der DataGrid-Spaltenklasse neu definiert, um das oben beschriebene Problem zu umgehen. Erstellen Sie zuerst einen Ordner im 'src'-Verzeichnis mit dem Namen' classes '. Erstellen Sie in diesem Ordner eine neue "ActionScript-Klasse" mit dem Namen "NestedDataGridColumn". Klicken Sie im Feld "Superklasse" auf "Durchsuchen ..." und wählen Sie "DataGridColumn" aus der angezeigten Liste aus. Behalten Sie die Standardwerte bei und klicken Sie auf "Fertig stellen". Eine neue Datei sollte erstellt und mit dem folgenden Code gefüllt werden:

 Paketklassen import mx.controls.dataGridClasses.DataGridColumn; public class NestedDataGridColumn erweitert DataGridColumn public function NestedDataGridColumn (columnName: String = null) super (columnName); 

Schritt 10: Deklaration der 'nestedDataField'-Eigenschaft

Fügen Sie in der NestedDataGridColumn-Klasse eine öffentliche bindbare Variable mit dem Namen 'nestedDataField' hinzu. Wir verwenden dies anstelle der Standardeigenschaft 'dataField', um den Feldnamen zu übergeben. Dies ist wichtig, da bei Verwendung der Standardeigenschaft 'dataField' eine Fehlermeldung angezeigt wird Fehler: Suchkriterien müssen mindestens einen Sortierfeldwert enthalten. tritt auf, wenn wir versuchen, das DataGrid zu sortieren, nachdem die benutzerdefinierte Sortierfunktion später definiert wurde.

Schritt 11: Die Funktion 'itemToLabel' neu definieren

Wie Sie sehen, wurde die neue Klasse, die wir erstellt haben, bereits mit einem Konstruktor gefüllt. Lassen Sie den Konstruktor so wie er ist und fügen Sie darunter die folgende Funktion hinzu:

 Überschreiben Sie die öffentliche Funktion itemToLabel (data: Object): String var fields: Array; var label: String; var dataFieldSplit: String = nestedDataField; var currentData: Object = Daten; // Prüfen Sie, ob der NestedDataField-Wert ein '.' enthält. (d. h. greift auf einen verschachtelten Wert zu) if (nestedDataField.indexOf (".")! = -1) // Alle Felder abrufen, auf die zugegriffen werden muss fields = dataFieldSplit.split ("."); für jedes (var f: String in Feldern) // Durchlaufen Sie die Felder nacheinander und erhalten Sie den endgültigen Wert. Gehen Sie dabei bei jeder Iteration ein Feld tief currentData = currentData [f]; if (currentData ist String) // den letzten Wert zurückgeben return String (currentData);  // Wenn keine Verschachtelung beteiligt ist else if (dataFieldSplit! = "") currentData = currentData [dataFieldSplit];  // Wenn unsere Methode nicht wie erwartet funktioniert hat, rufen Sie die Standardfunktion auf. try label = currentData.toString ();  catch (e: Error) label = super.itemToLabel (Daten);  // Gibt das Ergebnis zurück. 

Die Neudefinition der 'itemToLabel'-Funktion ist der Schlüssel, um auf verschachtelte Daten in Ihrem DataGrid zugreifen zu können. Die itemToLabel-Funktion steuert, was in den DataGrid-Zeilen angezeigt wird. Daher verwenden wir es hier, um Flex aufzufordern, die verschachtelten Daten in der von uns angegebenen Weise anzuzeigen.

Wie Sie sehen, beginnt die Funktionsdefinition mit dem Schlüsselwort 'override'. Dies bedeutet, dass die vordefinierte Standardfunktion mit demselben Namen zugunsten der von Ihnen definierten Funktion überschrieben wird. Jede Aussage wird in den Kommentaren erklärt. Kurz gesagt, die Funktion prüft, ob auf verschachtelte Datenfelder zugegriffen wird (wenn ein '.' Vorhanden ist). Wenn dies der Fall ist, rufen Sie jeden Datenfeldnamen ab und iterieren Sie durch den dataProvider. Gehen Sie jeden Schritt tiefer durch, indem Sie auf das untergeordnete Feld zugreifen.

Die Funktion 'itemToLabel' wird von Flex mit einem Argument aufgerufen, das die ArrayCollection enthält, die als dataProvider für das dataGrid angegeben wurde. Auf alle Attribute der NestedDataGridColumn (wenn sie in der mxml-Datei verwendet werden) kann direkt zugegriffen werden, und allen in dieser Klasse definierten öffentlichen Eigenschaften kann in der MXML ein Wert zugewiesen werden. In unserer Datei NestedDataGrid.mxml ersetzen wir die Komponenten 'mx: DataGridColumn' durch die Komponente 'classes: NestedDataGridColumn' und weisen die spezifischen Elemente, die in den Spalten angezeigt werden sollen, dem 'nestedDataField'-Attribut zu (das in der deklariert wurde.) NestedDataGridColumn.as 'Datei). Die DataGridColumn sollte jetzt so aussehen:

          

Beachten Sie, dass ich die 'nestedDataField'-Eigenschaft hier direkt als "presenter.name" und "presenter.phone" angegeben habe. Außerdem habe ich den Spalten Breiten hinzugefügt und die Breite der 'mx: Panel'-Komponente zur besseren Darstellung auf 600px gesetzt. Ich habe die sortable -Eigenschaft den beiden neuen Spalten hinzugefügt, um false zu sein. Wenn Sie dies entfernen (oder auf true setzen) und das Programm ausführen, wird die Spalte nicht sortiert. Wir lösen das im nächsten Schritt, indem wir unsere eigene Sortierfunktion definieren. Für den Moment sollte die Anwendung so aussehen:


Schritt 12: Schreiben der benutzerdefinierten Sortierfunktion

Jetzt müssen Sie nur noch die benutzerdefinierte Sortierfunktion definieren, sodass die Sortierung auch in allen Feldern aktiviert wird (Sie möchten beispielsweise die Namen der Moderatoren alphabetisch sortieren). Fügen Sie die Funktion 'mySortCompareFunction' wie angegeben unter der Funktion 'itemToLabel' hinzu:

 private Funktion 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 ("."); für jedes (var f: String in Feldern) currentData1 = currentData1 [f]; currentData2 = currentData2 [f];  else if (dataFieldSplit! = "") currentData1 = currentData1 [dataFieldSplit]; currentData2 = currentData2 [dataFieldSplit];  if (currentData1 ist int && currentData2 ist int) var int1: int = int (currentData1); var int2: int = int (aktuelleDaten2); var Ergebnis: int = (int1> int2)? - 1: 1; Ergebnis zurückgeben;  if (currentData1 ist String && currentData2 ist String) currentData1 = String (currentData1); currentData2 = String (currentData2); return (currentData1> currentData2)? - 1: 1;  if (currentData1 ist Datum && currentData2 ist Datum) var date1: Date = currentData1 as Date; var date2: Date = currentData2 als Datum; var date1Timestamp: Number = currentData1.getTime (); var date2Timestamp: Number = currentData2.getTime (); return (date1Timestamp> date2Timestamp)? - 1: 1;  return 0; 

Diese Funktion wird von Flex mit zwei Objekten aufgerufen, und es wird erwartet, dass entweder -1.0 oder 1 zurückgegeben wird, je nachdem, ob das erste Objekt größer als das zweite Objekt ist oder diesem entspricht oder darunter. Flex kümmert sich um die eigentliche Sortierung.

Diese Funktion verwendet dieselbe Logik wie die Funktion 'itemToLabel', um den entsprechenden verschachtelten Wert abzurufen. Abhängig von der Art des Werts (ob int, String oder Date) vergleicht er den Wert entsprechend und gibt -1 zurück, wenn 'currentData1' größer ist als 'currentData2', 0, wenn sie gleich sind, und 1, wenn 'currentData2 'ist größer als' currentData1 '.

Schritt 13: Anschließen der benutzerdefinierten Sortierfunktion

Wenn Sie bemerkt haben, dass 'customSortCompareFunction' keine vordefinierte Funktion in der Klasse DataGridColumn ist, die wir überschreiben. Diese Funktion muss auf andere Weise als Sortierfunktion zugewiesen werden. Der vordefinierten Variablen 'sortCompareFunction' muss der Name der Sortierfunktion zugewiesen werden, in unserem Fall 'customSortCompareFunction'. Dies sollte innerhalb des Konstruktors erfolgen. Der Konstruktor sieht jetzt so aus:

 public function NestedDataGridColumn (columnName: String = null) // die benutzerdefinierte Sortierfunktion, die der vordefinierten Variablen zugewiesen wird sortCompareFunction = mySortCompareFunction; super (Spaltenname); 

Sobald dies erledigt ist, sind Sie fertig. Sie haben jetzt eine benutzerdefinierte Klasse, die beliebig verschachtelte Daten zur Anzeige in einem DataGrid verarbeiten kann. Und Sie können das Raster beliebig sortieren.

Fazit

Heute haben Sie gelernt, wie Sie eine Einschränkung der FlexDataGrid-Klasse umgehen, um beliebig verschachtelte Daten zu erhalten und sie in einem DataGrid anzuzeigen. Sie haben auch gelernt, wie Sie Ihre eigene Sortierfunktion definieren, damit das Raster sortierbar bleibt. Sie können diese NestedDataGridColumn jetzt in allen Ihren Anwendungen ohne zusätzlichen Aufwand verwenden.

Sie können die 'itemToLabel'-Funktion um ein beliebiges anderes Zugriffsformat erweitern, z. B. den Zugriff auf Arrays in den untergeordneten Objekten oder den Zugriff auf XML-Attribute. Sie können die Sortierfunktion auch erweitern, um andere Datentypen zu sortieren. Sie können möglicherweise weitere Funktionen hinzufügen, z. B. das Einfärben der Zeilen basierend auf der Besprechungspriorität und das Anzeigen weiterer Details zum Moderator, indem Sie auf eine Zeile klicken.

Danke fürs Lesen :)