Java týden Předvánoční slevová akce
Využij předvánočních slev a získej od nás 20 % bodů zdarma! Více zde
Pouze tento týden sleva až 80 % na Java e-learning!

Lekce 6 - Upomínač narozenin v C# .NET WPF - Návrh oken

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Code Behind v C# .NET WPF a dokončení kalkulačky, jsme doprogramovali jednoduchou kalkulačku. Během následujících několika C# .NET tutoriálů si vytvoříme středně pokročilou aplikaci. Bude se jednat o upomínač narozenin přátel. Hotová aplikace bude vypadat takto:

Upomínač narozeniny v C# .NET WPF

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ádnete. Aplikace je ještě poměrně jednoduchá a věřím, že nejlépe se látka naučí na praktickém příkladu.

Návrh formulářů

Začněme tradičně návrhem formulářů. Vytvořte si nový WPF projekt s názvem UpominacNarozenin.

Hlavní formulář

Formuláři nastavte titulek okna, startovní pozici na obrazovce a můžete 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:

Grid okna v C# .NET WPF

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 Gridu vypadá nyní následovně:

<Grid Margin="10">
        <Grid.RowDefinitions>
                <RowDefinition Height="20"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="30"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="200"/>
        </Grid.ColumnDefinitions>
</Grid>
Horní TextBlocky

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.

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ž spojujete buňky tabulky v Excelu. Stejně tak existuje RowSpan, který vkládá element přes více řádků. StackPanelům 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.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal">
        <TextBlock Text="Dnes je "/>
        <TextBlock Text="" />
</StackPanel>

<StackPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal">
        <TextBlock Text="Nejbližší narozeniny má "/>
        <TextBlock Text=""/>
        <TextBlock Text=" za "/>
        <TextBlock Text=""/>
        <TextBlock Text=" dní."/>
</StackPanel>
Spodní tlačítka
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Úplně stejným způsobem vložíme do posledního řádku okna dvě tlačítka. Opět budou ve StackPanelu (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.Column="0" Grid.Row="3" 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>

Váš formulář by měl nyní vypadat asi takto:

StackPanely v C# .NET WPF

Můžete si aplikaci zkusit spustit a okno rozšířit, abyste zkontrolovali, zda se vše přizpůsobuje.

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 XAMLu, 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"/>
Kalendář

Zbývá vložit jen kalendář a nad něj opět několik 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 TextBlocky vedle sebe, budou tedy v dalších StackPanelech. 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 Exploreru -> Add -> Window), které pojmenujeme OsobaWindow. Opět si nastavte titulek, startovní pozici a ikonku.

Ukažme si znovu obrázek hotových formulářů, nyní pracujeme na tom vpravo:

Upomínač narozeniny v C# .NET WPF
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:

Grid okna v C# .NET WPF

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>
Image

Do prvního řádku vložíme nějaký obrázek, abychom se s nimi naučili pracovat. Spoustu ikon volně ke stažení naleznete na webu http://www.iconfinder.com, vždy si přečtěte licenci pro jaké případy můžete danou ikonu používat. 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"/>
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ří. Pokud vás napadlo, jak v textu Labelu tedy zapsat podtržítko, napíšete 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í Labelu s ovládacím prvkem je realizované pomocí atributu Target. Zde je výraz ve složených závorkách, který začíná slovem Binding. Binding označuje provázání, zde Labelu 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 stisknete 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, nejjednodušší je přidat Zavírací tlačítko a tomu nastavit atribut IsCancel na True.

Tak a máme hotovo. Myslím, že jste si užili navrhování formulářů v XAMLu do sytosti naučili se zas něco nového. V příští lekci, Upomínač narozenin v C# .NET WPF - Logická vrstva, to bude čistě o logické části aplikace a C# kódu. Navržený formulář je jako vždy ke stažení níže.


 

Stáhnout

Staženo 745x (311.26 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
18 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Code Behind v C# .NET WPF a dokončení kalkulačky
Všechny články v sekci
Okenní aplikace v C# .NET WPF
Miniatura
Následující článek
Upomínač narozenin v C# .NET WPF - Logická vrstva
Aktivity (7)

 

 

Komentáře

Avatar
Daniel Vršek:14.1.2014 20:05

Z nejakých neznámych dôvodnou mi nechce zobrazovať obrázok mám to ako jednu časť môže to byť nejakým špecial parametrom?

 
Odpovědět
14.1.2014 20:05
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Daniel Vršek
David Čápka:14.1.2014 20:38

Pokud jsi stáhl hotový projekt, tak to bude tím, že ho mám já v PC ;-)

