Praca z dostawcą danych

Dostawca danych to źródło danych dla składników ComboBox, DataGrid, List i TileList. Każda z tych klas składników ma właściwość dataProvider , do której można przypisać obiekt DataProvider w celu wypełnienia komórek składnika danymi. Zazwyczaj dostawca danych jest kolekcją danych, np. obiektem Array lub XML.

Tworzenie dostawcy danych

Dostawcę danych dla składników ComboBox, List i TileList można utworzyć, korzystając z parametru dataProvider w środowisku tworzenia treści. Składnik DataGrid nie udostępnia parametru dataProvider w Inspektorze właściwości, ponieważ może mieć kilka kolumn i jego dostawca danych jest odpowiednio bardziej skomplikowany. Obiekty dostawców danych dla powyższych składników oraz dla składnika DataGrid można tworzyć także za pomocą kodu ActionScript.

Korzystanie z parametru dataProvider

Prosty obiekt dostawcy danych dla składników ComboBox, List i TileList można utworzyć, klikając parametr dataProvider na karcie Parametry w Inspektorze właściwości lub Inspektorze składników.

Dwukrotne kliknięcie wartości w komórce, która początkowo zawiera pustą tabelę, spowoduje otwarcie okna dialogowego Wartości umożliwiającego utworzenie dostawcy danych poprzez wprowadzenie wielu wartości etykiet i danych.

Okno dialogowe Wartości dostawcy danych

Klikając znak plus, można dodać element do dostawcy danych. Kliknięcie znaku minus powoduje usunięcie elementu. Kliknięcie strzałki w górę powoduje przeniesienie zaznaczonego elementu bliżej początku listy, a kliknięcie strzałki w dół — bliżej końca listy. Na poniższej ilustracji przedstawiono okno dialogowe Wartości, w którym tworzona jest lista imion dzieci oraz ich dat urodzenia.

Okno dialogowe Wartości z danymi

Utworzona tablica (obiekt Array) zawiera pary pól etykiet i wartości. Pola etykiet to label i data , natomiast pola wartości to imiona i daty urodzenia dzieci. Pole etykiety identyfikuje zawartość komórek wyświetlaną na liście, czyli w tym przypadku imiona dzieci. Wynikowy składnik ComboBox wygląda następująco:

Składnik ComboBox wypełniony przez dostawcę danych

Po zakończeniu dodawania danych należy kliknąć przycisk OK, aby zamknąć okno dialogowe. Tablica w parametrze dataProvider jest teraz wypełniona elementami utworzonymi przez użytkownika.

Parametr dataProvider z danymi

Dostęp do utworzonych wartości etykiet i danych można uzyskać w języku ActionScript za pośrednictwem właściwości dataProvider składnika.

Tworzenie dostawcy danych przy użyciu kodu ActionScript

Dostawcę danych można utworzyć, tworząc dane w obiekcie Array lub XML i przekazując ten obiekt jako parametr value do konstruktora obiektu DataProvider.

Uwaga: W języku ActionScript 3.0 nie jest możliwe bezpośrednie przypisanie obiektu Array lub XML do właściwości dataProvider, ponieważ właściwość jest zdefiniowana jako obiekt typu DataProvider i można jej przypisywać tylko obiekty tego typu.

W poniższym przykładzie składnik List, będący pojedynczą kolumną wierszy, jest wypełniany imionami i datami urodzin kilkorga dzieci. W przykładowym kodzie lista jest definiowana w tablicy items i przekazywana jako parametr podczas tworzenia instancji obiektu DataProvider ( new DataProvider(items) ); następnie instancja ta jest przypisywana właściwości dataProvider składnika List.

import fl.controls.List; 
import fl.data.DataProvider; 
 
var aList:List = new List(); 
var items:Array = [ 
{label:"David", data:"11/19/1995"}, 
{label:"Colleen", data:"4/20/1993"}, 
{label:"Sharon", data:"9/06/1997"}, 
{label:"Ronnie", data:"7/6/1993"}, 
{label:"James", data:"2/15/1994"}, 
]; 
aList.dataProvider = new DataProvider(items); 
addChild(aList); 
aList.move(150,150);

