Lekce 6 - Upomínač narozenin v C# .NET WPF - Návrh oken
V předešlém cvičení, Řešené úlohy k 1.-5. lekci WPF v C# .NET, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním WPF tutoriálu začneme programovat Upomínač narozenin přátel. Hotová aplikace bude vypadat takto:

Vidíme, že aplikace má 2 formuláře, používá ovládací prvky pro práci s datem a také obsahuje ukládání dat do souborů. Vnitřně narazíme na architekturu Model-View-ViewModel, výjimky a bindingy. Nebude toho málo, ale vše si postupně vysvětlíme a jistě to zvládneme. Aplikace je ještě poměrně jednoduchá a nejlépe se látka naučí na praktickém příkladu.
Návrh formulářů
Začněme tradičně návrhem formulářů. Vytvoříme si nový WPF projekt
s názvem UpominacNarozenin.
Hlavní formulář
Formuláři nastavíme titulek okna, startovní pozici na obrazovce a můžeme i nějakou ikonku.
Rozložení
Možností jak dospět toho samého výsledků při rozložení formuláře
je více. My si jeho <Grid> rozdělíme následujícím
způsobem:

Tabulka má 2 sloupce a 4 řádky. Řádky jsou vysoké postupně:
20, 30, * a 30 DIP. Ten
předposlední se tedy roztahuje s oknem. Levý sloupec má šířku
*, pravý má pevnou šířku 200 DIP. Kolem celého
elementu <Grid> je Margin 10 DIP.
Kód v elementu Grid vypadá nyní následovně:
<Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="200"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="20"/> <RowDefinition Height="30"/> <RowDefinition Height="*"/> <RowDefinition Height="30"/> </Grid.RowDefinitions> </Grid>
Horní elementy
<TextBlock>
V prvních dvou řádcích elementu <Grid> jsou vložené
elementy <TextBlock> s informací o dnešním datu a
nejbližších narozeninách. Text se zde skládá z několika částí a
ačkoli lze v každém řádku použít pouze jeden
<TextBlock>, do kterého hodnotu složíme, my si pro
zjednodušení vložíme několik elementů <TextBlock> vedle
sebe.
Element <StackPanel>
Pro skládání ovládacích prvků vedle sebe nebo pod sebe slouží
<StackPanel>. Jedná se o kontejner na další prvky, stejně
jako <Grid>. Do každého řádku tabulky vložíme jeden
<StackPanel>. Budeme chtít, aby se
<StackPanel> nevložil pouze do prvního sloupce, ale
zasahoval do celého řádku. Proto mu zadáme atribut ColumnSpan s
hodnotou 2, což znamená, že zasahuje přes 2 sloupce. Je to
podobné jako colspan v HTML nebo jako když
spojujeme buňky tabulky v Excelu. Stejně tak existuje RowSpan,
který vkládá element přes více řádků. Elementům
<StackPanel> ještě nastavíme atribut
Orientation na hodnotu Horizontal, výchozí je totiž
Vertical, tedy řazení pod sebe. Rovnou do nich také vložíme
jednotlivé elementy <TextBlock>, text těch, kde se mají
zobrazovat data, ponecháme zatím prázdný.
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal"> <TextBlock Text="Dnes je " /> <TextBlock Text="" /> </StackPanel> <StackPanel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal"> <TextBlock Text="Nejbližší narozeniny má " /> <TextBlock Text="" /> <TextBlock Text=" za " /> <TextBlock Text="" /> <TextBlock Text=" dní." /> </StackPanel>
Spodní tlačítka
Úplně stejným způsobem vložíme do posledního řádku okna dvě
tlačítka. Opět budou v elementu <StackPanel> (protože je
chceme vedle sebe) a ten bude opět zasahovat přes 2 sloupce.
<StackPanel> se bude centrovat. Tlačítkům rovnou
přiřadíme jména, jelikož je budeme používat v Code Behind. Levému
nastavíme pravý Margin, aby nebyla nalepená úplně na
sobě:
<StackPanel Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center"> <Button Width="100" Margin="0,0,10,0" Name="pridatButton" Content="Přidat" /> <Button Width="100" Name="odebratButton" Content="Odebrat" /> </StackPanel>
Náš formulář nyní vypadá takto:

Můžeme si aplikaci zkusit spustit a okno rozšířit, s kontrolou, zda se vše přizpůsobuje.
Element <ListBox>
Uložené osoby budeme zobrazovat v ovládacím prvku
<ListBox>. Jak již název napovídá, jedná se o nějaký
seznam položek. <ListBox> je v podstatě rozbalený
<ComboBox>, pracuje se s ním úplně stejně. V našem
případě nebudeme položky definovat v kódu XAML, ale načteme
je později z logické vrstvy aplikace. <ListBox> vložíme
do 1. sloupce a 3. řádku, pojmenujeme ho osobyListBox a
nastavíme mu spodní Margin na 10 DIP.
<ListBox Name="osobyListBox" Grid.Column="0" Grid.Row="2" Margin="0, 0, 0, 10"/>
Element <StackPanel>
Zbývá vložit jen kalendář a nad něj opět několik elementů TextBlock.
Můžeme si v dané buňce buď udělat další <Grid> nebo
použít <StackPanel>, který je na řazení prvků pod sebe
dělaný. Tomu nastavíme levý Margin na 10 DIP. V
každém řádku opět potřebujeme 2 elementy <TextBlock>
vedle sebe, budou tedy v dalších elementech <StackPanel>.
Kalendář vložíme jako ovládací prvek <Calendar>,
slouží sice spíše pro výběr data, ale my jej budeme používat pro jeho
zobrazení.
<StackPanel Grid.Column="1" Grid.Row="2" Margin="10, 0, 0, 0"> <StackPanel Orientation="Horizontal"> <TextBlock Text="Narozeniny: "/> <TextBlock Text="" /> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock Text="Věk: "/> <TextBlock Text="" /> </StackPanel> <Calendar Name="narozenCalendar" /> </StackPanel>
Hlavní formulář máme hotový.
Dialog pro přidání osoby
K projektu přidáme nové okno (kliknutím pravým tlačítkem na projekt v
Solution Explorer -> Add -> Window), které pojmenujeme
OsobaWindow. Opět si nastavíme titulek, startovní pozici a
ikonku.
Ukažme si znovu obrázek hotových formulářů, nyní pracujeme na tom vpravo:

Rozložení
<Grid> rozdělíme opět na 2 sloupce a 4 řádky. Výšky
řádků jsou následující: 4*, 30, 30,
*. První a poslední řádek se tedy roztahují s oknem, první
zabere 4x více prostoru než poslední. Oba sloupce budou mít šířku
*, ta je výchozí, nemusíme ji tedy ani definovat. Okolo celého
Gridu necháme opět Margin 10. Výsledek vypadá takto:

A jeho kód:
<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="4*"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> </Grid>
Element Image
Do prvního řádku vložíme nějaký obrázek, abychom se s nimi naučili
pracovat. Spoustu ikon volně ke stažení nalezneme na tomto webu, na kterém si přečtěte
licenci pro jaké případy je možno danou ikonu použít. Obrázek vložíme
pomocí ovládacího prvku <Image>. Soubor obrázku
(nejčastěji .png) musíme podobně jako ikonu nejprve přidat do
projektu. Poté název souboru uvedeme v atributu Source prvku
<Image>. Když máme obrázků v projektu již hodně,
vyplatí se na ně vytvořit nějakou složku. Výchozí chování obrázků je,
že se roztahují tak, aby vyplnily rodičovský prvek. To nám zde nevyhovuje a
proto nastavíme Stretch na hodnotu "None". Obrázek
vložíme do celého řádku tabulky pomocí ColumnSpan:
<Image Source="osoba_pridat.png" Stretch="None" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="0"/>
Element <Label>
Do druhého sloupce dalších dvou řádků přijdou ovládací prvky k
zadání jména a data narození. Ke každému prvku umístíme do prvního
sloupce popisek. Nepoužijeme k tomu však <TextBlock>, ale
<Label>. <Label> je popisek, který se
vztahuje k určitému prvku. Pokud do textu jeho popisku vložíme podtržítko
před nějaké písmeno, definujeme tak klávesovou zkratku. Po stisknutí
Alt + tohoto písmena se zaktivní ovládací prvek, ke
kterému popisek patří.
Podtržítko bychom v elementu <Label>
napsali jako dvě za sebou.
K zadání jména použijeme samozřejmě <TextBox>. K
zadání data narození použijeme ovládací prvek
<DatePicker>. Ukažme si kód:
<Label Content="_Jméno" Grid.Column="0" Grid.Row="1" Target="{Binding ElementName=jmenoTextBox}" /> <Label Content="_Datum narození" Grid.Column="0" Grid.Row="2" Target="{Binding ElementName=narozeninyDatePicker}" /> <TextBox Grid.Column="1" Grid.Row="1" Name="jmenoTextBox" Margin="0,0,0,5" /> <DatePicker Grid.Column="1" Grid.Row="2" Name="narozeninyDatePicker" Margin="0,0,0,5" />
Vidíme, že propojení elementu <Label> s ovládacím
prvkem je realizované pomocí atributu Target. Zde je výraz ve
složených závorkách, který začíná výrazem Binding.
Binding označuje provázání, zde <Label> na
prvek s určitým jménem. Setkáme se s ním ještě na mnoha místech. Zbytek
kódu by neměl být nic nového. Nyní ještě nemůžeme formulář ve
spuštěné aplikaci zobrazit, ale až to půjde a stiskneme na něm
Alt + J, zaktivní se pole se jménem. Alt +
D zaktivní DatePicker.
Dialog dokončíme vložením potvrzovacího tlačítka. To se bude zobrazovat dole ve středu posledního řádku.
<Button Name="okButton" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="100" Content="OK"/>
Každému oknu můžeme ve WPF ještě přiřadit co mají dělat výchozí a
ukončovací klávesy. Výchozí klávesa je Enter a měla by vyvolat
stisk tlačítka OK. Ukončovací klávesa je Esc. Proto
tlačítku přidáme ještě atribut IsDefault="True".
Pokud bychom chtěli, aby se dialog zavřel stisknutím
Esc, přidali bychom zavírací tlačítko s nastaveným atributem
IsCancel na hodnotu True.
Tak a máme hotovo.
V příští lekci, Upomínač narozenin v C# .NET WPF - Logická vrstva, to bude čistě o logické části aplikace a C# kódu, o kterou rozšíříme naši aplikaci Upomínač narozenin.
Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 1111x (419.63 kB)
 
				

 David se informační technologie naučil na
				David se informační technologie naučil na