Anda di halaman 1dari 51

ASP.NET AJAX Server Controls.

Zaawansowane programowanie
w nurcie .NET Framework 3.5.
Microsoft .NET Development Series
Autor: Adam Calderon, Joel Rumerman
Tumaczenie: Mikoaj Szczepaniak
ISBN: 978-83-246-2089-0
Tytu oryginau: Advanced ASP.NET
AJAX Server Controls For .NET Framework 3.5
Format: 168x237, stron: 584
Poznaj najlepsze techniki implementowania wasnych kontrolek
serwera frameworka ASP.NET
Jak skonstruowa niezalene od przegldarek skrypty JavaScript?
Jak zbudowa wasne, niestandardowe usugi aplikacji?
Jak zarzdza relacjami komponentw z elementami modelu DOM?
Kontrolki serwera pozwalaj umieszcza dane dotyczce wygldu przegldarki
i funkcjonalnoci serwera w spjnych obiektach wielokrotnego uytku. Mona je
stosowa nie tylko na wielu stronach tej samej aplikacji szkieletu ASP.NET, ale take
w wielu rnych aplikacjach tego frameworka. Oferuje on mnstwo gotowych, zarwno
wyjtkowo prostych, jak i zoonych kontrolek serwera. Co wicej z jego pomoc
mona rwnie tworzy wasne kontrolki, posiadajce funkcjonalnoci, ktrych
nie zaimplementowano w kontrolkach ju istniejcych. Jak wykorzysta ten potencja
ASP.NET?
Ksika ASP.NET AJAX Server Controls. Zaawansowane programowanie w nurcie
.NET Framework 3.5 zawiera szczegowe wyjanienia i instrukcje, jak korzysta
z frameworka ASP.NET AJAX w procesie tworzenia kontrolek serwera, obejmujcych
funkcjonalno frameworka AJAX. Dziki temu podrcznikowi poznasz wewntrzne
mechanizmy i moliwoci rozszerzania frameworka ASP.NET AJAX. Nauczysz si
konstruowa interaktywne kontrolki przy uyciu elementw zestawu narzdzi AJAX
Control Toolkit oraz budowa wasne, niestandardowe usugi aplikacji.
Programowanie w jzyku JavaScript
Obsuga bdw
acuchy, zmienne i argumenty funkcji
Programowanie biblioteki Microsoft AJAX Library
Dziedziczenie i implementacja interfejsu
Typy wyliczeniowe
Kontrolki
Obiekt Sys. Application
Dodawanie funkcji klienckich do kontrolek serwera
Lokalizacja we frameworku ASP.NET AJAX
Wytwarzanie kontrolek w rodowisku czciowej komunikacji zwrotnej
Usugi aplikacji
Architektura strony klienckiej i architektura serwera
Nie ograniczaj si twrz i dodawaj wasne funkcjonalnoci AJAX do kontrolek serwera!

Spis treci
Sowo wstpne

13

Przedmowa

15

Podzikowania

23

O autorach

27

KOD KLIENTA

Programowanie w jzyku JavaScript


Oglnie o jzyku JavaScript
Wprowadzenie do JavaScriptu
Atrybuty jzyka JavaScript
Proste typy danych

31
32
32
32
34

acuchy
Obiekty
Zmienne i argumenty funkcji
Obsuga bdw
Opnianie wykonywania kodu za pomoc limitw i przedziaw czasowych

35
36
43
51
56

Programowanie obiektowe w jzyku JavaScript


Abstrakcyjne typy danych
Dziedziczenie

64
65
71

Podsumowanie

75

Programowanie biblioteki Microsoft AJAX Library


Rozszerzanie wbudowanych typw jzyka JavaScript

77
78

Wartoci logiczne
Daty i liczby

78
79

Spis treci
acuchy
Tablice

79
80

Rozszerzanie biblioteki Microsoft AJAX Library


Klasy
Interfejsy
Typy wyliczeniowe
Dziedziczenie i implementacja interfejsu

85
85
92
96
101

Wane nowe typy


Typ Sys.EventHandlerList
Typ Sys.StringBuilder
Obiekt Sys.Debug
Typ Sys.UI.DomElement
Typ Sys.UI.DomEvent

111
111
117
118
123
128

Zarzdzanie zasigiem
Delegacje
Wywoania zwrotne

133
134
135

Podsumowanie

137

II

KONTROLKI

Komponenty
Definicja komponentw

141
141

Komponenty, kontrolki i zachowania

142

Typ Sys.Component
Definiowanie nowych komponentw
Tworzenie komponentw
Podsumowanie wiedzy o komponentach

144
148
153
168

Kontrolki
Nowe pojcia
Definiowanie nowej kontrolki
Tworzenie kontrolki
Podsumowanie wiedzy o kontrolkach

168
170
172
174
175

Zachowania
Definiowanie zachowania
Tworzenie zachowania
Podsumowanie wiedzy o zachowaniach

175
177
178
183

Podsumowanie

183

Spis treci
4

Obiekt Sys.Application
Informacje podstawowe
Tworzenie obiektu Sys.Application
Informacje o typie
Informacje o metodach

7
185
185
185
187
188

Meneder komponentw
Dodawanie komponentu
Odnajdywanie komponentu
Usuwanie komponentu
Uzyskiwanie komponentw

190
191
194
197
198

Procedura inicjalizacji
Proces tworzenia komponentw
Zdarzenie load

198
202
211

Procedura zwalniania
Metoda Sys.Application.dispose

215
216

Podsumowanie

218

Dodawanie funkcji klienckich do kontrolek serwera


Architektura generowania skryptw
Generowanie skryptw zachowa i kontrolek
Zasoby skryptu
Kontrolka ScriptManager

Dodawanie zachowania klienta z wykorzystaniem klasy ExtenderControl


Wprowadzenie do klasy ExtenderControl
Tworzenie kontrolki rozszerzajcej

219
220
220
225
228

230
231
231

Dodawanie funkcjonalnoci klienta z wykorzystaniem klasy ScriptControl 242


Przegld klasy ScriptControl
243
Tworzenie kontrolki skryptu
245
Dodawanie funkcjonalnoci klienta do kontrolek kompozytowych
z wykorzystaniem interfejsu IScriptControl
Przegld kontrolek kompozytowych
Interfejs IScriptControl
Tworzenie kontrolki kompozytowej

254
254
256
257

Podsumowanie

261

Spis treci
6

Lokalizacja we frameworku ASP.NET AJAX


Lokalizacja we frameworku ASP.NET
Okrelenie, ktre elementy wymagaj lokalizacji
Przystosowanie aplikacji do regu okrelonej kultury
Lokalizacja wywietlanych wartoci

263
263
265
269
274

Lokalizacja we frameworku ASP.NET AJAX


Mechanizmy lokalizacyjne jzyka JavaScript
Mechanizmy lokalizacyjne ASP.NET AJAX

283
284
287

Podsumowanie

320

Wytwarzanie kontrolek
w rodowisku czciowej komunikacji zwrotnej
Dziaanie kontrolki UpdatePanel
Wpyw czciowej komunikacji zwrotnej na komponenty klienckie

321
322
327

Automatyczne zwalnianie zachowa i kontrolek


Automatyczne zwalnianie komponentw
Rczne zwalnianie komponentw, kontrolek lub zachowa

332
340
343

adowanie wyrae i plikw jzyka JavaScript


Metody rejestrowania skryptw w kontrolce ScriptManager
Metoda Sys.Application.notifyScriptLoaded()

357
357
363

Zdarzenia obiektu Sys.Application


Zdarzenie init
Zdarzenie load

365
365
366

Podsumowanie

368

III

KOMUNIKACJA

Architektura komunikacji frameworku ASP.NET AJAX


Nowy model komunikacji
Architektura komunikacji frameworku ASP.NET AJAX 2.0 Extensions
Usugi sieciowe
Metody stron
Serializacja
Komponenty frameworku stosowane po stronie serwera

Architektura komunikacji biblioteki Microsoft AJAX Library


Usugi poredniczce
Serializacja

371
372
374
375
385
386
391

398
398
411

Spis treci
Klasa WebRequest
Komponenty rdzenia dania sieciowego

Podsumowanie

Usugi aplikacji
Usugi czonkostwa, rl i profilw uytkownikw frameworku ASP.NET 2.0
Uwierzytelnianie formularzy
ASP.NET 2.0 Provider Model
Narzdzie Web Site Administration Tool
Czonkostwo
Role
Profile

9
412
417

419

421
421
422
425
427
427
432
438

Usugi aplikacji frameworku ASP.NET AJAX


Usuga uwierzytelniania
Usuga rl
Usuga profilw

441
441
446
448

Niestandardowe usugi aplikacji


Klasa ServiceHandlerFactory protokou HTTP i klasy pomocnicze
Porednik w dostpie do usugi
Konfiguracja

451
454
463
467

Podsumowanie

468

IV

ZESTAW NARZDZI AJAX CONTROL TOOLKIT

10

Architektura zestawu narzdzi ASP.NET AJAX Control Toolkit


Przegld zestawu narzdzi ASP.NET AJAX Control Toolkit
Atrybuty jako sposb na uproszczenie programowania
Bogaty zbir klas platformy .NET
Bogaty zbir klas jzyka JavaScript
Obsuga animacji

471
471
472
472
473
473

Struktura zestawu narzdzi ASP.NET AJAX Control Toolkit


Instalacja
Ukad pliku rozwizania

473
473
474

Architektura serwera
Atrybuty
Klasy bazowe dla kontrolek rozszerzajcych i kontrolek skryptowych
Klasy projektowe

475
476
480
485

10

Spis treci

11

Architektura strony klienckiej


Klasa BehaviorBase
Klasa ControlBase

488
489
490

Animacje
Struktura i rodzaje animacji
Architektura klienta
Architektura serwera

490
490
492
496

Podsumowanie

500

Dodawanie funkcji klienckich do kontrolek serwera


z wykorzystaniem zestawu narzdzi ASP.NET AJAX Control Toolkit 501
Dodawanie zachowa strony klienckiej
za pomoc klasy ExtenderControlBase
501
Szablon biblioteki kontrolki rozszerzajcej rodowiska Visual Studio 2008
Dziedziczenie po klasie bazowej ExtenderControlBase
Tworzenie klasy AjaxControlToolkit.BehaviorBase
Doczanie kontrolki rozszerzajcej do kontrolki docelowej
Wnioski kocowe

502
506
508
510
511

Dodanie mechanizmw obsugi trybu projektowania


do naszej kontrolki rozszerzajcej
Domylne funkcje trybu projektowania
Dodawanie klas projektujcych i edytorw do waciwoci

511
511
512

Dodawanie animacji do naszej kontrolki rozszerzajcej


Animacje tworzone z wykorzystaniem interfejsu API JavaScriptu
Animacje tworzone z wykorzystaniem modelu deklaratywnego

518
518
522

Podsumowanie

528

DODATKI
A

JavaScript w rodowisku Visual Studio


Technologia IntelliSense
Odwoania do bibliotek i usug sieciowych

Komentarze jzyka XML

Weryfikacja parametrw metod

531
531
531

535

539

Spis treci
C

11

Obiekty obsugujce i moduy frameworku ASP.NET


Cykl ycia aplikacji ASP.NET
Obiekty obsugujce dania protokou HTTP

543
543
544

Przegld obiektw obsugujcych protokou HTTP


Przegld fabryki obiektw obsugujcych protokou HTTP

544
546

Moduy protokou HTTP


Przegld moduw protokou HTTP

548
548

Kod obsugujcy bdy klientw


Klasa kliencka ErrorHandler

Strona testujca mechanizm obsugi bdw

553
553
555
555
556
557
558

Skorowidz

559

Klasa kliencka ErrorEventArgs


ErrorHandler Server Control
Klasa kliencka StackTrace
Usuga sieciowa ErrorDataService

3
Komponenty

Programowanie biblioteki Microsoft AJAX


Library rozpoczlimy omawianie biblioteki Microsoft AJAX Library i sposobw,
w jakie jej twrcy poszerzyli wbudowane typy JavaScriptu o nowe funkcje, technik wykorzystywania modelu prototypowego do rozszerzania samej biblioteki Microsoft AJAX
Library o nasze typy niestandardowe, a nawet kilku wanych aspektw dziaania typw
wbudowanych.
W tym rozdziale bdziemy kontynuowa omawianie biblioteki Microsoft AJAX Library
tym razem jednak skoncentrujemy si na komponentach i ich typach potomnych: kontrolkach i zachowaniach. W niniejszym rozdziale przystpimy te do tworzenia obiektw
klienckich zwizanych z kontrolkami serwera.
ROZDZIALE 2., ZATYTUOWANYM