Obiekt Array składa się z par pól etykiet i wartości. Pola etykiet to label i data , natomiast pola wartości to imiona i daty urodzenia dzieci. Pole etykiety identyfikuje zawartość komórek wyświetlaną na liście, czyli w tym przypadku imiona dzieci. Wynikowy składnik List wygląda tak:

Lista wypełniona przez dostawcę danych

Wartość pola danych jest dostępna, gdy użytkownik wybierze element na liście, klikając go i wywołując tym samym zdarzenie change . W poniższym przykładzie do poprzedniego przykładowego kodu dodano składnik TextArea ( aTa ) oraz funkcję obsługi zdarzeń ( changeHandler ), które wyświetlają datę urodzin dziecka, gdy użytkownik wybierze imię na liście.

import fl.controls.List; 
import fl.controls.TextArea; 
import flash.events.Event; 
import fl.data.DataProvider; 
 
var aList:List = new List(); 
var aTa:TextArea = new TextArea(); 
var items:Array = [ 
{label:"David", data:"1/19/1995"}, 
{label:"Colleen", data:"4/20/1993"}, 
{label:"Sharon", data:"9/06/1994"}, 
{label:"Ronnie", data:"7/6/1993"}, 
{label:"James", data:"2/15/1994"}, 
]; 
aList.dataProvider = new DataProvider(items); 
 
addChild(aList); 
addChild(aTa); 
 
aList.move(150,150); 
aTa.move(150, 260); 
 
aList.addEventListener(Event.CHANGE, changeHandler); 
 
function changeHandler(event:Event):void { 
    aTa.text = event.target.selectedItem.data; 
};

Teraz, gdy użytkownik wybierze imię dziecka na liście, w obszarze tekstowym pojawi się data urodzin dziecka, tak jak przedstawiono to na poniższej ilustracji. Zadanie to realizuje funkcja changeHandler() , gdy przypisuje właściwości text składnika TextArea ( aTa.text ) wartość elementu danych ( event.target.selectedItem.data ). Właściwość event.target to obiekt, który wywołał zdarzenie, czyli w tym przypadku obiekt List.

Wyświetlanie pola danych z dostawcy danych składnika List

Dostawca danych może zawierać dane inne niż tekst. W poniższym przykładzie obiekt DataProvider, dostarczający danych dla składnika TitleList, zawiera klipy filmowe. Kod buduje obiekt DataProvider, wywołując metodę addItem() w celu dodania kolejnego elementu po utworzeniu każdego kolejnego obiektu MovieClip (kolorowego prostokąta).

import fl.data.DataProvider; 
import flash.display.DisplayObject; 
 
var aBox:MovieClip = new MovieClip(); 
var i:uint = 0; 
var colors:Array = new Array(0x00000, 0xFF0000, 0x0000CC, 0x00CC00, 0xFFFF00); 
var colorNames:Array = new Array("Midnight", "Cranberry", "Sky", "Forest", "July"); 
var dp:DataProvider = new DataProvider(); 
for(i=0; i < colors.length; i++) { 
    drawBox(aBox, colors[i]);    // draw box w next color in array 
    dp.addItem( {label:colorNames[i], source:aBox} ); 
} 
aTl.dataProvider = dp; 
aTl.columnWidth = 110; 
aTl.rowHeight = 130; 
aTl.setSize(280,150); 
aTl.move(150, 150); 
aTl.setStyle("contentPadding", 5); 
 
