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 1063x (419.63 kB)