Definicja komponentw
Komponentem jest kady obiekt, ktrego typ kliencki dziedziczy po typie Sys.Component.
Wspomniany typ bazowy Sys.Component jest bardzo wany, poniewa wanie za jego
pomoc bdziemy rozszerza ten framework o nowe komponenty. Tworzenie nowych
komponentw z wykorzystaniem tego typu jest o tyle uzasadnione, e wanie typ
Sys.Component ma kilka specyficznych cech, ktrych nie oferuje aden inny typ biblioteki
Microsoft AJAX Library.
Po pierwsze, komponenty s projektowane z myl o zapenianiu luki dzielcej oprogramowanie klientw i serwerw. Za porednictwem obiektw serwera nazywanych deskryptorami skryptw (ang. script descriptors) moemy wymusza na frameworku ASP.NET
AJAX automatyczne generowanie kodu JavaScriptu odpowiedzialnego za tworzenie egzemplarzy naszych typw komponentw. W ten sposb moemy wiza mechanizmy
oprogramowania klienckiego z kontrolkami naszego serwera WWW bez koniecznoci
umieszczania jakichkolwiek skryptw jzyka JavaScript w klasach tych kontrolek.

142

Rozdzia 3. Komponenty

UWAGA Tworzenie komponentw za porednictwem kodu serwera


Techniki tworzenia komponentw za porednictwem kodu serwera zostan szczegowo
omwione w rozdziale 5., zatytuowanym Dodawanie funkcji klienckich do kontrolek
serwera.
Po drugie, Sys.Application, czyli obiekt globalny wystpujcy w roli swoistego rodowiska wykonawczego klienta, jest tworzony w sposb umoliwiajcy skuteczne zarzdzanie wszystkimi typami dziedziczcymi po typie Sys.Component. Oznacza to, e cykl
ycia naszych komponentw ma charakter predefiniowany. Nie tylko bdziemy na bieco
informowani o tworzeniu i niszczeniu tych komponentw, ale te bdziemy mogli
w razie koniecznoci wykonywa wasny, niestandardowy kod przy okazji kadego
z tych zdarze. Takie rozwizanie gwarantuje nam pen kontrol i wysoki poziom bezpieczestwa.

UWAGA Komponenty i kontrolki serwera WWW


Sposb zarzdzania komponentami przez obiekt Sys.Application przypomina techniki zarzdzania kontrolkami serwera WWW przez stron. Ta zbieno nie jest
przypadkowa zaprojektowano ten mechanizm w taki sposb, aby biblioteka
Microsoft AJAX Library tworzya moliwie przyjazne rodowisko dla programistw
ASP.NET. Obiekt Sys.Application zostanie szczegowo omwiony w rozdziale 4.,
zatytuowanym Obiekt Sys.Application.
I wreszcie komponenty oferuj wiele wbudowanych popularnych elementw funkcjonalnoci, ktrych bdziesz potrzebowa podczas tworzenia swoich aplikacji. Dysponuj na
przykad egzemplarzem typu Sys.EventHandlerList, dziki ktremu moesz tworzy,
obsugiwa i generowania niestandardowe zdarzenia. Komponenty implementuj te interfejs Sys.INotifyPropertyChanged z metodami powiadomie o zmianach waciwoci.
Co wicej, komponenty implementuj interfejs Sys.INotifyDisposing, dziki czemu
pozostae obiekty mona atwo powiadamia o zwalnianiu egzemplarzy komponentw.

Komponenty, kontrolki i zachowania


Jakby tego byo mao (jakby te komponenty nie wystarczyy), biblioteka Microsoft AJAX
Library dodatkowo oferuje dwa wyspecjalizowane typy komponentw: zachowania (ang.
behaviors), reprezentowane przez klas Sys.UI.Behavior, i kontrolki (ang. controls),
reprezentowane przez klas Sys.UI.Control. Hierarchi czc te trzy typy przedstawiono
na rysunku 3.1.

Definicja komponentw

RYSUNEK 3.1. Hierarchia klas czca typy Sys.Component, Sys.UI.Behavior i Sys.UI.Control

WSKAZWKA Komponenty zarzdzane


Jak wida na rysunku 3.1, Sys.Component jest typem bazowym zarwno dla typu
Sys.UI.Control, jak i dla typu Sys.UI.Behavior. We wczeniejszej czci tego rozdziau
wspomniano ju, e za zarzdzanie komponentami odpowiada obiekt Sys.Application
dziki opisywanej relacji dziedziczenia ten sam obiekt zarzdza take kontrolkami
i zachowaniami. Kiedy mwimy o obiekcie Sys.Application, mamy na myli struktur zarzdzajc komponentami, czyli zachowaniami, kontrolkami lub komponentami jako takimi.
W praktyce zachowania, kontrolki i komponenty s niemal identyczne. Ich podobiestwo wynika z tego, e zachowania i kontrolki dziedzicz zdecydowan wikszo swojej
funkcjonalnoci po typie bazowym, czyli po klasie komponentw, nie dodajc wiele od
siebie. Co wicej, funkcjonalno implementowana przez te dwa typy potomne nie wprowadza adnych istotnych zmian.
Jedn z najwaniejszych rnic dzielcych klas bazow komponentw od zachowa
i kontrolek jest wbudowany w te dwa typy potomne zwizek z elementem modelu DOM.
Twrcy tych klas zdecydowali si na doczenie tego zwizku, poniewa zachowania
i kontrolki w zaoeniu maj mie charakter wizualny. Z drugiej strony komponenty nie
dysponuj wbudowanymi zwizkami z elementami DOM, ktre nie musz mie postaci
konstrukcji wizualnych.
Najwaniejsz rnic dzielc zachowania i kontrolki jest to, e z pojedynczym elementem modelu DOM mona zwiza tylko jedn kontrolk; ale wiele zachowa.
W tabeli 3.1 podsumowano rnice dzielce wszystkie trzy typy.
Opisane w tabeli reguy s wymuszane w trakcie tworzenia komponentw, zachowa
i kontrolek. Wanie na podstawie tych cech powinnimy podejmowa decyzje o wyborze
waciwego typu bazowego dla naszych nowych typw potomnych. Prosty diagram ilustrujcy proces oceny tych waciwoci podczas wyboru typu, po ktrym powinien dziedziczy nowy typ potomny, pokazano na rysunku 3.2.

143

144

Rozdzia 3. Komponenty
TABELA 3.1. Rnice pomidzy komponentami, kontrolkami i zachowaniami
Typ obiektu

Moliwo zwizkw
Moliwo zwizkw
wikszej liczby tego rodzaju
z elementem DOM
obiektw z elementem DOM

Dostpno obiektu z poziomu


zwizanego elementu DOM

Komponent Brak moliwoci

Brak moliwoci
(komponent nie moe
by bezporednio
zwizany z elementem
DOM)

Brak moliwoci
(komponent nie moe by
bezporednio zwizany
z elementem DOM)

Kontrolka

Musi by
zwizany z jakim
elementem
modelu DOM.

Nie, pojedynczy
element DOM moe
by zwizany z tylko
jedn kontrolk.

Tak, dostp do kontrolki


mona uzyskiwa za
porednictwem waciwoci
expando nazwanej control
i doczonej do elementu
DOM.

Zachowanie Musi by
zwizany z jakim
elementem
modelu DOM.

Tak, pojedynczy
element DOM moe
by zwizany z jedn
lub wieloma
zachowaniami.

Tak, dostp do zachowania


jest moliwy za
porednictwem waciwoci
expando nazwanej tak jak to
zachowanie (pod warunkiem
e to zachowanie byo
nazwane w czasie inicjalizacji
elementu DOM).
Wszystkie zachowania
zwizane z elementem
DOM s dostpne za
porednictwem prywatnej
tablicy _behaviors doczonej
do tego elementu.

Skoro opanowalimy ju podstawy komponentw, kontrolek i zachowa, moemy


przystpi do szczegowego omwienia kadego z tych typw.

Typ Sys.Component
Sys.Component jest typem bazowym dla wszystkich komponentw i jako taki oferuje zdecydowan wikszo ich elementw funkcjonalnoci. Typ Sys.Component nie dziedziczy po adnym
innym typie, ale implementuje trzy interfejsy: Sys.IDisposable, Sys.INotifyPropertyChanged
oraz Sys.INotifyDisposing. Wszystkie te interfejsy krtko opisano w tabeli 3.2.

Typ Sys.Component

RYSUNEK 3.2. Proces decyzyjny dla wyboru komponentu, kontrolki lub zachowania
TABELA 3.2. Interfejsy implementowane przez typ Sys.Component
Interfejs

Zadanie

Metody

Sys.INotifyPropertyChanged

Implementuje mechanizm add_propertyChanged


powiadomie o zmianach remove_propertyChanged
wartoci waciwoci.

Sys.INotifyDisposing

Implementuje zdarzenie
zwalniania komponentu.

add_disposing
remove_disposing

Sys.IDisposable

Reprezentuje obiekt
przeznaczony
do zwolnienia.

dispose

Klasa Sys.Component zawiera te pi wewntrznych skadowych, ktre opisano


w tabeli 3.3.

145

146

Rozdzia 3. Komponenty
TABELA 3.3. Skadowe typu Sys.Component
Nazwa skadowej

Zadanie

Typ

_id

Reprezentuje unikatowy identyfikator danego


komponentu. Skadowa _id jest wykorzystywana
do odnajdywania komponentw zarejestrowanych
w obiekcie Sys.Application. Kady komponent
zarzdzany przez ten obiekt musi mie unikatowy
identyfikator.

string

_idSet

Okrela, czy prawidowo ustawiono waciwo _id.

boolean

_initializing Okrela, czy dany komponent jest w trakcie procesu

boolean

inicjalizacji.
_updating

Okrela, czy dany komponent jest aktualizowany.

boolean

_events

Reprezentuje list zdarze i metod obsugujcych.

Sys.Event
HandlerList

Oprcz implementowania metod wymaganych przez trzy interfejsy wymienione w tabeli 3.2, klasa Sys.Component udostpnia kilka metod dodatkowych, ktre umoliwiaj
nam operowanie na jej wewntrznych skadowych. W tabeli 3.4 szczegowo opisano zarwno te metody dodatkowe, jak i metody wymagane przez wspomniane trzy interfejsy.

TABELA 3.4. Metody klasy Sys.Component


Nazwa metody

Opis

Skadnia

beginUpdate

Oznacza dany komponent jako


aktualizowany. Metoda beginUpdate
jest wywoywana w czasie tworzenia
komponentu.

comp.beginUpdate();

endUpdate

Oznacza dany komponent jako


nieaktualizowany. Metoda endUpdate,
ktra jest wywoywana w czasie
tworzenia komponentu, wykonuje
metody initialize (jeli dany
komponent nie jest inicjalizowany)
i updated.

comp.endUpdate();

updated

Implementacja pusta.

comp.updated();

get_isUpdating

Zwraca warto skadowej _updating.

comp.get_isUpdating();

initialize

Oznacza dany komponent jako


inicjalizowany.

comp.initialize();

get_initialized

Zwraca warto skadowej _initialized. comp.get_initialized();

Typ Sys.Component
TABELA 3.4. Metody klasy Sys.Component cig dalszy
Nazwa metody

Opis

Skadnia

dispose

comp.dispose();
Wykonuje metody obsugujce
zdarzenie disposing. Usuwa
waciwo _events z danego
komponentu i anuluje jego rejestracj
w obiekcie Sys.Application.

get_events

Zwraca warto skadowej _events.

comp.get_events();

get_id

Zwraca warto skadowej _id.

comp.get_id();

set_id

Ustawia warto skadowej _id. Raz


ustawionego identyfikatora nie mona
zmienia (za porednictwem tej
metody); identyfikator nie moe
by zmieniany take po rejestracji
komponentu w obiekcie
Sys.Application.

comp.set_id(id);

add_disposing

Dodaje metod obsugujc


zdarzenie disposing.

comp.add_disposing
(handler);

remove_disposing

Usuwa metod obsugujc


zdarzenie disposing.

comp.remove_disposing
(handler);

add_propertyChan
ged

Dodaje metod obsugujc


zdarzenie propertyChanged.

comp.add_propertyChanged
(handler);

remove_propertyC
hanged

Usuwa metod obsugujc


zdarzenie propertyChanged.

comp.remove_property
Changed
(handler);

raisePropertyCha
nged

Wykonuje zarejestrowane
metody obsugujce zdarzenie
propertyChanged, przekazujc na
ich wejciu (w formie argumentw
zdarzenia) nazw zmodyfikowanej
waciwoci.

comp.raisePropertyChanged
(propertyName);

WSKAZWKA Metody beginUpdate, endUpdate oraz initialize


Metody beginUpdate, endUpdate oraz initialize s wykonywane automatycznie
w ramach procesu tworzenia komponentu. Wymienione metody z reguy nie s wywoywane z poziomu kodu zdefiniowanego przez uytkownika, ale mona je przykry, aby umieci w nich jak niestandardow funkcjonalno.

147

148

Rozdzia 3. Komponenty

Definiowanie nowych komponentw


Klasa Sys.Component jest niezwykle przydatna, jednak jej celem nie jest bezporednie
tworzenie egzemplarzy tego typu. Przeciwnie, twrcy klasy Sys.Component chcieli opracowa typ, ktry bdzie wykorzystywany w roli klasy bazowej dla komponentw definiowanych przez uytkownikw.
Nowy typ komponentu moemy zdefiniowa, stosujc model prototypowy omwiony
w rozdziale 2. i rejestrujc nasz komponent jako typ dziedziczcy po klasie bazowej
Sys.Component.