Odpovědět
14.1.2014 20:38
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na David Čápka
Daniel Vršek:18.1.2014 20:04

Nie nie už som zistil :) mne načítalo obrázok do image-u zobrazovalo mi ho vo formulári dizajnu ale keď som to zapol tak tam nebol ale keď som na ten obrázok dal celú adresu tak to už išlo aj keď som to zapol :)

 
Odpovědět
18.1.2014 20:04
Avatar
Gabriel Mastný
Redaktor
Avatar
Gabriel Mastný:9.5.2014 19:22

Zdravím,
Z mě nezjistitelných důvodů mi VS v XAML kódu vůbec nebere tag Calendar
při spuštění stažené aplikace vše klape ok ale při psaní v XAML to prostě nebere jak vlastní kód tak ani stažený...
Znění chyby: Calendar is not supported in WPF project.
Mám VS 2012.

Odpovědět
9.5.2014 19:22
Where there's will, there's way.
Avatar

Člen
Avatar
:15.7.2014 18:33

Davide, jistě to každému dojde, ale asi by bylo dobré (pro pořádek) obrázek v odstavci 'Rozložení' opravit.

 
Odpovědět
15.7.2014 18:33
Avatar
Odpovídá na David Čápka
Libor Šimo (libcosenior):14.6.2015 7:51

Dá sa v tomto štádiu po spustení pozrieť aj okno OsobaWindow?
Ak áno, ako?

Odpovědět
14.6.2015 7:51
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Michal Štěpánek:14.6.2015 9:12

dá, ale musel bys mít nastavenou událost kliknutí na tlačítko (je to v dalším dílu - propojení vrstev)

Odpovědět
14.6.2015 9:12
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Odpovídá na Michal Štěpánek
Libor Šimo (libcosenior):14.6.2015 19:13

Myslel som si to, diky.

Odpovědět
14.6.2015 19:13
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Michal Štěpánek
Libor Šimo (libcosenior):18.6.2015 16:43

Prečo je tu:
Label Content="_Jméno"
podtržník pred Jméno?
To tam musí byť?

Odpovědět
18.6.2015 16:43
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):18.6.2015 16:47

Sorry, je to písané v článku. Nevšimol som si to. ;(

Odpovědět
18.6.2015 16:47
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Filistin
Člen
Avatar
Filistin:23.11.2015 20:05

Zdravim!

Dá se nějak udělat, abych v elementu Image nemusel v Source psát celou cestu?
Tak, jak to máte vy - jenom Source=jmeno.png mi to nefunguje. Pouze když tám zadám celou cestu "C:\Users ... " (myslel jsem, že by to mohlo být tím, že jako User mam jméno s diakritikou, ale ani když jsme to hodil na Dčko - kde je pak cesta bez diakritiky - to nefunguje)

A měl bych ještě dotaz - pokud chci pak někomu poslat exe soubor - obrázek tam samozřejmě vidět není. Dá se to nějak napojit přímo - aby při zapnutí exe souboru na jiném počítači byl obrázek vidět?

 
Odpovědět
23.11.2015 20:05
Avatar
Lukas C#
Redaktor
Avatar
Odpovídá na Filistin
Lukas C#:23.11.2015 20:15

Musíš si vytvořit tu složku na obrázky přímo ve Visual studiu :-) Solution explorer: pravý klik na projekt -> add -> new folder (nebo tak nějak) - do toho ty obrázky dáš. Pak nejen že stačí napsat Source="slozka/o­brazek.png", ale tyto obrázky jsou zabalené v exe souboru, který posíláš - takže ho uvidí samozřejmě i ostatní :-)

 
Odpovědět
23.11.2015 20:15
Avatar
Filistin
Člen
Avatar
Filistin:23.11.2015 20:35

Z nějakého důvodu mi to nefuguje ani takhle :-?

 
Odpovědět
23.11.2015 20:35
Avatar
Odpovídá na Filistin
Michal Štěpánek:24.11.2015 9:35

Určitě tam máš něco špatně napsané, napiš sem, kde máš ty obrázky a ten kód, co ti nefunguje...

Editováno 24.11.2015 9:36
Odpovědět
24.11.2015 9:35
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Filistin
Člen
Avatar
Filistin:25.11.2015 23:46

