Pošto imamo samo praznu stranu, dodaćemo jedan jednostavan panel koji se zove Canvas. Canvas je panel koji omogućava standardno x0y koordinatno pozicioniranje elemenata.
<Canvas>
</Canvas>
Takođe ćemo dodati jedno dete u Canvas a to je Elipsa:
<Ellipse Height="100" Width="100" Fill="Red"/>
Dakle, dodali smo jednu elipsu u Canvas i kao što vidite, ovde nema za sada nikakvog Layout-a. Da bi Canvas pozicionirao elipsu, moramo da zadamo koodinate, a to ćemo uraditi primenjujući koncept Attached propertija. Sada ćemo postaviti attached propertije direktno na elipsu.
<Ellipse Canvas.Top="100" Canvas.Left="200" Height="100" Width="100" Fill="Red" />
Znači, postavljajući Canvas.Top="100" i Canvas.Left="200" uticali smo na elipsu da se pozicionira u okviru Canvas-a. Ovi propertiji se nazivaju attached propertiji zato što počinju sa „Canvas.„ notacijom. To nam govori da je property definisan canvas elementom. Attached propertiji daju mogućnost Canvas-u da definiše propertije koji se koriste na drugim elementima. Elipsa ne mora da zna za Top i Left propertije, oni su definisani od strane Canvas-a, a koriste se za definisanje pozicije elipse. Attached propertiji su uobičajeni kod panela zbog postojanja potrebe da panel određuje poziciju elemenata u okviru njega samog. Primetili ste da kada sam dodala ove propertije, elipsa je promenila položaj 100 piksela od vrha i 200 piksela od leve ivice.
Dodajmo sada još jedno dete u Canvas. Kopirajmo prvi red uz pomoć CRTL+C za copy i CTRL+V za paste, i promenimo vrednosti propertija.
<Ellipse Canvas.Top="110" Canvas.Left="240" Height="10" Width="10" Fill="Yellow" />
Primetite da su elipse postavljene po redu kako se definisale. Ako bi premestili malu elipsu ispred veće, ne bismo mogli da je vidimo. Kopirajmo je sada ispred veće elipse. Primetili ste da je mala žuta elipsa nestala. To se dešava po defaultu - elementi se ređaju po redu po kom su definisani. Sada ćemo upotrebiti još jedan attached property koji se odnosi na poziciju više elemenata u okviru Panela. To je Panel.Zindex.
<Ellipse Panel.ZIndex="1" Canvas.Top="110" Canvas.Left="240" Height="10" Width="10" Fill="Yellow" />
<Ellipse Canvas.Top="100" Canvas.Left="200" Height="100" Width="100" Fill="Red" />
ZIndex utiče na redosled "pojavljivanja" elemenata u panelu. Veći broj znači da je element ispred elementa sa manjim brojem. Default vrednost ZIndex-a je nula.
Sledeći panel koji ćemo objasniti je StackPanel. Stack Panel može biti horizontalni StackPanel i vertikalni StackPanel. Pogledajmo kako StackPanel funkcioniše.
Prvo, promenimo naš Canvas u StackPanel. Pogledajte šta se desilo - naše dve elipse su se poređale od vrha jedna posle druge. Ostali neki propertiji vezani za Canvas koji više nemaju smisla, pa ih zato treba obrisati. StackPanel funkcioniše tako što kreira stack elemenata od vrha ka dnu od svih elemenata koji se u njemu nalaze. Takođe, primetili ste verovatno da su svi poređani po sredini. To je zbog jednog propertija koji nije attached property već je regularan property i zove se HorizontalAlignment. Prvo povećajmo malu žutu elipsu da bude istih dimenzija kao i crvena.
HorizontalAlignment je property koji se može postaviti na bilo koji element. Može imati vrednosti: Left, Right, Center i Stretch. Zadajmo npr. vrednost ovog propertija da bude Left. Inače, default vrednost je stretch (a to bismo videli ako bismo uklonili širinu na elementu).
VerticalAlignment je property koji može imati vrednosti: Top, Center, Bottom i Stretch. Default vrednost je stretch. Ovaj property ima smisla ako je StackPanel horizontalno orijentisan.
<StackPanel Orientation="Horizontal">
<Ellipse Width="100" Height="100" Fill="Yellow" VerticalAlignment="Top"/>
<Ellipse Width="100" Height="100" Fill="Red" VerticalAlignment="Bottom"/>
</StackPanel>
Sledeći panel koji ćemo objasniti je WrapPanel. Ovaj panel je naročito koristan ako imate dosta malih elemenata koje je potrebno rasporediti u ograničenom prostoru. I u osnovi se ponaša kao više stack panela koji su raspoređeni jedan nakon drugoga. Prvo raspoređuje elemente u jedan red, i kad nestane mesta u prvom redu, on nastavlja da smešta elemente u drugi red i tako dalje sve dok ne pronađe mesta za sve elemente. Da biste videli kako Wrap panel funkcioniše, kopirajmo dosta elipsi, a zatim promenite StackPanel u WrapPanel. Prvo obrišimo Alignment propertije koje smo malopre postavili.
<Ellipse Height="100" Width="100" Fill="Yellow" />
<Ellipse Height="100" Width="100" Fill="Red" />
<Ellipse Height="100" Width="100" Fill="LightBlue" />
<Ellipse Height="100" Width="100" Fill="YellowGreen" />
Wrap Panel je rasporedio elemente u vrh i sa leve strane tj. smestio ih je u horizontalni stack. Ali pogledajte šta će se desiti kada napravimo dosta elipsi. Kopirajmo ove četii elipse pet - šest puta, i pritisnite F5 da bi ste refresh-ovali sve. Wrap panel ih je rasporedio u redove tako da je svaki red popunio dok je bilo prostora u njemu, a zatim je nastavio da ih raspoređuje u naredni red. Svaka od ovih elipsi ima istu širinu i visinu. Hajde da vidimo šta će se desiti ako jednoj elipsi promenimo visinu i širinu. Izaberimo jednu od njih, i promenićemo joj boju u sivo da bi mogli da je identifikujemo i promenićemo joj visinu i širinu da bude veća. Dakle, vidimo da se širina celog reda prilagodila dimenziji najvećeg, tj. najvišeg objekta.
Sada ćemo reći nekoliko reči o marginama. Property "Margin" se odnosi na skoro sve vrste Panela. To je placeholder, što znači da dodaje prostor elementu sa njegove spoljne strane. Postavimo margine na sivu elipsu. Prethodno ćemo vratiti veličinu elipse da bude kao i ostale elipse - širina i visina da bude 100 piksela.
Margin="30,0,0,0"
Vidite da smo postavili vrednost leve margine. Svaka od četiri vrednosti između zareza se odnosi redom na vrednosti margina u smeru kazaljke na satu.
Ako želimo da zadamo vrednosti samo leve i desne margine, možemo to zapisati na kraći način:
Margin="50,0"
Ili ako hoćemo da dodamo Margine istih vrednosti sa svih strana, jednostavno možemo otkucati:
Margin="50"
Grid Panel omogućava definisanje ćelija, kao u tabelama, i dodavanje sadržaja u te ćelije. Obrisaćemo sve elipse osim prve četiri klikom na Delete i pritisnućemo F5 za refresh. Sada želimo da zamenimo Wrap Panel sa Gridom,i kad refresh-ujemo, izgleda kao da imamo samo jednu elipsu. Ustvari, sve elipse su tu, samo što su sve smeštene direktno u centar jedne ćelije koja postoji u Gridu po default-u. Znači, po default-u, postoji samo jedna ćelija, tj. jedan red i jedna kolona. Grid koristi Alignment propertije da odredi položaj elemenata u okviru ćelije. Postavimo npr. na prvu elipsu:
HorizontalAlignment="Left"
VerticalAlignment="Top"
Sećate se da smo napomenuli da je default vrednost za HorizontalAlignment property - stretch, i da bi to videli kada bi uklonili širinu i visinu elementu. Uklonimo širinu i visinu plavoj elipsi. Sada vidimo da elipsa ispunjava čitavu ćeliju. Postavimo sada marginu na ovu elipsu.
Margin="50"
4.1 Dodavanje redova i kolona u Grid
Da bismo definisali redove i kolone u Gridu, upoznaćemo se sa još jednom vrstom popertija a to je ComplexProperty. Complex property je property čija je vrednost složenija od običnog stringa, broja, ili enumeracije. Koristi se za postavljanje složenih vrednosti kao što su npr. kolekcija objekata, a u našem slučaju su to redovi i kolone. Pogledajmo kako izgleda dodavanje complex propertija u Grid.
<Grid.ColumnDefinitions>
</Grid.ColumnDefinitions>
Ovo možda izgleda kao dodavanje deteta elementa u Grid, ali sintaksa koja počinje sa "Grid." nam govori da postavljamo property na Grid. A property koji postavljamo se zove ColumnDefinitions. ColumnDefinitions je kolekcija objekata tipa ColumnDefinition. Svaka ColumnDefinition koju dodajemo u ovu kolekciju će kreirati novu kolonu u Gridu. Kolonu dodajemo jednostavno dodavanjem taga ColumnDefinition. Dodajmo nekoliko kolona i pogledajmo kako one utiču na Grid:
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
Vidite da se ceo sadržaj premestio u prvu kolonu. Da bismo videli granice kolona, postavićemo property Grida pod nazivom „ShowGridLines" na vrednost true. Sad vidimo granice.
<Grid ShowGridLines="true">
4.2 Attached properties Grid.Column i Grid.RowSpan
Kako premeštamo objekte u kolone? Premeštamo ih koristeći attached propertije. Setite se da smo koristili attached propertije kod Canvasa - Canvas.Top i Canvas.Left. Rekli smo da se attached property koristi za pozicioniranje elementa u okviru panela i da je to property panela a ne elementa u okviru panela. Sada ćemo koristiti attached property "Grid.Column" da bismo smestili element u određenu kolonu. Postavićemo ovaj property na jednu od naših elipsi.
<Ellipse Height="100" Width="100" Grid.Column="1" Fill="Red" />
Najmanja vrednost ovog propertija je 0 što se odnosi na prvu kolonu i to je ujedno i defaultn-a vrednost, zato su se i sve elipse pojavile u prvoj koloni.
Takođe je moguće specificirati da se element prostire na više kolona, a property koji to omogućava je attached property „ColumnSpan". Po default-u, vrednost ovog propertija je jedan, što znači da se element prostire u jednoj koloni. Zato i sada vidimo da je svaka od ovih elipsi smeštana u jednu kolonu. Ako promenimo vrednost ovog propertija na dva, element će se prostirati na dve kolone. Dodajmo sada plavoj elipsi ColumnSpan=2:
<Ellipse Fill="LightBlue" Grid.ColumnSpan="2" />
4.3 Veličina kolona
Veličina kolone, odnosno, širina, se može definisati na 3 načina: proporcijom, u pikselima i automatski. Default-na vrednost širine je „*" (zvezda) i podrazumeva da širina kolone zauzima „jednu porciju raspoloživog prostora". Mi imamo tri kolone i svaka zauzima jednu porciju, tj. svaka zauzima trećinu raspoloživog prostora. Definišimo npr. za prvu kolonu da zauzima dve porcije raspoloživog prostora:
<ColumnDefinition Width="2*"/>
Dakle, raspoloživi prostor se deli na četiri dela, pri čemu prva kolona zauzima dve porcije tog prostora, a preostale dve kolone zauzimaju po jednu porciju.
Drugi način da odredimo širinu kolone je zadavanje standardne fiksne vrednosti - u pikselima. Ako promenimo širinu druge kolone da bude 100 piksela, pogledajte kako će se širina promeniti na tačno 100 piksela.
<ColumnDefinition Width="100"/>
Poslednji način da definišemo širinu kolone je jednostavno postavljanje vrednosti "Auto". Ako postavimo ovako širinu kolone, to znači da će se širina prilagoditi širini sadržaja u njoj. Prvo mora da nešto postoji u toj koloni, inače će se širina kolone smanjiti na nulu. To ćete videti ako postavite vrednost širine Auto na treću kolonu jer trenutno u njoj nema elemenata:
<ColumnDefinition Width="Auto"/>
Ako smestimo poslednju elipsu u treću kolonu, videćete kako će se njena širina prilagoditi širini elipse.
<Ellipse Height="100" Width="100" Fill="YellowGreen" Grid.Column="2" />
I na kraju, poželjno je napomenuti da se redovi ponašaju na isti način kao i kolone samo u suprotnom smeru. Dodajmo dva reda i odredimo im visine tako da prvi zauzima dve porcije prostora:
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition/>
</Grid.RowDefinitions>
Primetili ste da su svi elementi smešteni u prvi red i to je zato što je default vrednost za Grid.Row nula.
Na kraju je važno napomenuti da je moguće smeštati panele u panele, tj. ugnježdavati ih jedne u druge. Npr. moguće je smestiti StakPanel u Grid ili obrnuto. Ugnježdavanje panela predstavlja snažan Layout mehanizam.