Komponent ErrorHandler
Aby zademonstrowa technik definiowania nowych komponentw, utworzymy nowy,
wasny komponent obsugi bdw. Komponent ErrorHandler bdzie odpowiada za publikowanie obsugiwanych i nieobsugiwanych bdw z wykorzystaniem specjalnej usugi
danych o bdach.

Szkielet
Na pocztek utworzymy szkielet naszego nowego komponentu (patrz listing 3.1).

LISTING 3.1. Definiowanie komponentu ErrorHandler


/// <reference name="MicrosoftAjax.js"/>
ErrorHandler = function() {
ErrorHandler.initializeBase(this);
};
ErrorHandler.prototype = {
initialize: function() {
ErrorHandler.callBaseMethod(this, 'initialize');
},
dispose: function() {
ErrorHandler.callBaseMethod(this, 'dispose');
}
}
ErrorHandler.registerClass('ErrorHandler', Sys.Component);

Oprcz wywoania metody initializeBase w konstruktorze naszego typu i rejestracji


tej klasy jako typu dziedziczcego po klasie Sys.Component zdecydowalimy si na przykrycie metod initialize i dispose klasy bazowej Sys.Component. Umiecilimy te przykryte metody w szkielecie naszego komponentu, poniewa wanie przykrywanie initialize
i dispose jest zwykle jednym z pierwszych krokw procesu tworzenia komponentu
(podobn kolejno sugerujemy take Tobie).

Typ Sys.Component
Inicjalizacja i niszczenie komponentu
Nasz szkieletow definicj naley jeszcze uzupeni o implementacje metod initialize
i dispose.
W metodzie initialize konstruujemy nasz komponent. Proces konstruowania komponentu obejmuje takie kroki jak dodanie metod obsugujcych zdarzenia do elementw
modelu DOM, doczenie nowego elementu DOM do drzewa i wszystkie inne operacje
wymagane przez konkretny typ komponentw.
W metodzie dispose powinnimy umieci kod odpowiedzialny za zwalnianie naszego
komponentu. Zwalnianie komponentu moe obejmowa odczenie zdarze od elementu
modelu DOM, zniszczenie ewentualnych utworzonych elementw DOM lub zwolnienie
wszelkich innych zasobw utworzonych przez nasz komponent.

WSKAZWKA Metod dispose mona wywoa wicej ni raz


Warto tak implementowa metod dispose, aby mona j byo wywoywa wicej ni
raz bez ryzyka powodowania bdw czasu wykonywania. W przypadku do zoonych
aplikacji nietrudno o sytuacj, w ktrej zwalniany obiekt menedera wywoa metod
dispose wszystkich swoich komponentw potomnych. Okazuje si jednak, e kady
z tych obiektw potomnych jest zarejestrowany take w obiekcie Sys.Application jako
obiekt, ktry moe by zwalniany (ktry implementuje interfejs Sys.IDisposable).
Zwalniany obiekt Sys.Application automatycznie wykonuje metod dispose kadego z tak zarejestrowanych obiektw oznacza to, e metody dispose tych obiektw s wykonywane (co najmniej) dwukrotnie. Jeli nie zachowamy naleytej ostronoci, prby wielokrotnego wykonania metody dispose bd si koczyy bdami
czasu wykonywania. Mona jednak unikn tych problemw, stosujc proste mechanizmy weryfikacji w formie wyrae warunkowych.
Na potrzeby naszego nowego komponentu ErrorHandler naley doda metod obsugujc zdarzenie error obiektu window przy okazji inicjalizacji tego komponentu i usun
t metod przy okazji jego zwalniania. Proponowan implementacj tego mechanizmu
przedstawiono na listingu 3.2.

LISTING 3.2. Dodawanie metody obsugujcej zdarzenie error obiektu okna


/// <reference name="MicrosoftAjax.js"/>
ErrorHandler = function () {
ErrorHandler.initializeBase(this);
};
ErrorHandler.prototype = {
initialize: function () {
ErrorHandler.callBaseMethod(this, 'initialize');
window.onerror =
Function.createDelegate(this, this._unhandledError);

149

150

Rozdzia 3. Komponenty
},
dispose: function ErrorHandler$dispose() {
window.onerror = null;
ErrorHandler.callBaseMethod(this, 'dispose');
},
_unhandledError: function(msg, url, lineNumber) {
try {
var stackTrace = StackTrace.createStackTrace(arguments.callee);
ErrorDataService.PublishError
(stackTrace, msg, url, lineNumber);
}
catch (e) { }
}
}
ErrorHandler.registerClass('ErrorHandler', Sys.Component);

Jak wida na listingu 3.2, wykorzystalimy w naszym kodzie kilka interesujcych zabiegw. Po pierwsze, w metodzie initialize utworzono delegacj wskazujc na metod
_unhandledError i skojarzono t delegacj ze zdarzeniem error obiektu window (przypisujc j zdarzeniu onerror).

WSKAZWKA Zdarzenie window.onerror


W omawianym kodzie wykorzystano konstrukcj polegajc na przypisaniu delegacji
zdarzeniu onerror (zamiast metody $addHandler), poniewa z jakiego powodu zdarzenie error obiektu okna nie obsuguje dodawania zdarze za pomoc metod addEventListener ani attachEvent (czyli dwch metod waciwych dla konkretnych
przegldarek i ostatecznie wywoywanych przez metod $addHandler).
W metodzie dispose usunlimy metod obsugujc zdarzenie error obiektu window.
Dysponujemy wic gotowym kodem inicjalizujcym i zwalniajcym nasz komponent.
W metodzie unhandledError, ktra bdzie wykonywana w odpowiedzi na wystpienia
nieobsugiwanych bdw, podejmujemy dwa dziaania. Po pierwsze, generujemy lad
stosu, korzystajc z globalnego obiektu StackTrace przekazywanego za porednictwem
waciwoci callee zmiennej arguments naszej funkcji. Po uzyskaniu obiektu ladu stosu
wykonujemy metod PublishError porednika naszej usugi sieciowej ErrorDataService
(za porednictwem tej metody przekazujemy na serwer lad stosu, komunikat o bdzie,
adres URL strony, na ktrej ten bd wystpi, i numer wiersza kodu). Cay ten kod dodatkowo umiecilimy w ramach wyraenia try-catch, poniewa nie chcemy, aby kod obsugujcy bdy sam generowa jakiekolwiek bdy czasu wykonywania.

Typ Sys.Component

WSKAZWKA Obiekty StackTrace i ErrorDataService


Globalny obiekt StackTrace, ktry wykorzystano do wygenerowania naszego ladu
stosu wykonywania, jest niezwykle przydatny w procesie diagnozowania kodu, a jego
kompletny kod rdowy przedstawiono w dodatku D, zatytuowanym Kod obsugujcy bdy klientw. Podobnie, kod usugi sieciowej ErrorDataService, ktrej
uyto do odesania informacji o bdzie na serwer, take mona znale we wspomnianym dodatku.

Stosowanie metod i obiektw klasy bazowej


Skoro nasz typ dziedziczy po klasie Sys.Component, z natury rzeczy przejmuje wszystkie
atrybuty i zachowania tego typu bazowego. Korzystajc z obiektu Sys.EventHandlerList
dostpnego w ramach tej klasy (i jego funkcjonalnoci), moemy definiowa nowe zdarzenia bez koniecznoci samodzielnego pisania sporej iloci kodu. Na listingu 3.3 rozszerzono
nasz komponent ErrorHandler o zdarzenie, ktre moemy zarejestrowa jako generowane
w odpowiedzi na wystpienia bdw.

LISTING 3.3. Korzystanie z metod klasy bazowej


// wczeniejszy kod komponentu pozostaje niezmieniony
_unhandledError: function (msg, url, lineNumber) {
try {
var stackTrace =
StackTrace.createStackTrace(arguments.callee);
ErrorDataService.PublishError
(stackTrace, msg, url, lineNumber);
var args = new ErrorEventArgs(stackTrace, msg, url, lineNumber);
this._raiseUnhandledErrorOccured(args);
}
catch (e) { }
},
add_unhandledErrorOccurred: function(handler) {
this.get_events().addHandler("unhandledErrorOccurred", handler);
},
remove_unhandledErrorOccurred: function(handler) {
this.get_events().removeHandler("unhandledErrorOccurred", handler);
},
_raiseUnhandledErrorOccured: function(args) {
var evt = this.get_events().getHandler("unhandledErrorOccurred");
if (evt !== null) {
evt(this, args);

151

152

Rozdzia 3. Komponenty
}
},
}
ErrorHandler.registerClass('ErrorHandler', Sys.Component) ;
ErrorEventArgs = function(stackTrace, message, url, lineNumber) {
ErrorEventArgs.initializeBase(this);
this._message = message;
this._stackTrace = stackTrace;
this._url = url;
this._lineNumber = lineNumber;
}
ErrorEventArgs.registerClass("ErrorEventArgs", Sys.EventArgs);

Skoncentrujmy si najpierw na kocowej czci listingu 3.3, gdzie zdefiniowano nowy


typ ErrorEventArgs. Typ ErrorEventArgs dziedziczy po typie Sys.EventArgs i przeksztaca nasze informacje o bdzie w obiekt.
W typie ErrorHandler dodano trzy metody niezbdne do dodawania, usuwania i generowania zdarzenia unhandledErrorOccurred. W naszym kodzie wykorzystujemy list
metod obsugujcych utrzymywan przez obiekt Sys.Component dostp do listy samych
zdarze uzyskujemy za porednictwem metody this.get_events().
I wreszcie w metodzie _unhandledError dodalimy kod tworzcy argumenty zdarzenia
bdu i przekazujcy je do metody, ktra to zdarzenie generuje.
Ostatnia zmiana, ktr musimy wprowadzi do komponentu ErrorHandler, polega na
dodaniu waciwoci umoliwiajcej wczanie i wyczanie trybu publikowania bdw.
Niezbdne modyfikacje przedstawiono na listingu 3.4.

LISTING 3.4. Dodanie waciwoci wyczajcej tryb publikacji bdw


/// <reference name="MicrosoftAjax.js"/>
ErrorHandler = function () {
ErrorHandler.initializeBase(this);
this._disableErrorPublication = false;
};
ErrorHandler.prototype = {

get_disableErrorPublication: function() {
return this._disableErrorPublication;
},
set_disableErrorPublication: function(value) {
if (!this.get_updating()) {
this.raisePropertyChanged("disableErrorPublication");
}
this._disableErrorPublication = value;
},

Typ Sys.Component
_unhandledError: function(msg, url, lineNumber) {
try {
var stackTrace = StackTrace.createStackTrace(arguments.callee);
if (!this._disableErrorPublication) {
ErrorDataService.PublishError
(stackTrace, msg, url, lineNumber);
}
var args =
new ErrorEventArgs(stackTrace, msg, url, lineNumber);
this._raiseUnhandledErrorOccured(args);
}
catch (e) { }
},

}
ErrorHandler.registerClass('ErrorHandler', Sys.Component);

Ostatnia zmiana czyni z naszego typu przydatny komponent, ktry mona z powodzeniem wykorzystywa do wysyania na serwer informacji o bdach wystpujcych po stronie klienta i tym samym powiadamiania programistw o ewentualnych problemach.

Tworzenie komponentw
Na podstawie materiau zaprezentowanego w tym rozdziale do tego momentu mona by
pomyle, e tworzenie nowych komponentw polega na konstruowaniu ich obiektw
i przypisywaniu ich odpowiednim zmiennym (patrz listing 3.5).

LISTING 3.5. Tworzenie egzemplarza komponentu za pomoc sowa new


var errorHandler = new ErrorHandler();
errorHandler.set_disableErrorPublication (false);

Chocia w kodzie w tej formie nie ma niczego nieprawidowego (w kocu egzemplarz


komponentu jest wanie obiektem JavaScriptu), komponenty naley tworzy raczej za
porednictwem metody Sys.Component.create. Skadni wywoa metody create przedstawiono na listingu 3.6.

LISTING 3.6. Tworzenie egzemplarza komponentu za porednictwem metody Sys.Component.create


var newComponent =
Sys.Component.create(
type,
properties,
events,
references,
element);

153

154

Rozdzia 3. Komponenty
Dziaanie metody Sys.Component.create, ktra jest dostpna take za porednictwem
zmiennej globalnej $create, nie ogranicza si tylko do tworzenia nowego egzemplarza
okrelonego typu. Oprcz tworzenia nowego egzemplarza wskazanego typu metoda
Sys.Component.create rejestruje ten egzemplarz w obiekcie Sys.Application jako komponent zarzdzany, po czym automatycznie wywouje metody beginUpdate, endUpdate,
updating i initialize tego komponentu. Wszystkie te dziaania s podejmowane automatycznie w zalenoci od parametrw uytych w jej wywoaniu. Co wicej, metoda $create
moe przypisywa wartoci pocztkowe waciwoci, dodawa metody obsugujce zdarzenia, przypisywa inne komponenty w formie referencji i wiza z danym komponentem element modelu DOM. I wreszcie metoda $create zwraca wskanik do nowo utworzonego egzemplarza. Jak wida, metoda $create robi duo wicej ni tylko tworzenie
nowego egzemplarza naszego typu.