Kód by měl být správně. Zkusil jsem ještě pár jiných obrázků a s těmi to šlape.
Myslel jsem, že by to mohlo být větším rozlišením toho obrázku, ale vzalo mi to v pohodě i obrazek s rozlišením 1448x2048.
Pak jsem si všiml, že má v přípone JPG velkými písmeny (byl jsem zoufalej, tak jsem zkusil všechno) - tak jsem si našel jinej obrázek s příponou, která má písmena velká, ale tu mi to taky vzalo.
Jenom ten jedinej jeden obrázek to neveme. Dost divný ...
Ale na tom nesejde - hlavně, že neni chyba v kódu.
Díky za rady.

 
Odpovědět
25.11.2015 23:46
Avatar
Michal Gros
Redaktor
Avatar
Michal Gros :19.12.2015 20:25

není špatně ten obrázek návrhu tabulky u druhého okna ?

Odpovědět
19.12.2015 20:25
Jestli jste dobří nahrnou na Vás spoustu práce. Jestli jste sakra dobří, tak se jí dokážete zbavit.
Avatar
Odpovídá na Michal Gros
Michal Štěpánek:20.12.2015 19:37

jak špatně?

Odpovědět
20.12.2015 19:37
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Lukáš Hypša:10.3.2016 17:04

V "Dialog přidání okna" máš v "Rozložení" špatnej obrázek.

Odpovědět
10.3.2016 17:04
Jsem lama co se roky snaží naučit napsat aspoň pár řádků a furt mu to nejde...
Avatar
krepsy3
Redaktor
Avatar
krepsy3:7.5.2016 22:00

Ahoj, Zkusil jsem label natargetovat na Checkbox, a v ten moment mi přestalo jít kliknout na ten checkbox, šlo to pouze přes tu klávesu označenou podtržítem, což je dost nepraktické, protože v té mé aplikaci se to týká odděděného Childa UserControlu, kterých tam mám více. Co s tím?

Odpovědět
7.5.2016 22:00
Programátor je stroj k převodu kávy na kód.
Avatar
Odpovídá na krepsy3
Michal Štěpánek:8.5.2016 9:40

Co myslíš tím

label natargetovat na Checkbox

?

Odpovědět
8.5.2016 9:40
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
krepsy3
Redaktor
Avatar
Odpovídá na Michal Štěpánek
krepsy3:8.5.2016 14:53

Přesně podle tutoriálu:

<Label Target="{Binding ElementName=isColorCheckbox}" Content="_Color"  />
<CheckBox Name="isColorCheckbox" />

Btw. dělá mi to i u ostatních kontrolek na tomtéž formuláři. Když Binding odmažu, funguje vše normálně. Možná pomůže informace, že tento formulář mám jako UserControl (Jméno je Pot.xaml), který do hlavního formuláře dědím přes

kontrolkaNaHlavnímPanelu.Children.Add(new Pot())
Odpovědět
8.5.2016 14:53
Programátor je stroj k převodu kávy na kód.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Michal Gros
David Čápka:10.8.2016 16:24

Jo, byl tam 2x ten samý, už jsem to opravil :)

Odpovědět
10.8.2016 16:24
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na Gabriel Mastný
René Češka:10.9.2016 23:14

Vyřešil jsi to nějak? Mám úplně stejný problém jenom s tím rozdílem že mám Visual studio comunity 2015.

 
Odpovědět
10.9.2016 23:14
Avatar
Gabriel Mastný
Redaktor
Avatar
Odpovídá na René Češka
Gabriel Mastný:11.9.2016 0:06

Jj, problém byl v tom že jsem zakládal projekt, který pracoval nejvýš s .NET frameworkem 3 a Calendar je přidaný až od 4.0...

Odpovědět
11.9.2016 0:06
Where there's will, there's way.
Avatar
Odpovídá na Gabriel Mastný
René Češka:11.9.2016 8:27

Dík, a dá se nějak přenastavit framework v už založeném pojektu?

 
Odpovědět
11.9.2016 8:27
Avatar
René Češka:11.9.2016 8:35

Sorry blbá otázka stačily mi 3 vteřiny googlení a než sem si to uvědomil a otestoval tak mi ten koment už nešel smazat.

 
Odpovědět
11.9.2016 8:35
Avatar
Josef Luňáček:6.5.2018 19:10

Dobrý den, měl bych jeden dotaz. V úvodu je psáno, že zde narazíme i na architekturu MVVM. Mohl by mi někdo poukázat na konkrétní použití zde na tomto příkladu?
Děkuji.

Odpovědět
6.5.2018 19:10
Nikdo není dokonalý.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 27 zpráv z 27.