8. diel - PRIPOMIENKOVÉ narodenín v C # .NET WPF - Prepojenie vrstiev
V minulej lekcii, PRIPOMIENKOVÉ narodenín v C # .NET WPF - Logická vrstva , sme naprogramovali väčšinu logické vrstvy aplikácie. Dnes v C# .NET tutoriálu aplikáciu sprevádzkujeme.
Oddelenie prezentácie a logiky
Teraz máme dokončenú tzv. Prezentačné časť aplikácie (formulára) a logickú časť (triedy). Tieto 2 vrstvy sa v aplikácii striktne oddeľujú, pretože inak je kód veľmi neprehľadný. Nikdy by ste nemali vykonávať výpočty, zápisy do súborov, databázy a podobné veci priamo v kóde formulára! Vždy si vytvoríme triedu, ktorá poskytuje príslušné metódy a túto triedu z formulára iba používame. Logika zostane v triede. Trieda by naopak vôbec nemala vedieť o formulári. Nemala by teda napr. Zobrazovať chybové hlášky, ale iba vyvolávať v prípade chyby výnimky. Je potom na formulári, aby užívateľovi chybu zobrazil. Práve formulár je tá časť aplikácie, ktorá s užívateľom komunikuje. Žiadna iná to nerobí.
Ak vás napadlo, že naše jednoduchá kalkulačka, ktorú sme vytvorili v prvých lekciách kurze, bola návrhové zle, máte pravdu. Z dôvodu jednoduchosti sme napísali výpočty rovno do obslužnej metódy tlačidla. Správne by sme mali mať nejakú triedu, ktorá by výsledky počítala a jej metódy by sme z formulára iba volali. XAML a aj jeho Code Behind je teda stále prezentačná vrstva aplikácie. XAML definuje ako formulár vyzerá, Code Behind volá logiku, ktorú neobsahuje.
Dnes si teda ukážeme, ako sa to robí správne.
Prepojenie prezentácie a logiky
Prejdeme do Code Behind formulára MainWindow
a triede pridáme
privátne atribút typu SpravceOsob
, v ktorom rovno vytvoríme
inštanciu správcu:
private SpravceOsob spravceOsob = new SpravceOsob();
Inštancie správcu sa vytvorí pri vytvorení formulára a formulár s ňou ďalej bude komunikovať a tak vykonávať úkony, ktoré si želá užívateľ.
Pridávanie osôb
Aby sme niečo konečne tiež videli, prejdeme k pridávanie osôb. Najprv
prejdeme do kódu formulára OsobaWindow
, kde si rovnako ako v
predchádzajúcom formulári pripravíme správcu osôb ako privátne atribút.
Keby sme tu aj vytvorili jeho inštanciu, nebolo by nám to moc platné,
pretože osoby by boli načítané v správcovi v hlavnom formulári. A
načítať ich znovu by bolo neefektívne. Necháme si teda hotového a
načítaného správcu odovzdať konštruktory a uložíme ho do pripravenej
premennej:
private SpravceOsob spravceOsob; public OsobaWindow(SpravceOsob spravceOsob) { InitializeComponent(); this.spravceOsob = spravceOsob; }
Teraz naklikne tlačidlo OK a do správcu pridáme osobu pomocou hodnôt,
ktoré užívateľ do jednotlivých prvkov zadal. K hodnote v
DatePicker
u pristúpime pomocou vlastnosti
SelectedDate
, ktorá je nullovatelného typu
DateTime?
.
Určite si spomínate, že metóda Pridej()
vyvolá výnimku v
prípade príliš krátkeho mená, nullového dáta alebo dáta v budúcnosti.
Preto kód s pridaním vložíme do bloku try
, za ktorým bude
nasledovať blok catch
. Ak výnimka v bloku try
nastane, program sa ihneď presunie do bloku catch
, kde pomocou
okna MessageBox
zobrazí chybovú hlášku. Ak by sme výnimku
takto neošetrili, spôsobila by pád aplikácie.
private void okButton_Click(object sender, RoutedEventArgs e) { try { spravceOsob.Pridej(jmenoTextBox.Text, narozeninyDatePicker.SelectedDate); Close(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Chyba", MessageBoxButton.OK, MessageBoxImage.Exclamation); } }
K správe výnimky sa dostaneme cez vlastnosť Message
.
Všimnite si tiež, že správe nastavujeme ikonku vykřičníčku. V metóde
už neriešime žiadnu logiku a je vďaka tomu pomerne krátka.
V tomto formulári sme skončili. Presunieme sa späť do
MainWindow
, tentoraz do grafického návrhára. Naklikne tlačidlo
pridatButton
a jeho obslužnú metódu upravíme takto:
private void pridatButton_Click(object sender, RoutedEventArgs e) { OsobaWindow osobaWindow = new OsobaWindow(spravceOsob); osobaWindow.ShowDialog(); }
V obslužné metóde tlačidla pridatButton
vytvoríme novú
inštanciu formulára OsobaWindow
, ktoré odovzdáme miestneho
správcu osôb. Na inštanciu následne zavoláme metódu
ShowDialog()
. Tá zobrazí nový formulár (rovnako ako metóda
Show()
) ak tomu ešte zablokuje zvyšok aplikácie, ktorý sa
zaktivní až v prípade, keď sa dialóg zatvorí. Výsledkom je, že sa s
hlavným formulárom nedá pracovať kým dialóg nepotvrdíme či neukončíme.
U dialógov sa toto väčšinou robí (dialógy rozumejte pomocné formulára,
ktorý slúži najčastejšie na zadanie údajov). Aj keď nám by v podstate
nevadilo, keby užívateľ počas zadávania novej osoby aplikáciu používal a
otvoril potrebné ďalšie dialóg na zadávanie.
Keď by sme aplikáciu teraz spustili, osobu by sme síce pridali do
ObservableCollection
, však by sme ju v ListBox
u
nevideli. Je to samozrejme z toho dôvodu, že ListBox
nie je na
túto kolekciu napojený. Iste vás neprekvapí, že toho docielime pomocou
binding.
Binding
Ak chceme bindovat, musíme oknu najprv nastaviť tzv. Kontext. To je objekt, ktorého vlastnosti budeme bindovat. To urobíme najjednoduchšie v konstruktoru okna pomocou nasledujúceho kódu:
DataContext = spravceOsob;
Inštancie správca osôb je teraz nastavená ako dátový kontext hlavného okna a my v tomto okne môžeme zobrazovať jej vlastnosti.
Presunieme sa do XAML a elementu <ListBox>
dodáme
atribút ItemsSource
:
<ListBox Name="osobyListBox" Grid.Column="0" Grid.Row="2" Margin="0, 0, 0, 10" ItemsSource="{Binding Osoby}"/>
Tým hovoríme, že zdrojom položiek ListBox
u je vlastnosť
Osoby
na kontextu, ktorým je správca osôb.
Skúste si aplikáciu spustiť a pridať nejaké osoby. Pridanej osoby sa
ihneď objaví v ListBox
u vďaka bindingům. ListBox
vždy zobrazuje to, čo vracia metóda ToString()
jeho položiek. U
osôb teda zobrazuje ich meno. Podobne fungujú samozrejme aj ďalšie
ovládacie prvky, napr. ComboBox
.
Odobratie užívateľov
Obslužná metóda tlačidla odebratButton
bude vyzerať
takto:
private void odebratButton_Click(object sender, RoutedEventArgs e) { if (osobyListBox.SelectedItem != null) { spravceOsob.Odeber((Osoba)osobyListBox.SelectedItem); } }
Dôležitá je podmienka, ktorá zisťuje, či je v ListBox
u
vybraná nejaká položka. Ako vidíte, k vybranej položke sa dostaneme cez
vlastnosť SelectedItem
. Položku následne přetypujeme na
Osoba
, pretože je typu object
(to aby bol
ListBox
univerzálne). Túto osobu odovzdáme metóde
Odeber()
na správcovi, ktorá ďalej vykoná fyzické odobratie z
ObservableCollection
.
Dnešný projekt je nižšie na stiahnutie a ja sa na vás teším v budúcej lekcii, PRIPOMIENKOVÉ narodenín v C # .NET WPF - binding , kedy budeme pokračovať v binding.