UWAGA Wykonywanie metody initialize


Metoda initialize zawsze jest wykonywana po ustawieniu wszystkich waciwoci,
zdarze i referencji.
Co wane, metoda $create tworzy nie tylko egzemplarze typw, ktre bezporednio
dziedzicz po klasie Sys.Component, ale te egzemplarze typw na wielu poziomach dziedziczenia pomidzy wskazanym typem a typem Sys.Component. Zbir tych egzemplarzy
obejmuje kontrolki dziedziczce po typie Sys.UI.Control i zachowania dziedziczce po
typie Sys.UI.Behavior. Metoda $create dziaa inaczej w przypadku zachowa i inaczej
w przypadku kontrolek te nieznaczne rnice zostan omwione przy okazji analizy
tych typw w dalszej czci tego rozdziau.

UWAGA Parametry metody $create


Jedynym parametrem wymaganym przez metod $create jest type. Pozostae parametry properties, events, references i element maj opcjonalny charakter.
Jeli nie chcemy z nich korzysta, powinnimy w ich miejsce przekaza warto null.
Przekazanie wartoci innej ni null za porednictwem parametru element jest prawidowe, pod warunkiem e typ, ktrego egzemplarz tworzymy, dziedziczy po klasie
Sys.UI.Control lub Sys.UI.Behavior. Jeli przekaemy ten parametr w sytuacji, gdy
tworzony egzemplarz komponentu nie dziedziczy po adnym z wymienionych typw,
zostanie wygenerowany bd.
Podobnie, jeli nie przekaemy wartoci innej ni null za porednictwem parametru
element podczas tworzenia egzemplarza typu dziedziczcego po klasie Sys.UI.Control
lub Sys.UI.Behavior, zostanie wygenerowany bd.

Typ Sys.Component
Aby zademonstrowa sposb uycia metody $create, przeanalizujemy szereg jej wywoa, zmieniajc parametry przekazywane na wejciu tej metody.

UWAGA Obiekt Sys.Application jest zainicjalizowany


W poniszym materiale powiconym dziaaniu metody $create zakadamy, e
obiekt Sys.Application zosta ju zainicjalizowany. Mimo e komponenty nie zawsze s tworzone w takich okolicznociach, decydujemy si na to zaoenie na potrzeby
pocztkowej analizy metody $create, aby uproci nasze dalsze rozwaania.
Okazuje si jednak, e istnieje kilka istotnych rnic dzielcych proces tworzenia
komponentw po inicjalizacji obiektu Sys.Application od procesu tworzenia komponentw przed pen inicjalizacj tego obiektu zmiany dziaania metody $create
wskutek niepenej inicjalizacji obiektu Sys.Application zostan omwione przy okazji
analizy samego procesu inicjalizacji tego obiektu w rozdziale 4.

Stosowanie parametru type


Przyjrzyjmy si najpierw podstawowemu wywoaniu metody $create polegajcemu na
przekazaniu samego typu obiektu, ktry chcemy utworzy, oraz wartoci null w miejsce
pozostaych parametrw. Przykad takiego wywoania przedstawiono na listingu 3.7.

LISTING 3.7. Parametr type


var errorHandler =
Sys.Component.create(
ErrorHandler,
null,
null,
null,
null);

type

Opis: Typ tworzonego komponentu


Oczekiwany typ: type
Wymagany: Tak
Pozostae wymagania: Obiekt przekazany za porednictwem tego parametru musi
by egzemplarzem typu dziedziczcego po klasie Sys.Component.
Uwagi: Parametr nie jest otoczony cudzysowami, poniewa ma posta obiektu
typu Type, nie acucha. Obiekt klasy Type jest egzemplarzem typu Function
zarejestrowanym w bibliotece Microsoft AJAX Library z wykorzystaniem metody
registerClass, registerInterface lub registerEnum (tak jak nasz komponent
ErrorHandler).

155

156

Rozdzia 3. Komponenty
W przedstawionym przykadzie pierwszym dziaaniem metody Sys.Component.create
jest sprawdzenie, czy za porednictwem parametru type przekazano obiekt (w tym przypadku ErrorHandler) typu Type, ktry dziedziczy po klasie Sys.Component. Po sprawdzeniu
tego parametru metoda Sys.Component.create tworzy nowy egzemplarz typu ErrorHandler
i przypisuje go pewnej zmiennej lokalnej.

UWAGA Rejestrowanie obiektw implementujcych interfejs IDisposable


Podczas tworzenia egzemplarza komponentu, nowy obiekt jest rejestrowany w obiekcie Sys.Application jako egzemplarz typu implementujcy interfejs IDisposable.
Takie rozwizanie gwarantuje moliwo wywoania metody dispose tego egzemplarza
podczas zwalniania samego obiektu Sys.Application. Omwimy to zagadnienie bardziej
szczegowo w rozdziale 4.
Bezporednio potem nastpuje wywoanie metody beginUpdate ju utworzonego egzemplarza komponentu. Dziaanie metody beginUpdate domylnie ogranicza si do przypisania
wartoci true wewntrznej fladze aktualizacji, mona jednak t metod przykry w ramach
implementacji nowego komponentu, aby podejmowaa ewentualne dodatkowe dziaania.
Nastpnie jest wywoywana metoda endUpdate nowego egzemplarza metoda
endUpdate przywraca warto false wewntrznej flagi _updating, po czym wykonuje
przykryt przez nas metod initialize (ktra w naszej wersji docza do zdarzenia error
obiektu window funkcj obsugujc). Po wykonaniu metody initialize nastpuje wywoanie metody updated. Jeli nie przykrylimy metody updated, jej oryginalna wersja nie
podejmuje adnych dziaa. Do zwrconego komponentu moemy uzyskiwa dostp za
porednictwem zmiennej, ktrej przypisano wywoanie metody Sys.Component.create.

WSKAZWKA Test skadowej _initialized


Metoda endUpdate zawiera mechanizm sprawdzajcy (przed wywoaniem metody
initialize), czy wewntrzna skadowa _initialized reprezentuje warto false.
O ile w przypadku metody $create w chwili wywoywania endUpdate skadowa
_initialized zawsze ma warto false, o tyle w razie wywoania metody endUpdate
na dalszych etapach cyklu ycia danego komponentu skadowa _initialized bdzie
miaa warto true, co uniemoliwi ponowne wykonanie metody initialize. Takie
rozwizanieumoliwia nam wywoywanie metod beginUpdate i endUpdate bez ryzyka
ponownej inicjalizacji naszego komponentu.
Ten prosty przykad dobrze pokazuje, jak wane s zdania niewypowiedziane. Do tej
pory ani razu nie wspomniano w tym punkcie o dodawaniu naszego komponentu do zbioru obiektw zarzdzanych przez obiekt Sys.Application (jak wiemy, za t operacj odpowiada metoda Sys.Component.create). W tym przypadku naszego komponentu nie
dodano do tego zbioru, poniewa nigdy nie ustawiono jego identyfikatora tylko kom-

Typ Sys.Component
ponenty z ustawionymi identyfikatorami s automatycznie dodawane do zbioru komponentw zarzdzanych obiektu Sys.Application. Mona to zmieni, rcznie ustawiajc
identyfikator komponentu i dodajc go do listy komponentw zarzdzanych obiektu
Sys.Application (patrz listing 3.8).

LISTING 3.8. Rczne ustawienie identyfikatora komponentu i wywoanie metody addComponent


var errorHandler =
Sys.Component.create(
ErrorHandler,
null,
null,
null,
null);
errorHandler.set_id("ApplicationErrorHandler");
Sys.Application.addComponent(errorHandler);

UWAGA Wywoywanie metody addComponent


Gdybymy sprbowali rcznie doda dany komponent do obiektu Sys.Application
bez uprzedniego ustawienia identyfikatora tego komponentu, otrzymalibymy bd
czasu wykonywania.
Alternatywnym sposobem rozwizania tego problemu jest pocztkowe ustawienie
identyfikatora komponentu. Jeli ustawimy ten identyfikator za porednictwem parametru
properties, nasz komponent zostanie automatycznie dodany do zbioru komponentw
zarzdzanych przez obiekt Sys.Application bezporednio po przetworzeniu parametru
events. Niezbdne zmiany przedstawiono na listingu 3.9.

LISTING 3.9. Ustawienie identyfikatora komponentu w ramach wywoania metody Sys.Component.create


var errorHandler =
Sys.Component.create(
ErrorHandler,
{id: "ApplicationErrorHandler"},
null,
null,
null);

Poniewa okrelenie identyfikatora komponentu jest warunkiem jego rejestracji jako


komponentu zarzdzanego, niemal zawsze powinnimy t waciwo definiowa przy
okazji wywoania metody $create. Istniej jednak specjalne przypadki, w ktrych moemy
wiadomie rezygnowa z ustawiania identyfikatora lub odkada t operacj na przyszo
zdarza si to jednak do rzadko.

157

158

Rozdzia 3. Komponenty
Warto te pamita, e identyfikatory komponentw zarzdzanych przez obiekt
Sys.Application musz by unikatowe. Gdybymy sprbowali doda do zbioru kompo-

nentw zarzdzanych przez ten obiekt dwa komponenty z tym samym identyfikatorem
(niezalenie od tego, czy zrobilibymy to za porednictwem wyraenia $create, czy rcznie wywoujc metod addComponent), otrzymalibymy bd.

UWAGA Korzystanie ze zwrconej zmiennej


Metoda $create umoliwia nam dostp do utworzonego komponentu za porednictwem zwrconego przez siebie wskanika. Okazuje si jednak, e wspomniany znacznik
jest przydatny tylko w pewnych sytuacjach. Poniewa nasz komponent jest rejestrowany w obiekcie Sys.Application, moemy w przyszoci uzyska dostp do tego
komponentu albo odnajdujc go w zbiorze komponentw zarzdzanych przez ten obiekt,
albo korzystajc z jego unikatowego identyfikatora.

Stosowanie parametru properties


W tym przykadzie sprbujemy przekaza na wejciu metody Sys.Component.create
kilka pocztkowych wartoci waciwoci. Wywoanie tej metody przedstawiono na
listingu 3.10.

LISTING 3.10. Przekazywanie pocztkowych wartoci waciwoci


var errorHandler =
Sys.Component.create(
ErrorHandler,
{
id: "ApplicationErrorHandler",
disableErrorPublication: true
},
null,
null,
null);

properties

Oczekiwany typ: Object


Wymagany: Nie
Opis: Obiekt zawierajcy pary klucz-warto, gdzie klucz reprezentuje nazw
ustawianej waciwoci komponentu, a warto reprezentuje to, co tej waciwoci
ma zosta przypisane.
W przedstawionym przykadzie pocztkowe kroki metody $create s takie same jak
w poprzednim przykadzie. Metoda $create weryfikuje warto parametru type, tworzy
nasz komponent i wykonuje metod beginUpdate.

Typ Sys.Component
W kolejnym kroku metoda $create przypisuje przekazane wartoci waciwociom
komponentu. Waciwoci i ich wartoci s przekazywane na wejciu tej metody z wykorzystaniem skadni acuch-obiekt (wyrnionej pogrubieniem na listingu 3.10). Zamiast
korzysta ze wspomnianej skadni, mona by uy przedstawionego na listingu 3.11 kodu
tworzcego obiekt, jednak wanie skadnia acuch-obiekt jest w tej sytuacji krtsza i bardziej
czytelna.

LISTING 3.11. Tworzenie obiektu waciwoci z wykorzystaniem zmiennych


var initialProperties = new Object;
initialProperties.id = "ApplicationErrorHandler";
initialProperties.disableErrorPublication = true;
var errorHandler =
$create(
ErrorHandler,
initialProperties,
null,
null,
null);

