Język XAML (ang. Extensible Application Markup Language) jest językiem znaczników i preferowanym do tworzenia interfejsów Silverlight, które są zapisywane w plikach o rozszerzeniu .xaml. Pomimo faktu, że interfejs ten jest oprogramowywany przez język obiektowy np. C#, to trzeba mieć świadomość obiektowości XAML. Tak naprawdę każdy element tego języka jest obiektem.
W HTML4 nagłówek z reguły opisywaliśmy jako:
Treść nagłówka
Powyższa linijka to prosty przykład wyświetlenia tekstu: Witaj srebrne światełko (o rozmiarze czcionki 25) za pomocą kontrolki TextBlock. To samo jednak można osiągnąć w code-behind pliku .xaml czyli .xaml.cs:
TextBlock textBlock = new
TextBlock();
textBlock.FontSize = 25;
textBlock.Text = " Witaj
srebrne światełko";
XAML jest językiem znaczników, który bazuje na innym znacznikowym języku – XML. To oznacza, że plik .xaml złożony jest ze znaczników, a dokładniej: z tagów. W tagach znajdują się różne słowa kluczowe, które mogą oznaczać klasy, właściwości czy zdarzenia, zaś zadaniem kompilatora XAML-a jest przepisanie ich do CLR (ang. Common Language Runtime). W XAML-u zgodnie z zasadą XML, każdy tag rozpoczynający musi mieć także tag zamykający (tzw. zapis rozszerzony):
Istnieje jednak drugi sposób zapisu powyższej linijki, w którym nie używamy taga zamykającego (tzw. zapis skrócony):
Listing 1. Siatka Grid z polem tekstowym TextBox. Powyższy kod pochodzi
z solucji 2_1_SL.sln (do ściągnięcia z załączników niniejszego artykułu)
Wynikiem powyższego przykładu
będzie:
Zgodnie ze specyfikacją XML, na podstawie którego powstał
XAML, poprawny dokument może mieć tylko jeden element główny – korzeń dokumentu
(czyli tzw. root element).
Głównym elementem pliku MainPage.xaml (plik z solucji 2_1_SL.sln ) jest UserControl – klasa, dzięki której programista może tworzyć obiekt
pod tytułem: kontrolka użytkownika. Co więcej, UserControl jest specyficzną
klasą, po której mogą dziedziczyć kontrolki tworzone przez użytkownika. Pisanie
aplikacji w Silverlight jest zawsze tworzeniem nowej kontrolki (każdy kolejny
plik .xaml będzie rozpoczynał się od znacznika UserControl).
Wewnątrz kontroli UserControl może znaleźć się maksymalnie JEDEN
element – zwykle jest to kontener. W naszym przykładzie (2_1_SL) tym kontenerem
jest siatka Grid.
UWAGA: popularnymi kontenerami używanymi w SL są: Canvas,
StackPanel oraz Grid. Kanwa (ang. Canvas)
charakteryzuje się pozycjonowaniem absolutnym – podajemy dokładną pozycję
obiektu, który pozycjonujemy, podczas gdy panel stosu (ang. Stack Panel) oraz siatka (ang. Grid) umożliwiają pozycjonowanie
relatywne.
Korzeń UserControl posiada m.in. właściwości: DesignWidth oraz DesignHeight. Określają one odpowiednio szerokość i wysokość
kontrolki, czyli tak naprawdę pisanej przez nas aplikacji. Można tutaj podać
dowolne liczby lub usunąć obie właściwości (w takiej sytuacji, gdy usuniesz DesignWidth oraz DesignHeight, sprawisz,
że nasz aplikacja będzie zajmowała całą dostępną powierzchnię w przeglądarce i
będzie się dostosowywała do wielkości przeglądarki.
Na listingu 1 możesz znaleźć atrybut xmlns. Definiuje on domyślną przestrzeń nazw (ang. Namespace)
aplikacji SL. W domyślnej przestrzeni nazw zawarte są definicje obiektów,
których można użyć w aplikacji, czyli np. Grid, TextBlock czy Run. Gdybyśmy
usunęli xmlns z kodu, wówczas kompilator nie rozpoznałby tych elementów i
zwróciłby błąd.
Jako wartość domyślnej przestrzeni nazw podaje się
hiperłącze do mapowanej przestrzeni nazw, czyli:
Listing 2. Domyślna przestrzeń nazw w XAML-u
Obok domyślnej przestrzeni nazw,
istniej możliwość zdefiniowania dodatkowych przestrzeni nazw. Definicje tych
przestrzeni muszą znaleźć się w korzeniu UserControl i muszą być opatrzone
odpowiednim prefiksem.
Listing 3. Przykłady dodatkowych przestrzeni nazw, które są standardowo
generowane przez Visual Studio podczas tworzenia projektu
Dodatkowe przestrzenie nazw są
bardzo ważne w SL. Dzięki nim możemy korzystać z mechanizmu zdarzeń oraz
dołączać własne, wcześniej napisane kontrolki do swojej aplikacji SL.
Obok zdefiniowania przestrzeni,
bardzo ważnym krokiem będzie skorzystanie z niej. W tym celu, aby użyć obiektów
zdefiniowanych w dodatkowej przestrzeni nazw, należy zastosować następującą
składnię:
Dokonajmy modyfikacji kodu z
listingu 1 dodając prefiks: „mojPrefiks” do domyślnej przestrzeni nazw (w tym
momencie nie będzie żadnej przestrzeni domyślnej):
Listing 4. Dodanie prefiksu mojPrefiks do domyślnej przestrzeni xmlns
Jak prezentuje powyższy listing,
nasza aplikacja zgłasza błędy. Aby się w ogóle skompilowała, musimy koniecznie
dodać prefiks mojPrefiks do wszystkich elementów, które korzystają z
przestrzeni domyślnej, tj. Grid, TextBlock, Run, LineBreak.
UWAGA:
prefiks mojPrefiks musi się pojawić nawet w samym znaczniku UserControl, w
którym są definiowane przestrzenie nazw. To oznacza, że UserControl również
korzysta z domyślnej przestrzeni nazw.
Listing 5. Poprawna wersja projektu 2_1_SL z prefiksem mojPrefiks
Dodatkowa przestrzeń nazw „x”
Przestrzeń nazw z prefiksem x jest bardzo ważną przestrzenią nazw,
ze względu na klasy jakie mapuje. Przestrzeń ta musi znaleźć się w pliku .xaml
jeśli w aplikacji SL używamy zdarzeń czy szablonów kontrolek.
Przestrzeń zawiera definicje
kilku ważnych konstrukcji m.in.:
- x:Class
– definiuje przestrzeń nazw i klasę, która dostarcza code-behind dla danego
pliku .xml
- x:Name
– ustala unikalną nazwę obiektu w ramach .xaml, po której będzie można
rozpoznać dany obiekt w pliku code-behind (innymi słowy: identyfikuje obiekt
nadając identyfikator jak ID kontrolki w ASP.NET)
- x:Key
– ustala unikalny klucz w katalogu zasobów
Domyślna własność znacznika
W języku XAML jedne elementy mogą
znajdować się wewnątrz innych obiektów. Listing 1 przedstawia kontener Grid, w
którym znajduje się kontrolka TextBlock. W obiekcie TextBlock znajdują się w
odpowiedniej kolejności kontrolki Run (do wyprowadzania tekstu) oraz LineBreak
(oznacza koniec linii). W ten sposób powstaje hierarchiczna struktura
zależności (tzw. drzewo zależności).
Bardzo ciekawą właściwością w
języku znaczników XAML jest tzw. własność domyślna. Jest to cecha, dzięki
której w niektórych przypadkach nie musisz w kodzie pisać nazwy właściwości.
Listing 6. Domyślna własność obiektu Run to Text
Listing 6 wyprowadza na stronie
SL tekst: „Bold Text” dzięki
własności domyślnej kontrolki Run – Text. Dla przykładu Button (przycisk)
posiada własność domyślną Content zaś TextBlock – Text. Natomiast dla
wszystkich kontenerów domyślną własnością jest Children (co oznacza zdolność
przechowywania kolekcji obiektów).
Składnia atrybutowa oraz elementów właściwości
W języku XAML istnieją 2 sposoby
deklarowania właściwości:
- składnia atrybutowa
Polega na tym,
że wszystkie właściwości obiektu są określane w postaci jego atrybutów.
Listing 7. Składnia atrybutowa
Obiekt Run ma
zadeklarowane w postaci atrybutów następujące właściwości:
- FontFamily – określa rodzaj czcionki,
- FontStyle – określa styl czcionki,
- FontSize – określa wielkość czcionki.
- składnia elementów właściwości
Podstawową
różnicą w stosunku do składni atrybutowej jest to, że należy stosować
rozszerzony zapis, używając zarówno taga otwierającego jak i zamykającego.
Pomiędzy tymi tagami należy podać definicje właściwości.
Listing 8. Przedstawia definicję 2-óch
kolumn siatki Grid za pomocą składni elementów właściwości
Ćwiczenie
Otwórz projekt 2_2_SL i zapoznaj się z XAML-em zawartym w projekcie.
Zauważ, że został wstawiony
kontener Grid, który tworzy na stronie tabelę składającą się z 3-ech wierszy i
kolumn o odpowiedniej szerokości i wysokości. Każda komórka tabeli (stworzonej
przez siatkę Grid) ponumerowana jest w postaci x,y – gdzie x oznacza numer
wiersza, zaś y – numer kolumny. Pierwsza komórka więc opatrzona jest wartością
0,0 (pierwsza komórka w lewym górnym rogu), zaś ostatnia – 2,2. Zauważ, że do
ostatniej komórki tabeli (przyp. 2,2) został wstawiony obiekt Prostokąt (ang. Rectangle) wypełniony kolorem żółtym.
Prostokąt wypełniony kolorem czerwonym znajduje się na przecięciu komórki 0,0
jak i 1,0 (za taki stan rzeczy odpowiada właściwość RowSpan).
A za co odpowiada właściwość
ColumnSpan?
Listing 9. Projekt 2_2_SL
Listing 9. Wynik działania 2_2_SL
Podsumowanie
Niniejszy artykuł wprowadza nas w świat języka XAML, dzięki
któremu tworzymy rozwiązania Silverlight. Poznaliśmy pojęcia obiektu, właściwości (jej składni
atrybutowej oraz elementowej) oraz domyślnej i dodatkowej przestrzeni nazw. W kolejnym artykule będziemy dalej zagłębiać się w język
znaczników XAML rozwiązań SL.