function drawBox(box:MovieClip,color:uint):void { 
            box.graphics.beginFill(color, 1.0); 
            box.graphics.drawRect(0, 0, 100, 100); 
            box.graphics.endFill();        

Obiekt DataProvider można również zapełnić danymi XML (a nie tablicą). Poniższy przykładowy kod zapisuje dane w obiekcie XML o nazwie employeesXML , a następnie przekazuje ten obiekt jako parametr value do funkcji-konstruktora DataProvider() :

import fl.controls.DataGrid; 
import fl.data.DataProvider; 
 
var aDg:DataGrid = new DataGrid(); 
addChild(aDg); 
 
var employeesXML:XML =  
    <employees> 
        <employee Name="Edna" ID="22" /> 
        <employee Name="Stu" ID="23" /> 
    </employees>; 
 
var myDP:DataProvider = new DataProvider(employeesXML); 
 
aDg.columns = ["Name", "ID"]; 
aDg.dataProvider = myDP;

Dane mogą być zapisane jako atrybuty XML (tak jak w poprzednim przykładzie) lub jako właściwości XML, co ilustruje poniższy przykład:

var employeesXML:XML =  
    <employees> 
        <employee> 
            <Name>Edna</Name> 
            <ID>22</ID> 
        </employee> 
        <employee> 
            <Name>Stu</Name> 
            <ID>23</ID> 
        </employee> 
    </employees>;

Obiekt DataProvider ma także zestaw metod i właściwości umożliwiających dostęp do niego i manipulowanie nim. Interfejs API dostawcy danych umożliwia dodawanie, usuwanie, zastępowanie, sortowanie i scalanie elementów w obiekcie DataProvider.

Manipulowanie dostawcą danych

Istnieje możliwość dodawania elementów do obiektu DataProvider za pomocą metod addItem() i addItemAt() . W poniższym przykładzie dodawane są elementy wprowadzane przez użytkownika w polu tekstowym edytowalnego składnika ComboBox. Przyjęto, że składnik ComboBox został już przeciągnięty na stół montażowy i że nadano mu nazwę instancji aCb .

import fl.data.DataProvider; 
import fl.events.ComponentEvent; 
 
var items:Array = [ 
{label:"Roger"}, 
{label:"Carolyn"}, 
{label:"Darrell"}, 
{label:"Rebecca"}, 
{label:"Natalie"}, 
{label:"Mitchell"}, 
]; 
aCb.dataProvider = new DataProvider(items); 
     
aCb.addEventListener(ComponentEvent.ENTER, newItemHandler); 
 
function newItemHandler(event:ComponentEvent):void { 
    var newRow:int = event.target.length + 1; 
        event.target.addItemAt({label:event.target.selectedLabel}, 
        event.target.length); 
}

Możliwe jest także zastępowanie i usuwanie elementów w składniku za pośrednictwem jego dostawcy danych. W poniższym przykładzie zaimplementowano dwa odrębne składniki List, listA i listB , oraz udostępniono składnik Button z etykietą Sync. Gdy użytkownik kliknie przycisk (składnik Button), wywoływana jest metoda replaceItemAt() zastępująca elementy listy listB elementami listy listA . Jeśli lista listA jest dłuższa niż listB , wywoływana jest metoda addItem() w celu dodania dodatkowych elementów do listy listB . Jeśli lista listB jest dłuższa niż listA , wywoływana jest metoda removeItemAt() w celu usunięcia nadmiarowych elementów z listy ListB .

// Requires the List and Button components to be in the library 
 
import fl.controls.List; 
import fl.controls.Button; 
import flash.events.Event; 
import fl.data.DataProvider; 
 
var listA:List = new List(); 
var listB:List = new List(); 
var syncButton:Button = new Button(); 
syncButton.label = "Sync"; 
 
var itemsA:Array = [ 
{label:"David"}, 
{label:"Colleen"}, 
{label:"Sharon"}, 
{label:"Ronnie"}, 
{label:"James"}, 
]; 
var itemsB:Array = [ 
{label:"Roger"}, 
{label:"Carolyn"}, 
{label:"Darrell"}, 
{label:"Rebecca"}, 
{label:"Natalie"}, 
{label:"Mitchell"}, 
]; 
listA.dataProvider = new DataProvider(itemsA); 
listB.dataProvider = new DataProvider(itemsB); 
 
addChild(listA); 
addChild(listB); 
addChild(syncButton); 
 
listA.move(100, 100); 
listB.move(250, 100); 
syncButton.move(175, 220); 
 
syncButton.addEventListener(MouseEvent.CLICK, syncHandler); 
 
function syncHandler(event:MouseEvent):void { 
    var i:uint = 0; 
    if(listA.length > listB.length) {     //if listA is longer, add items to B 
        while(i < listB.length) { 
            listB.dataProvider.replaceItemAt(listA.dataProvider.getItemAt(i), i); 
            ++i; 
        } 
        while(i < listA.length) { 
            listB.dataProvider.addItem(listA.dataProvider.getItemAt(i++)); 
        } 
    } else if(listA.length == listB.length) { //if listA and listB are equal length 
        while(i < listB.length) { 
            listB.dataProvider.replaceItemAt(listA.dataProvider.getItemAt(i), i); 
            ++i; 
        } 
    } else {                //if listB is longer, remove extra items from B 
        while(i < listA.length) { 
            listB.dataProvider.replaceItemAt(listA.dataProvider.getItemAt(i), i); 
            ++i; 
        } 
        while(i < listB.length) { 
            listB.dataProvider.removeItemAt(i++); 
        } 
    } 
}

Metody merge() , sort() i sortOn() obiektu DataProvider umożliwiają scalanie i sortowanie dostawców danych. W poniższym przykładzie dwie instancje klasy DataGrid ( aDg i bDg ) wypełniane są niepełnymi składami drużyn softballowych. Dodawany jest składnik Button z etykietą Merge (Scal), a gdy użytkownik kliknie ten składnik, funkcja obsługi zdarzenia ( mrgHandler ) scala skład bDg ze składem aDg i sortuje wynikowy składnik DataGrid według zawartości kolumny Name.

import fl.data.DataProvider; 
import fl.controls.DataGrid; 
import fl.controls.Button; 
 
var aDg:DataGrid = new DataGrid(); 
var bDg:DataGrid = new DataGrid(); 
var mrgButton:Button = new Button(); 
addChild(aDg); 
addChild(bDg); 
addChild(mrgButton); 
bldRosterGrid(aDg); 
bldRosterGrid(bDg); 
var aRoster:Array = new Array(); 
var bRoster:Array = new Array(); 
aRoster = [ 
        {Name:"Wilma Carter", Bats:"R", Throws:"R", Year:"So", Home: "Redlands, CA"},  
        {Name:"Sue Pennypacker", Bats:"L", Throws:"R", Year:"Fr", Home: "Athens, GA"}, 
        {Name:"Jill Smithfield", Bats:"R", Throws:"L", Year:"Sr", Home: "Spokane, WA"}, 
        {Name:"Shirley Goth", Bats:"R", Throws:"R", Year:"Sr", Home: "Carson, NV"} 
]; 
bRoster = [ 
        {Name:"Angelina Davis", Bats:"R", Throws:"R", Year:"So", Home: "Odessa, TX"}, 
        {Name:"Maria Santiago", Bats:"L", Throws:"L", Year:"Sr", Home: "Tacoma, WA"}, 
        {Name:"Debbie Ferguson", Bats:"R", Throws:"R", Year: "Jr", Home: "Bend, OR"} 
]; 
aDg.dataProvider = new DataProvider(aRoster); 
bDg.dataProvider = new DataProvider(bRoster); 
aDg.move(50,50); 
aDg.rowCount = aDg.length; 
bDg.move(50,200); 
bDg.rowCount = bDg.length; 
mrgButton.label = "Merge"; 
mrgButton.move(200, 315); 
mrgButton.addEventListener(MouseEvent.CLICK, mrgHandler); 
 
function bldRosterGrid(dg:DataGrid){ 
    dg.setSize(400, 300); 
    dg.columns = ["Name", "Bats", "Throws", "Year", "Home"]; 
    dg.columns[0].width = 120; 
    dg.columns[1].width = 50; 
    dg.columns[2].width = 50; 
    dg.columns[3].width = 40; 
    dg.columns[4].width = 120; 
}; 
 
function mrgHandler(event:MouseEvent):void { 
    aDg.dataProvider.merge(bDg.dataProvider); 
    aDg.dataProvider.sortOn("Name"); 
}

Więcej informacji zawiera opis klasy DataProvider w dokumentacji języka ActionScript 3.0 .