Niezalenie od stosowanej skadni nasz kod wyraa denie do ustawienia dwch waciwoci: id oraz disableErrorPublication.
Aby ustawienie tych waciwoci byo moliwe, metoda $create deleguje sterowanie
do innej metody, nazwanej Sys$Component_setProperties. Ta globalna metoda dostpna
w ramach biblioteki Microsoft AJAX Library zostaa stworzona wanie z myl o ustawianiu
waciwoci komponentw. Metoda Sys$Component_setProperties otrzymuje na wejciu
dwa parametry: obiekt target i obiekt properties.
W ramach tej metody kada z naszych waciwoci expando doczona do parametru
properties jest odczytywana i przetwarzana wedug zbioru cile okrelonych regu.
Pierwsza regua okrela, czy dla danej waciwoci istnieje metoda zwracajca jej warto. Nazw tej metody okrela si, poprzedzajc nazw samej waciwoci (w tym przypadku id) przedrostkiem get_. W naszym przykadzie metoda get_id istnieje w klasie
bazowej Sys.Component, zatem warunek tej reguy jest speniony.
Po stwierdzeniu istnienia metody zwracajcej metoda Sys$Component_setProperties
przystpuje do poszukiwania metody ustawiajcej. Nazwa tej metody powinna si skada
z nazwy samej waciwoci poprzedzonej przedrostkiem set_. Ponownie okazuje si, e
odpowiednia metoda (w tym przypadku set_id) istnieje w klasie bazowej Sys.Component.
Po stwierdzeniu istnienia metody ustawiajcej metoda Sys$Component_setProperties
wywouje j, przekazujc na jej wejciu warto biecej waciwoci. W prezentowanym
przykadzie metoda ustawiajca otrzymuje warto ApplicationErrorHandler.
Opisywany proces jest powtarzany a do momentu skutecznego zastosowania wszystkich waciwoci danego komponentu lub wystpienia jakiego bdu (zwizanego na
przykad z brakiem metody zwracajcej, niewaciw liczb parametrw obsugiwanych
przez metod ustawiajc lub wieloma innymi moliwymi problemami). W naszym przykadzie waciwo disableErrorPublication jest inicjalizowana z wartoci true.

159

160

Rozdzia 3. Komponenty

UWAGA Iteracyjne przeszukiwanie waciwoci


Dostp do waciwoci expando doczonych do parametru properties uzyskujemy,
korzystajc z ptli forin. Jak wiemy z rozdziau 1., zatytuowanego Programowanie
w jzyku JavaScript, ptla forin iteracyjnie przeszukuje waciwoci obiektu i umieszcza we wskazanej zmiennej biec waciwo.
Po umieszczeniu nazwy biecej waciwoci w zmiennej, dostp do wartoci skojarzonej z t nazw mona uzyska wedug regu obowizujcych w wiecie tablic asocjacyjnych opisanych w rozdziale 1.

Wywoywanie metod ustawiajcych


Jak ju wspomniano, metoda ustawiajca waciwo jest wykonywana
w trakcie tworzenia obiektu komponentu. Podobnie jak w jzykach platformy
.NET, metoda ustawiajca moe zawiera dowolny kod niezbdny do ustawienia odpowiedniej waciwoci. Jeli dziaanie tej metody bdzie procesem dugotrwaym, tworzenie komponentu bdzie wstrzymane do czasu zakoczenia tego procesu.
W tej sytuacji musimy zachowa naleyt ostrono, aby metoda ustawiajca bya moliwie efektywna i tym samym aby proces tworzenia komponentu trwa jak najkrcej.
Jeli dysponujemy jakim dodatkowym kodem, ktry jednak nie powinien by
wykonywany w ramach procesu tworzenia komponentu, moemy tego wykonywania unikn, uzaleniajc je od wartoci skadowej prywatnej _updating:

set_disableErrorPublication: function(value) {
if (!this.get_updating()) {
this.raisePropertyChanged
("disableErrorPublication");
}
this._disableErrorPublication = value;
},

W powyszym przykadzie kodu rdowego przed wygenerowaniem zdarzenia propertyChangedupewniamy si, e dany komponent nie jest aktualizowany. Sprawdzenie flagi _updating jest nieporwnanie mniej kosztowne
ni przechodzenie przez cay proces generowania zdarzenia.
Ostrzeenie: Przedstawiony kod ma wycznie charakter testowy. Przed jego
uyciem powinnimy dokadnie sprawdzi, czy w naszym przypadku zdarzenie propertyChanged rzeczywicie nie powinno by generowane w czasie,
gdy dany komponent jest aktualizowany.

Typ Sys.Component

Ustawianie waciwoci zoonych


Przykady waciwoci id i disableErrorPublication naszego egzemplarza
komponentu ErrorHandler ustawianych za porednictwem metody $create
s do proste. Okazuje si jednak, e istniej cztery bardziej zaawansowane
scenariusze ustawiania waciwoci, ktre warto wykorzysta podczas tworzenia zoonych komponentw w ramach pojedynczych wyrae:
1. Ustawianie wartoci pozbawionej metody ustawiajcej lub zwracajcej, na
przykad atrybutu elementu DOM lub waciwoci doczonej do prototypu.
2. Dopisywanie elementw do tablicy.
3. Ustawianie waciwoci podkomponentu, czyli komponentu zawartego
w innym komponencie.
4. Dodawanie waciwoci do istniejcego obiektu.
Kady z tych scenariuszy zilustrowano w kodzie poniszego, do mao realistycznego komponentu MyComplexComponent:
MyComplexComponent = function() {
MyComplexComponent.initializeBase(this);
this.city = null;
this._areaCodes = [];
this._myObject = { firstName: "Harry" };
this.subComponent =
$create(ErrorHandler,
null,
null,
null,
null);
};
MyComplexComponent.prototype = {
someExpandoProperty: null,
get_address: function() {
return this._address;
},
set_address: function(value) {
this._address = value;
},
get_areaCodes: function() {
return this._areaCodes;
},
get_myObject: function() {
return this._myObject;
}
};
MyComplexComponent.registerClass(
"MyComplexComponent",
Sys.Component);

161

162

Rozdzia 3. Komponenty
var newComponent =
$create(
MyComplexComponent,
{
id: "MyNewComplexComponent",
city: "Sanok",
areaCodes: [619, 858, 760],
someExpandoProperty: "Moja warto waciwoci expando",
subComponent:
{
id: "ApplicationErrorHandler",
disableErrorPublication: "true"
},
myObject: { lastName: "Nowak" }
},
null,
null,
null);

1. Ustawianie wartoci, dla ktrej nie istnieje metoda zwracajca lub ustawiajca.
Ten scenariusz zilustrowano na przykadzie ustawiania waciwoci city
i someExpandoProperty. Tego rodzaju waciwoci mona ustawia, poniewa stanowi istniejce pola swojego obiektu. Gdyby nie istniay, wyraenie setProperties by ich nie dodao.
2. Doczanie elementw do tablicy.
Drugi zaawansowany scenariusz zilustrowano na przykadzie waciwoci
areaCodes. W tym przypadku zdefiniowano now tablic zoon z trzech
elementw (619, 858 i 760) i przypisano j waciwoci areaCodes. Dodawanie elementw do istniejcej tablicy wymaga metody zwracajcej, ale
nie wymaga metody ustawiajcej warto tej waciwoci. W razie istnienia
metody ustawiajcej istnieje moliwo jej uycia zamiast kodu metody
zwracajcej wwczas to kod metody ustawiajcej bdzie odpowiada
za doczenie elementw do tablicy. Warto te pamita o koniecznoci
uprzedniego utworzenia egzemplarza danej tablicy. Jeli okae si, e dana
zmienna wskazuje na null lub undefined, zostanie wygenerowany bd.
3. Ustawianie waciwoci podkomponentu.
Trzeci zaawansowany scenariusz przedstawiono na przykadzie waciwoci subComponent. W tym przypadku zdefiniowano podobiekt zawierajcy
waciwoci id oraz disableErrorPublication, ktre zdefiniowano wczeniej w ramach komponentu ErrorHandler. Kiedy metoda setProperties
odkrywa te waciwoci, uzyskuje dostp do podkomponentu, po czym
rekurencyjnie wywouje metod setProperties, stosujc ten podkomponent w roli parametru target oraz podobiekt zawierajcy te waciwoci
w roli parametru properties. Tego rodzaju wywoania rekurencyjne mog
by wykorzystywane na dowolnej liczbie poziomw (jeli ustawiono parametr properties w odpowiedni sposb).

Typ Sys.Component
Rwnie dobrze moglibymy tutaj zdefiniowa metod zwracajc i otrzyma ten sam efekt, gdybymy jednak dodatkowo zdefiniowali metod
ustawiajc, proces ustawiania waciwoci podkomponentu nie dziaaby
zgodnie z naszymi oczekiwaniami.
Metoda setProperties wywoywana rekurencyjnie z wykorzystaniem
komponentu w roli parametru target sama wywouje metod beginUpdate
tego komponentu przed wejciem w ptl forin i metod endUpdate po
opuszczeniu tej ptli. Warto o tym pamita, jeli w naszym kodzie korzystamy z metody get_updating.
4. Ustawianie waciwoci zwykego obiektu JavaScriptu.
Czwarty, ostatni zaawansowany scenariusz przedstawiono na przykadzie
waciwoci myObject. Waciwo myObject definiuje prosty obiekt zawierajcy waciwo lastName, ktra reprezentuje warto "Nowak". Kiedy
metoda setProperties odkrywa t waciwo, stosuje rekurencyjne wywoanie metody setProperties, aby zastosowa t now waciwo dla
skadowej myObject. Tym razem zamiast przekazywa komponent za porednictwem parametru target, przekazujemy w roli tego parametru
waciwo myObject, a obiekt nowej waciwoci jest przekazywany za
porednictwem waciwoci properties.
Jak wida, parametr properties metody $create moe z powodzeniem obsugiwa kilka zaawansowanych scenariuszy. Jeli bdziesz o tej moliwoci pamita, by moe znajdziesz dla tych rozwiza zastosowania w swoim kodzie.

Stosowanie parametru events


W tym przykadzie sprbujemy wykorzysta parametr events do skojarzenia metody
obsugujcej z dostpnym, zainicjalizowanym zdarzeniem. Moliwy sposb realizacji tego
zadania pokazano na listingu 3.12.

LISTING 3.12. Przekazywanie metod obsugujcych na wejciu metody $create


$create(
ErrorHandler,
{
id:"ApplicationErrorHandler",
disableErrorPublication: true
},
{
unhandledErrorOccurred:
function(sender, args) {
alert(args._stackTrace);
}
},
null,
null);

163

164

Rozdzia 3. Komponenty
events

Oczekiwany typ: Object


Wymagany: Nie
Opis: Obiekt zawierajcy pary klucz-warto, gdzie klucz reprezentuje nazw zdarzenia
danego komponentu, a warto zawiera metod obsugujc, ktra ma zosta skojarzona
z tym zdarzeniem.
W przedstawionym przykadzie pocztkowe kroki podejmowane przez metod $create
s takie same jak w przykadzie ilustrujcym techniki stosowania parametru properties.
Metoda $createweryfikuje otrzymany typ, tworzy komponent, wykonuje metod beginUpdate, po czym ustawia waciwoci tego komponentu.
Po ustawieniu waciwoci nastpuje przetworzenie parametru events. Podobnie jak
w przypadku parametru properties, parametr events jest obiektem zawierajcym zbir
par klucz-warto. Elementy obiektu events s iteracyjnie przeszukiwane, a kada odnaleziona para klucz-warto dodaje metod obsugujc do odpowiedniego zdarzenia a do
wyczerpania caego zbioru lub wystpienia jakiego bdu. Nastpnie take podobnie
jak w przypadku parametru properties przekazane w ten sposb metody obsugujce
s dodawane do zdarze za pomoc odpowiedniej metody. W tym przypadku klucz,
czyli unhandledErrorOccurred, jest automatycznie poprzedzany przedrostkiem add_
otrzymujemy wic metod add_unhandledErrorOccurred. Wspomniany acuch jest
nastpnie traktowany jako funkcja naleca do definicji danego komponentu. Jeli metod
add_unhandledErrorOccurred rzeczywicie uda si odnale w tym komponencie i jeli
warto tej pary klucz-warto jest obiektem typu Function, obiekt ten jest przekazywany
na wejciu metody add_unhandledErrorOccurred jako jej parametr (w ten sposb wskazana
metoda jest dodawana do zbioru metod obsugujcych dane zdarzenie).
W naszym przykadzie uycia wyraenia $create zdefiniowano metod obsugujc zdarzenie w ramach samego wywoania. Okazuje si, e tak zdefiniowana metoda moe by z powodzeniem skojarzona ze zdarzeniem unhandledErrorOccurred. Alternatywnym sposobem przekazania tej metody jest predefiniowanie funkcji obsugujcej nasze zdarzenie (patrz listing 3.13).

LISTING 3.13. Predefiniowanie metody obsugujcej zdarzenie


function unhandledErrorHandler(sender, args) {
alert(args._stackTrace);
}
$create(
MyComponent,
{address: "ul. Faszywa 123" },
{
unhandledErrorOccurred:
unhandledErrorHandler
}
},
null,
null);

Typ Sys.Component
Predefiniowanie metod obsugujcych zdarzenia umoliwia ich wielokrotne wykorzystywanie take w innych komponentach lub wywoywanie proceduralne.
Co wicej, gdybymy chcieli obsugiwa zdarzenie za pomoc metody zawartej w naszym
komponencie (zamiast jak w kodzie z listingu 3.13 korzysta z funkcji globalnej),
powinnimy wykona dodatkowy krok polegajcy na utworzeniu delegacji obejmujcej nasz
metod obsugujc, aby kontekst wskazywa na odpowiedni komponent (patrz listing 3.14).

LISTING 3.14. Opakowanie metody obsugujcej w ramach delegacji


MyOtherComponent = function() {
MyOtherComponent.initializeBase(this);
this._subComponent = null;
};
MyOtherComponent.prototype = {
_unhandledErrorOccurred: function(sender, args) {
var stackTrace = args._stackTrace;
if (typeof(stackTrace) != "undefined") {
alert (" lad stosu tego bdu: " + stackTrace);
}
},
initialize: function() {
MyOtherComponent.callBaseMethod(this, "initialize");
this._errorHandler =
$create(
ErrorHandler,
{
id:"ApplicationErrorHandler",
disableErrorPublishing: true
},
{
unhandledErrorOccurred:
Function.createDelegate (
this,
this._unhandledErrorOccurred
)
},
null,
null);
// powoduje wygenerowanie bdu
var nullObj = null;
nullObj.causeError;
}
};
MyOtherComponent.registerClass("MyOtherComponent", Sys.Component);

165

166

Rozdzia 3. Komponenty
We fragmencie kodu metody initialize typu MyOtherComponent wyrnionym pogrubieniem utworzylimy egzemplarz komponentu ErrorHandler. Metod obsugujc przypisywan do zdarzenia unhandledErrorOccurred umieszczamy w delegacji, aby umoliwi
wykonywanie metody _unhandledErrorOccurred z wykorzystaniem waciwego kontekstu.

UWAGA Przedrostki funkcji


Przy okazji omawiania technik ustawiania waciwoci i dodawania metod obsugujcych zdarzenia za pomoc metody $create moglimy obserwowa sposoby poprzedzania waciwoci przedrostkami get_ i set_ oraz metod obsugujcych przedrostkiem
add_. Okazuje si, e wymienione przedrostki nie tylko maj charakter estetyczny, ale
take znaczenie funkcjonalne.

Stosowanie parametru references


Za porednictwem parametru references moemy przypisa jeden komponent waciwoci innego komponentu i tym samym czy ze sob rne komponenty. By moe
zastanawiasz si, po co mielibymy wykorzystywa do tego celu odrbny parametr, skoro
rwnie dobrze mona by osign ten cel za pomoc parametru properties. Dodatkowy
parametr jest niezbdny, poniewa podczas tworzenia egzemplarzy komponentw klienckich
z wykorzystaniem kodu serwera nie znamy kolejnoci tworzenia tych komponentw. Jeli
korzystamy z odrbnego parametru, w ramach procesu inicjalizacji realizowanego przez
obiekt Sys.Application referencje do komponentw s traktowane w specjalny sposb,
a ich przypisywanie nastpuje dopiero po utworzeniu wszystkich komponentw. W ten
sposb udao si wyeliminowa problemy zwizane z prbami uzyskiwania przez komponenty dostpu do innych, jeszcze nieistniejcych komponentw.
Aby zilustrowa znaczenie parametru references, przekazujemy jeden komponent
w formie referencji do innego komponentu za porednictwem wspomnianego parametru
wyraenia $create. W tym celu musimy najpierw utworzy komponent, ktry bdzie
mona wykorzysta w roli referencji do naszego drugiego komponentu. Na listingu 3.15
przedstawiono dwa przykadowe wyraenia $create. Dla jasnoci w prezentowanym scenariuszu posuylimy si dwoma fikcyjnymi komponentami.

LISTING 3.15. Przypisywanie referencji


// tworzy pierwszy komponent
$create(
MyComponent,
{
id: "MyFirstComponent"
},
null
null,
null
);

Typ Sys.Component
// tworzy drugi komponent i przypisuje go waciwoci nazwanej
// subComponent i nalecej do pierwszego komponentu
$create(
MyComponent,
{
id: "MySecondComponent"
},
null,
{
subComponent:"MyFirstComponent"
},
null
);

references

Oczekiwany typ: Object


Wymagany: Nie
Opis: Obiekt zawierajcy pary klucz-warto, gdzie klucz reprezentuje waciwo
komponentu, a warto reprezentuje komponent, ktry tej waciwoci ma zosta
przypisany. Warto powinna zawiera identyfikator tego komponentu.
Po wykonaniu kodu odpowiedzialnego za przypisywanie zdarze metoda $create
przystpuje do przetwarzania parametru references. Podobnie jak parametry properties
i events, parametr references ma posta obiektu z parami klucz-warto, gdzie klucz
reprezentuje waciwo, ktrej chcemy przypisa komponent, a warto reprezentuje identyfikator komponentu, ktry ma zosta przypisany tej waciwoci.
Na listingu 3.15 obiekt przekazywany za porednictwem parametru references wyrniono pogrubieniem. Jak wida, chcemy przypisa waciwoci subComponent tworzonego
komponentu komponent z identyfikatorem MyFirstComponent. Podobnie jak omwiona
wczeniej metoda setProperties, metoda setReferences szuka metody ustawiajcej,
ktrej nazwa odpowiada nazwie metody danej waciwoci poprzedzonej przedrostkiem
set_. W tym przypadku bdzie to metoda nazwana set_subComponent. Po odnalezieniu
tej metody wyraenie $create szuka w zbiorze komponentw zarzdzanych przez obiekt
Sys.Application komponentu z identyfikatorem MyFirstComponent. Jeli uda si odnale
ten komponent, zostanie wywoana metoda ustawiajca set_subComponent, ktrej parametr
bdzie reprezentowa znaleziony komponent.

UWAGA Odnajdywanie komponentw zarzdzanych


Za porednictwem metody Sys.Application.find moemy odnajdywa zarejestrowane komponenty wedug identyfikatorw. Przy okazji szczegowego omawiania klasy
Sys.Application (w rozdziale 4.) przyjrzymy si uwanie midzy innymi jej metodzie find.

167

168

Rozdzia 3. Komponenty

WSKAZWKA Kolejno tworzenia komponentw


Jak ju wspomniano, warunkiem prawidowego dziaania tego kodu jest dostpno egzemplarza komponentu MyFirstComponent przed wykonaniem drugiego wyraenia $create. Referencje do nieistniejcych komponentw mog by stosowane
tylko wtedy, gdy obiekt Sys.Application znajduje si w fazie inicjalizacji. Omwimy
to zagadnienie bardziej szczegowo w rozdziale 4.

Stosowanie parametru element


Ostatni parametr metody $create, czyli element, reprezentuje wskanik do elementu modelu DOM. Poniewa parametr element moe by stosowany tylko podczas tworzenia
nowego zachowania lub nowej kontrolki, omwimy go przy okazji analizy procesw definiowania i tworzenia wymienionych typw.

Podsumowanie wiedzy o komponentach


Komponent definiuje si nie tylko jako obiekt dziedziczcy po klasie Sys.Component, ale
te jako obiekt zarzdzany przez obiekt Sys.Application. Oznacza to, e samo utworzenie
egzemplarza typu dziedziczcego po klasie Sys.Component za pomoc sowa kluczowego
new nie powoduje automatycznej rejestracji tego egzemplarza w obiekcie Sys.Application.
Aby dokona takiej automatycznej rejestracji, musimy uy metody $create. Metoda
$create dodatkowo realizuje takie zadania jak ustawianie waciwoci, kojarzenie metod
obsugujcych ze zdarzeniami, przypisywanie referencji do innych komponentw i wizanie tworzonego komponentu z elementem DOM (o czym przekonamy si za chwil, przy
okazji omawiania kontrolek i zachowa). Co wicej, ta sama metoda automatycznie wywouje metod initialize tworzonego komponentu w ramach tej metody moemy
umieci dowolny kod, ktry powinien by wykonywany po ustawieniu wszystkich waciwoci, dodaniu metod obsugujcych zdarzenia i przypisaniu referencji do komponentw.

Kontrolki
Kontrolka jest specjalnym rodzajem komponentu bezporednio zwizanym z elementem
modelu DOM. Pojedynczy element DOM moe by zwizany z tylko jedn kontrolk,
a wspomniana kontrolka musi by zwizana tylko z tym konkretnym elementem.
Poniewa z pojedynczym elementem DOM mona zwiza tylko jedn kontrolk,
w praktyce moliwe zastosowania tego rodzaju komponentw ograniczaj si do sytuacji,
w ktrych chcemy dysponowa pen kontrol nad tym elementem modelu DOM. W sytuacji,
gdy nie jestemy pewni swoich oczekiwa odnonie danego elementu DOM, powinnimy
raczej uy zachowania, po czym w razie koniecznoci zastpi je kontrolk. W praktyce
przechodzenie od kontrolek do zachowa (i odwrotnie) nie jest zbyt trudne i nie wymaga
zbyt wielu zmian w kodzie rdowym.

Kontrolki
Poniewa kontrolka jest bezporednio zwizana z elementem modelu DOM, zawiera
metody stworzone specjalnie z myl o uzyskiwaniu dostpu i wykonywaniu operacji na
skojarzonym z ni elementem DOM. W tabeli 3.5 szczegowo omwiono metody kontrolki odpowiedzialne za dostp i modyfikacje powizanego elementu DOM.

TABELA 3.5. Metody klasy Sys.UI.Control


Nazwa metody

Opis

Skadnia

set_id

Przykrywa metod set_id


brak prawidowych zastosowa
komponentu. Generuje bd,
poniewa identyfikator kontrolki
zawsze jest skojarzony
z identyfikatorem elementu DOM.

get_id

Przykrywa metod get_id


komponentu. Zwraca identyfikator
elementu DOM zwizanego z dan
kontrolk.

return ctrl.get_id();

get_visible

Zwraca warto zwrcon


przez wywoanie metody

return ctrl.get_visible();

Sys.UI.DOMElement.getVisible

elementu DOM zwizanego z dan


kontrolk.
set_visible

Wywouje metod
Sys.UI.DomElement.setVisible,

ctrl.set_visible
(visibility);

korzystajc z elementu DOM


zwizanego z dan kontrolk
i wartoci logicznej przekazanej
na wejciu metody set_visible.
get_visibility
Mode

Wywouje metod Sys.UI.Dom


Element.getVisibilityMode,

return ctrl.get_visibility
Mode();

korzystajc z elementu DOM


zwizanego z dan kontrolk.
set_visibility
Mode

Wywouje metod Sys.UI.Dom


Element.setVisibilityMode,
korzystajc z elementu DOM
zwizanego z dan kontrolk
i parametru typu Sys.UI.Visibi
lityMode przekazanego na wejciu
metody set_visibilityMode.

get_element

Zwraca element modelu DOM


zwizany z dan kontrolk.

ctrl.set_visibilityMode(
Sys.UI.VisibilityMode
);

return ctrl.get_element();

169

170

Rozdzia 3. Komponenty
TABELA 3.5. Metody klasy Sys.UI.Control cig dalszy
Nazwa metody

Opis

Skadnia

addCssClass

Wywouje metod

ctrl.addCssClass
(cssClassName)

Sys.UI.DomElement.addCssClass,

korzystajc z elementu DOM zwizanego


z dan kontrolk i nazwy dodawanej
klasy CSS.
removeCssClass

Wywouje metod
Sys.UI.DomElement.removeCssClass,

ctrl.removeCssClass
(cssClassName);

korzystajc z elementu DOM zwizanego


z dan kontrolk inazwy usuwanej klasy CSS.
toggleCssClass

Wywouje metod
Sys.UI.DomElement.toggleCssClass,

ctrl.toggleCssClass
(cssClassName);

korzystajc z elementu DOM zwizanego


z dan kontrolk i nazwy wczanej klasy CSS.
dispose

Przykrywa metod dispose klasy


Sys.Component. Wywouje metod
dispose klasy bazowej, przypisuje warto
undefined waciwoci expando element
i usuwa z danego komponentu referencj
do elementu DOM.

ctrl.dispose();

Nowe pojcia
Oprcz metod, ktre uzyskuj dostp do elementu DOM skojarzonego z dan kontrolk
i operuj na tym elemencie, twrcy klasy Sys.UI.Control wprowadzili dwa nowe pojcia:
rodzic kontrolki (ang. controls parent) i znana z frameworku ASP.NET propagacja zdarze
(ang. event bubbling).

Rodzic kontrolki
Waciwo parent kontrolki zawiera wskanik do innej kontrolki. Warto tej waciwoci jest wyznaczana na dwa sposoby. Jeli waciwo parent ustawiono wprost za pomoc
metody set_parent, warto przekazana za porednictwem parametru tej metody jest
rodzicem danej kontrolki. Jeli rodzica nie okrelono wprost, w jego poszukiwaniu jest
wykorzystywany wskanik parentNode elementu DOM a do odnalezienia elementu skojarzonego z jak kontrolk wanie ta kontrolka jest traktowana jako rodzic naszej
kontrolki.
Metody stworzone z myl o operowaniu na wskaniku do rodzica kontrolki opisano
w tabeli 3.6.

Kontrolki
TABELA 3.6. Metody typu Sys.UI.Control zwizane z rodzicem kontrolki
Nazwa metody

Opis

Skadnia

get_parent

Zwraca wprost ustawionego rodzica


lub pierwsz kontrolk napotkan
podczas przetwarzania wskanika
parentNode elementu DOM.

var parent =
ctrl.get_parent();

set_parent

Wprost ustawia rodzica danej


kontrolki.

ctrl.set_parent(otherCtrl);

Propagacja zdarze
Propagacja zdarze jest technik polegajc na przekazywaniu zdarze w gr hierarchii
za porednictwem wskanika do rodzica i tym samym umoliwianiu kontrolkom
rodzicw obsugi tych zdarze.
Mechanizm propagowania zdarze zaimplementowany w bibliotece Microsoft AJAX
Library przypomina technik propagowania zdarze z wykorzystaniem kontrolek ASP.NET.
Kontrolka rozpoczyna ten proces, wywoujc metod raiseBubbleEvent i przekazujc na
jej wejciu rdo i argumenty zdarzenia. W ciele metody raiseBubbleEvent jest uzyskiwany rodzic danej kontrolki za porednictwem doczonej do niej metody get_parent, po
czym nastpuje wywoanie metody onBubbleEvent dla tego rodzica. Domylna implementacja metody onBubbleEvent klasy Sys.UI.Control zwraca warto false, oznaczajc,
e dana kontrolka nie obsuya tego zdarzenia i e proces propagacji powinien trwa dalej
(zdarzenie powinno by przekazywane w gr hierarchii).
Jeli dana kontrolka jest zainteresowana obsug tak propagowanego zdarzenia, moe
to zrobi, przykrywajc domyln implementacj metody onBubbleEvent. W przykrytej
metodzie naley okreli, czy proces propagowania zdarzenia powinien by kontynuowany,
czy zatrzymany na poziomie tej kontrolki. Jeli propagacja zdarzenia zatrzymuje si na
rodzicu danej kontrolki, metoda onBubbleEvent zwraca warto true. Jeli jednak dane zdarzenie ma by propagowane dalej, w gr drzewa rodzicw kontrolek, metoda onBubbleEvent
zwraca warto false.
Metody stworzone z myl o technice propagowania zdarze szczegowo opisano
w tabeli 3.7.

UWAGA Dodatkowe metody


Poniewa klasa Sys.UI.Control dziedziczy po klasie bazowej Sys.Component, wszystkie
metody dostpne dla obiektw klasy Sys.Component s dostpne take dla egzemplarzy
klasy Sys.UI.Control.

171

172

Rozdzia 3. Komponenty
TABELA 3.7. Metody typu Sys.UI.Control zwizane z propagowaniem zdarze
Nazwa metody

Opis

Skadnia

onBubbleEvent

Metoda onBubbleEvent jest czci


frameworku propagowania zdarze.
Aby zapewni jak funkcjonalno tej
metody, naley j przykry. Metoda
onBubbleEvent domylnie zwraca
warto false.

Metoda onBubbleEvent
jest automatycznie
wywoywana
przez metod
raiseBubbleEvent.

raiseBubbleEvent

Metoda raiseBubbleEvent jest czci


frameworku propagowania zdarze.
Przeszukuje list rodzicw kontrolki
i uruchamia metod onBubbleEvent
kadego z tych obiektw.

ctrl.raiseBubbleEv
ent(source, args);

Definiowanie nowej kontrolki


Podobnie jak w przypadku nowych komponentw, podczas definiowania nowych kontrolek bdziemy stosowali model prototypowy opisany w rozdziale 2. Aby zilustrowa
sposb definiowania nowej kontrolki, utworzymy now kontrolk skojarzon z polem
tekstowym (typu textbox), ktra umoliwi nam tylko wpisywanie wartoci liczbowych. Na listingu 3.16 przedstawiono kod niezbdny do zdefiniowania nowej kontrolki
NumberOnlyTextBox.

LISTING 3.16. Definiowanie nowego typu kontrolki


/// <reference name="MicrosoftAjax.js"/>
NumberOnlyTextBox = function(element) {
NumberOnlyTextBox.initializeBase(this, [element]);
this._keyDownDelegate = null;
};
NumberOnlyTextBox.prototype = {
initialize: function() {
NumberOnlyTextBox.callBaseMethod(this,'initialize');
this._keyDownDelegate =
Function.createDelegate(this, this._keyDownHandler);
$addHandler(this.get_element(), "keydown", this._keyDownDelegate);
},
dispose: function() {
$removeHandler
(this.get_element(), "keydown", this._keyDownDelegate);
this._keyDownDelegate = null;
NumberOnlyTextBox.callBaseMethod(this, 'dispose');
},

Kontrolki
_keyDownHandler: function(e) {
return ((e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode == 8));
}
};
NumberOnlyTextBox.registerClass("NumberOnlyTextBox", Sys.UI.Control);

Jak wida na listingu 3.16, istniej dwie wane rnice dzielce kontrolk NumberOnlyTextBox
od zadeklarowanego wczeniej komponentu ErrorHandler.
Po pierwsze, funkcj klasy bazowej naszej kontrolki NumberOnlyTextBox peni typ
Sys.UI.Control, nie jak wczeniej typ Sys.Component.
Po drugie, konstruktor naszego nowego typu otrzymuje parametr element i przekazuje go
do konstruktora swojej klasy bazowej za porednictwem metody initializeBase. Parametr
element reprezentuje element modelu DOM, ktry ma zosta skojarzony z dan kontrolk.
W odpowiedzi na przekazanie wspomnianego elementu na wejciu konstruktora klasy
Sys.UI.Control s podejmowane trzy dziaania. Po pierwsze, tak przekazany element
DOM jest weryfikowany pod ktem ewentualnego zwizku z inn kontrolk. Jeli okae
si, e taki zwizek istnieje, konstruktor klasy Sys.UI.Control generuje bd i cay proces
tworzenia kontrolki koczy si niepowodzeniem. W przeciwnym razie konstruktor przystpuje do drugiego kroku, polegajcego na przypisaniu tego elementu DOM wewntrznej
skadowej _element. I wreszcie kontrolka sama jest przypisywana temu elementowi modelu
DOM z wykorzystaniem waciwoci expando nazwanej control. Gdybymy utworzyli
referencj do element zwizanego z nasz kontrolk, moglibymy uzyska dostp do zwizanej z nim kontrolki za pomoc nastpujcego wywoania:
$get("TextBox1").control;

Na listingu 3.17 przedstawiono kod demonstrujcy omwione powyej reguy na


przykadzie naszego nowo utworzonego typu kontrolki NumberOnlyTextBox.

LISTING 3.17. Tworzenie egzemplarza typu NumberOnlyTextBox z wykorzystaniem sowa kluczowego new
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Control Testing!</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="SM1" runat="server" />
// dla uproszczenia pominito definicj typu NumberOnlyTextBox
<asp:TextBox ID="txtBox1" runat="server" Width="150px" />
<script type="text/javascript">
var numberOnlyTextBox =

173

174

Rozdzia 3. Komponenty
new NumberOnlyTextBox($get("txtBox1"));
// wywietla txtBox1
alert ("Identyfikator elementu zwizanego z kontrolk numberOnlyTextBox: " +
numberOnlyTextBox.get_element().id);
// wywietla txtBox1
alert ("Identyfikator elementu zwizanego z kontrolk numberOnlyTextBox: " +
$get("txtBox1").control.get_id());
// generuje bd JavaScriptu, poniewa dana kontrolka
// jest ju zwizana z polem txtBox1
var numberOnlyTextBox2 =
new NumberOnlyTextBox ($get("txtBox1"));
</script>
</form>
</body>
</html>

Tworzenie kontrolki
Na listingu 3.17 do utworzenia nowego egzemplarza naszego typu NumberOnlyTextBox
wykorzystalimy sowo kluczowe new. Z podrozdziau powiconego naszemu komponentowi wiemy ju, e metoda $create wykonuje cay pakiet zada i nie ogranicza si
tylko do utworzenia nowego egzemplarza wskazanego typu, a poniewa nasz nowy typ dziedziczy po klasie Sys.UI.Control, ktra z kolei dziedziczy po klasie Sys.Component, moemy
uy wyraenia $create w taki sam sposb jak w przypadku komponentu ErrorHandler.
Zamiast traci czas na ponowne omawianie metody $create, ograniczymy si tylko do
analizy zastosowa parametru element, poniewa tylko w jego przypadku mamy do czynienia z istotnymi rnicami. Podstaw naszych analiz bdzie kod z listingu 3.17, ktry
zmodyfikujemy przez zastosowanie metody $create. Kod powstay w wyniku tych zmian
wprowadzono na listingu 3.18.

LISTING 3.18. Tworzenie egzemplarza typu NumberOnlyTextBox z wykorzystaniem metody $create


<html>
<head runat="server">
<title>Test kontrolki!</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="SM1" runat="server" />
// dla uproszczenia pominito definicj typu NumberOnlyTextBox
<asp:TextBox ID="txtBox1" runat="server" Width="150px" />

Zachowania
<script type="text/javascript">
$create(
NumberOnlyTextBox,
null,
null,
null,
$get("txtBox1")
);
</script>
</form>
</body>
</html>

Kod wyrniony pogrubieniem zawiera wywoanie metody $create. Warto zwrci


szczegln uwag na sposb przekazania wywoania $get("txtBox1") za porednictwem
parametru element metody $create. W czasie tworzenia nowego egzemplarza klasy
NumberOnlyTextBox metoda $create sprawdza, czy typ NumberOnlyTextBox dziedziczy po
typie Sys.UI.Control lub Sys.UI.Behavior. Jeli tak (a tak jest w tym przypadku), metoda
$create wykorzystuje parametr element w roli argumentu wywoywanego konstruktora
(podobne rozwizanie zastosowalimy na listingu 3.17 przed uyciem metody $create do
utworzenia naszej nowej kontrolki).

UWAGA Ustawianie identyfikatora kontrolki


Inaczej ni w przypadku komponentw i zachowa, bezporednie ustawianie identyfikatorw kontrolek nie jest moliwe. Identyfikator kontrolki zawsze jest tosamy
z identyfikatorem powizanego z ni elementu modelu DOM.

Podsumowanie wiedzy o kontrolkach


Kontrolki w niewielkim stopniu rni si od komponentw (klasa komponentw jest
typem bazowym klas kontrolek). Najwaniejsza rnica polega na koniecznoci zwizania
kadej kontrolki z pojedynczym elementem modelu DOM (w przypadku komponentw
istnienie tego rodzaju zwizkw nie jest konieczne).

Zachowania
Zachowanie to kolejny specjalny rodzaj komponentu zwizany z elementami modelu DOM.
Podobnie jak kontrolki, zachowania musz by skojarzone z elementami DOM. Okazuje
si jednak, e w inaczej ni w przypadku kontrolek, pojedynczy element DOM moe by
zwizany z wicej ni jednym zachowaniem.

175

176

Rozdzia 3. Komponenty
W wymiarze praktycznym zachowania definiuj oczekiwany sposb zachowywania si
elementu DOM. Moemy na przykad zdecydowa, e dany element DOM powinien by
zwijany do pojedynczego wiersza, pywa na stronie bd wypenia ca dostpn przestrze na ekranie. Wszystkie te zachowania moemy doczy do elementu modelu DOM
wanie za pomoc egzemplarzy typw zachowa.
Aby uatwi nam definiowanie nowych typw zachowa i korzystanie z egzemplarzy
tych typw, typ bazowy Sys.Behavior definiuje kilka dodatkowych metod, uzupeniajcych
zbir metod oferowanych przez jego typ bazowy Sys.Component. Metody klasy Sys.Behavior
szczegowo omwiono w tabeli 3.8.

TABELA 3.8. Metody klasy Sys.UI.Behavior


Nazwa metody

Opis

Skadnia

get_element

return behavior.
Zwraca element modelu dom
zwizany z danym zachowaniem. get_element();

get_name

Zwraca nazw danego zachowania. return behavior.


get_name();
Jeli wprost okrelono nazw
danego zachowania, zwracana jest
wanie ta nazwa. W przeciwnym
razie metoda get_name zwraca
skrcon nazw typu tego
zachowania.

set_name

Ustawia nazw danego


zachowania. Nazwa ustawiana
w ten sposb musi by unikatowa.
Nazw zachowa nie mona
ustawia po ich inicjalizacji.
Nazwa zachowania nie moe si
rozpoczyna od znaku biaego,
nie moe si koczy znakiem
biaym, nie moe te by
acuchem pustym.

behavior.set_name
("HiddenElm");

initialize

Wywouje metod initialize


klasy bazowej. Kojarzy dane
zachowanie z odpowiednim
elementem DOM przez dodanie
do tego elementu waciwoci
expando z nazw danego
zachowania.

behavior.initialize();

Zachowania
TABELA 3.8. Metody klasy Sys.UI.Behavior cig dalszy
Nazwa metody

Opis

Skadnia

dispose

Przykrywa metod dispose klasy Sys. behavior.dispose();


Component. Wywouje metod
dispose klasy bazowej, usuwa
z elementu DOM waciwo
expando reprezentujc nazw
danego zachowania i usuwa
referencj do tego elementu
z samego zachowania.

get_id

return behavior.
Zwraca warto waciwoci id
get_id();
danego komponentu (jeli t
warto ustawiono). Jeli warto
tej waciwoci nie zostaa
ustawiona, metoda get_id zwraca
identyfikator elementu DOM
powizanego z tym zachowaniem
i nazw samego zachowania.

Sys.UI.Behavior.
getBehaviorsByType

Zwraca wszystkie zachowania


doczone do elementu DOM
okrelonego typu.

Sys.UI.Behavior.
getBehaviorByName

return Sys.UI.Behavior.
Zwraca zachowanie doczone
do wskazanego elementu modelu getBehaviorByName
(element, behaviorName)
DOM (jeli takie zachowania
istniej).

Sys.UI.Behavior.
getBehaviors

return Sys.UI.Behavior.
Zwraca kopi zachowa
getBehaviors(element);
doczonych do wskazanego
elementu DOM. Jeli okrelony
element modelu DOM nie jest
zwizany z adnymi zachowaniami,
metoda getBehaviors zwraca
tablic pust.

return Sys.UI.Behavior.
getBehaviorsByType
(element, typeName)

Definiowanie zachowania
Podobnie jak podczas definiowania nowych komponentw i nowych kontrolek, definiujc
nowe zachowania posugujemy si modelem prototypowym omwionym w rozdziale 2.
Zamiast tworzy od podstaw nowy przykad, odpowiednio zmodyfikujemy przedstawiony
w poprzednim podrozdziale kod definiujcy kontrolk NumberOnlyTextBox. Na listingu 3.19
przedstawiono kod niezbdny do zdefiniowania zachowania NumberOnlyTextBox.

177

178

Rozdzia 3. Komponenty
LISTING 3.19. Definiowanie typu zachowania
/// <reference name="MicrosoftAjax.js"/>
NumberOnlyTextBox = function(element) {
NumberOnlyTextBox.initializeBase(this, [element]);
this._keyDownDelegate = null;
};
NumberOnlyTextBox.prototype = {
initialize: function() {
NumberOnlyTextBox.callBaseMethod(this,'initialize');
this._keyDownDelegate =
Function.createDelegate(this, this._keyDownHandler);
$addHandler(this.get_element(), "keydown", this._keyDownDelegate);
},
dispose: function() {
$removeHandler
(this.get_element(), "keydown", this._keyDownDelegate);
this._keyDownDelegate = null;
NumberOnlyTextBox.callBaseMethod(this, 'dispose');
},
_keyDownHandler: function(e) {
return ((e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode == 8));
}
};
NumberOnlyTextBox.registerClass("NumberOnlyTextBox", Sys.UI.Behavior);

Jak wida, kod definiujcy nasze zachowanie NumberOnlyTextBox niemal niczym nie
rni si od kodu definiujcego wczeniej tak samo nazwan kontrolk. Rnice sprowadzaj si do rezygnacji z typu bazowego Sys.UI.Control na rzecz typu Sys.UI.Behavior.
Podobnie jak konstruktor klasy Sys.UI.Control, konstruktor typu Sys.UI.Behavior
otrzymuje na wejciu parametr reprezentujcy element modelu DOM. W ciele tego konstruktora warto wspomnianego parametru jest przypisywana wewntrznej skadowej
_element, co jest rwnoznaczne ze skojarzeniem odpowiedniego elementu DOM z tworzonym zachowaniem. Nastpnie nasze zachowanie jest dodawane do waciwoci expando nazwanej _behaviors. Waciwo expando _behaviors pod pewnymi wzgldami
przypomina waciwo control stosowan dla kontrolek, ale ma posta tablicy, ktra
moe reprezentowa wicej ni jedno zachowanie zwizane z danym elementem DOM.

Tworzenie zachowania
Z podrozdziaw powiconych komponentom i kontrolkom wiemy, e najlepszym sposobem
konstruowania nowych egzemplarzy typw dziedziczcych po klasie Sys.Component jest
korzystanie z metody $create nie inaczej jest w przypadku zachowa.

Zachowania
W praktyce proces tworzenia zachowania przebiega dokadnie tak samo jak proces
tworzenia kontrolki, zatem kod przedstawiony ju na listingu 3.18 w zupenoci wystarczy
jako przykad tego rozwizania.
Okazuje si jednak, e inaczej ni w przypadku kontrolek, podczas tworzenia zachowa
mog wystpowa dwa powane problemy cile zwizane z unikatowoci zachowa.

Problemy zwizane z unikatowoci zachowa


Z pierwszym problemem mamy do czynienia w sytuacji, gdy identyfikator (waciwo id)
zachowania nie jest ustawiona i gdy jest generowany automatycznie na podstawie skojarzonego z tym zachowaniem elementu DOM i nazwy samego zachowania. Poniewa
wspomniana warto jest generowana automatycznie, jest wielce prawdopodobne, e ten
sam identyfikator zostanie przypisany wicej ni jednemu zachowaniu. Jeli ten sam
identyfikator zostanie wygenerowany dla wielu zachowa, prba rejestracji drugiego
i kadego kolejnego zachowania z tego zbioru w obiekcie Sys.Application zakoczy si
niepowodzeniem, poniewa komponenty zarzdzane przez ten obiekt musz mie unikatowe identyfikatory. Opisany problem zademonstrowano na listingu 3.20.

LISTING 3.20. Tworzenie zachowa z tym samym identyfikatorem


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Test zachowa!</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="SM1" runat="server" />
// dla uproszczenia pominito definicj typu NumberOnlyTextBox
<asp:TextBox ID="txtBox1" runat="server" Width="150px" />
<script type="text/javascript">
$create(
NumberOnlyTextBox,
null,
null,
null,
$get("txtBox1")
);
// to wywoanie spowoduje bd, poniewa identyfikator tego komponentu
// bdzie taki sam jak w poprzednio zarejestrowanym zachowaniu
$create(
NumberOnlyTextBox,
null,
null,
null,

179

180

Rozdzia 3. Komponenty
$get("txtBox1")
);
</script>
</form>
</body>
</html>

Poniewa w przedstawionym przykadzie nie ustawilimy wprost nazw ani identyfikatorw tworzonych zachowa, waciwoci id obu tych zachowa bd miay warto txtBox1$NumberOnlyTextBox. Automatycznie generowany identyfikator zachowania skada
si z identyfikatora powizanego elementu DOM (w tym przypadku txtBox1), symbolu $
oraz nazwy samego zachowania, ktra w razie braku nazwy okrelonej wprost jest zastpowana nazw typu zachowania (bez ewentualnych przestrzeni nazw).

UWAGA Nazwa NumberOnlyTextBox


W naszym przykadzie automatycznie generowana nazwa zachowania jest identyczna
z nazw typu, czyli NumberOnlyTextBox.
Gdyby typ naszego zachowania nalea do jakich przestrzeni nazw, na przykad
MyProject.Behaviors.NumberOnlyTextBox, automatycznie generowana nazwa tego
zachowania i tak miaaby posta NumberOnlyTextBox.
Kiedy drugie zachowanie sprbuje si zarejestrowa w obiekcie Sys.Application,
zostanie wygenerowany bd w zwizku z istnieniem ju zarejestrowanego komponentu
z takim samym identyfikatorem.
Aby rozwiza ten problem, naley wprost ustawi albo nazw, albo identyfikator naszego zachowania. Niezalenie od tego, ktr waciwo zdecydujemy si ustawi, uyta
warto musi by unikatowa. Jeli ustawimy waciwo id, uyty identyfikator powinien
by unikatowy w skali wszystkich komponentw. Jeli ustawimy waciwo name, uyta
nazwa powinna by unikatowa w skali wszystkich zachowa skojarzonych z tym samym
elementem modelu DOM. Na listingu 3.21 przedstawiono kod, ktry prawidowo tworzy
dwa zachowania zwizane z tym samym polem typu textbox.

LISTING 3.21. Ustawianie identyfikatora zachowania


<script type="text/javascript">
$create(
NumberOnlyTextBox,
{id: "Behavior1" },
null,
null,
$get("txtBox1")
);

Zachowania
$create(
NumberOnlyTextBox,
{id: "Behavior2" },
null,
null,
$get("txtBox1")
);
</script>

Drugi powany problem zwizany z tworzeniem zachowa moe wystpowa w sytuacji, gdy doczamy wiele egzemplarzy tego samego zachowania do jednego elementu
modelu DOM i gdy nazwy tych zachowa nie zostay wprost ustawione. Poniewa automatycznie generowane nazwy egzemplarzy tego samego zachowania bd takie same (na
przykad NumberOnlyTextBox), nie bdziemy mogli ich odnale za porednictwem metody
Sys.UI.getBehaviorByName.
Doczanie wielu egzemplarzy tego samego zachowania do jednego elementu modelu
DOM zdarza si do rzadko, ale nie mona takiej sytuacji wykluczy. Na listingu 3.22
przedstawiono kod ilustrujcy moliwo odnajdywania tylko jednego z zachowa typu
NumberOnlyTextBox skojarzonych z naszym polem tekstowym.

LISTING 3.22. Problemy z odnajdywaniem zachowa wedug nazw


<html>
<head runat="server">
<title>Test zachowa!</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="SM1" runat="server" />
// dla uproszczenia pominito definicj typu NumberOnlyTextBox
<asp:TextBox ID="txtBox1" runat="server" Width="150px" />
<script type="text/javascript">
$create(
NumberOnlyTextBox,
{id: "Behavior1"},
null,
null,
$get("txtBox1")
);
$create(
NumberOnlyTextBox,
{id: "Behavior2"},
null,
null,

181

182

Rozdzia 3. Komponenty
$get("txtBox1")
);
var beh = Sys.UI.Behavior.getBehaviorByName
($get("txtBox1"), " NumberOnlyTextBox ");
alert (beh.get_name());
var behaviorsAssignedToDom =
Sys.UI.Behavior.getBehaviors($get("txtBox1"));
var behaviors = '';
for (var i=0; i<behaviorsAssignedToDom.length; i++) {
behaviors += behaviorsAssignedToDom[i].get_name() + " ";
}
// wywietla NumberOnlyTextBox NumberOnlyTextBox, poniewa
// zdefiniowano dwa tak samo nazwane zachowania
alert (behaviors);
</script>
</form>
</body>
</html>

Rozwizanie tego problemu wymaga ustawienia wprost nazw wszystkich tworzonych


zachowa.
Na zakoczenie tego podpunktu powiconego problemom zwizanym z tworzeniem
zachowa warto podkreli, e konsekwentne ustawianie wprost identyfikatorw i (lub)
nazw moe nam oszczdzi wielu problemw, mimo e brak wyrae ustawiajcych te
waciwoci nie zawsze powoduje generowanie bdw. Sugerujemy wic ustawianie waciwoci id oraz name dla kadego tworzonego egzemplarza zachowania niezalenie od
sytuacji. Przykad zastosowania tego wzorca przedstawiono na listingu 3.23.

LISTING 3.23. Przypisywanie identyfikatorw i nazw tworzonym egzemplarzom zachowa


<script type="text/javascript">
$create(
NumberOnlyTextBox,
{id: "Behavior1",
name: "Behavior1"},
null,
null,
$get("txtBox1")
);

Podsumowanie
$create(
NumberOnlyTextBox,
{id: "Behavior2",
name: "Behavior2"},
null,
null,
$get("txtBox1")
);
</script>

Podsumowanie wiedzy o zachowaniach


Zachowania nie rni si zbytnio od egzemplarzy swojego typu bazowego, czyli komponentw. Najwaniejsza rnica ma zwizek z koniecznoci kojarzenia zachowa z elementami modelu DOM (komponenty nie mog by kojarzone z tego rodzaju elementami).
Najwaniejsz rnic dzielc zachowania od kontrolek jest moliwo doczania do
pojedynczego elementu DOM tylko jednej kontrolki (liczba doczanych zachowa jest
nieograniczona).

Podsumowanie
W tym rozdziale omwiono komponenty, kontrolki i zachowania. Przyjrzelimy si typowi bazowemu komponentw pod ktem jego popularnych obiektw oraz sposobom rozszerzania tego typu przez kontrolki i zachowania, czyli wyspecjalizowane komponenty
zawierajce referencje do elementw modelu DOM. Omwilimy te techniki samodzielnego konstruowania egzemplarzy wszystkich trzech typw oraz sposoby realizacji tych
zada z wykorzystaniem funkcji $create.
W nastpnym rozdziale skoncentrujemy si na obiekcie Sys.Application, ktry peni
funkcj menedera wszystkich komponentw, kontrolek i zachowa. Po omwieniu wspomnianego obiektu przystpimy do analizy technik czenia elementw biblioteki Microsoft
AJAX Library z kodem frameworku ASP.NET AJAX stosowanym po stronie serwera
(w tym technik tworzenia komponentw, kontrolek i zachowa za porednictwem kodu
.NET). I wreszcie, aby ostatecznie wyczerpa temat komponentw, kontrolek i zachowa,
zajmiemy si tematem ich lokalizowania i sposobami reagowania na ich umieszczanie
w kontrolce UpdatePanel.

183

Anda mungkin juga menyukai