Lekce 5 - Upomínač narozenin - Propojení prezentační a logické vrstvy
V minulé lekci, Upomínač narozenin - Logická vrstva, jsme naprogramovali většinu logické vrstvy aplikace pro upomínání narozenin.
Dnes v C# .NET tutoriálu aplikaci zprovozníme.
Oddělení prezentace a logiky
Nyní máme dokončenou tzv. prezentační část aplikace (formuláře) a logickou část (třídy). Tyto 2 vrstvy se v aplikaci striktně oddělují, jelikož jinak je kód velmi nepřehledný. Nikdy byste neměli provádět výpočty, zápisy do souborů, databáze a podobné věci přímo v kódu formuláře! Vždy si vytvoříme třídu, která poskytuje příslušné metody a tuto třídu z formuláře pouze používáme. Logika zůstane ve třídě. Třída by naopak vůbec neměla vědět o formuláři. Neměla by tedy např. zobrazovat chybové hlášky, ale pouze vyvolávat v případě chyby výjimky. Je potom na formuláři, aby uživateli chybu zobrazil. Právě formulář je ta část aplikace, která s uživatelem komunikuje. Žádná jiná to nedělá.
Pokud vás napadlo, že naše jednoduchá kalkulačka, kterou jsme vytvořili v prvních lekcích kurzu, byla návrhově špatně, máte pravdu. Z důvodu jednoduchosti jsme napsali výpočty rovnou do obslužné metody tlačítka. Správně bychom měli mít nějakou třídu, která by výsledky počítala a tu bychom z formuláře pouze volali.
Dnes si tedy ukážeme, jak se to dělá správně.
Propojení prezentace a logiky
Přejdeme do zdrojového kódu formuláře PrehledForm
a
třídě přidáme privátní atribut typu SpravceOsob
, ve kterém
rovnou vytvoříme instanci správce:
private SpravceOsob spravceOsob = new SpravceOsob();
Instance správce se vytvoří při vytvoření formuláře a formulář s ní dále bude komunikovat a tak provádět úkony, které si přeje uživatel.
V konstruktoru formuláře nastavíme dnesLabel
na aktuální
datum a ListBox
u nastavíme vlastnost DataSource
na
BingList
Osoby
na správci osob. Tím napojíme
ListBox
na BindingList
, odteď bude zobrazovat jeho
obsah a pokud se do listu něco přidá, projeví se to i v
ListBox
u.
public PrehledForm()
{
InitializeComponent();
dnesLabel.Text = DateTime.Now.ToLongDateString();
osobyListBox.DataSource = spravceOsob.Osoby;
}
Přidávání a mazání osob
Abychom něco konečně také viděli, přejdeme k přidávání osob.
Nejprve přejdeme do kódu formuláře OsobaForm
, kde si stejně
jako v předchozím formuláři připravíme správce osob jako privátní
atribut. Kdybychom zde i vytvořili jeho instanci, nebylo by nám to moc
platné, jelikož osoby by byly načtené ve správci v hlavním formuláři. A
načítat je znovu by bylo neefektivní. Necháme si tedy hotového a
načteného správce předat konstruktorem a uložíme ho do připravené
proměnné:
private SpravceOsob spravceOsob; public OsobaForm(SpravceOsob spravceOsob) { InitializeComponent(); this.spravceOsob = spravceOsob; }
Nyní naklikneme tlačítko OK a do správce přidáme osobu pomocí hodnot,
které uživatel do jednotlivých prvků zadal. K hodnotě v
TextBox
u přistoupíme pomocí vlastnosti Text
, k
hodnotě v DateTimePickeru
pomocí vlastnosti
Value
.
Určitě si vzpomínáte, že metoda Pridej()
vyvolá výjimku v
případě příliš krátkého jména nebo data v budoucnosti. Proto kód s
přidáním vložíme do bloku try
, za kterým bude následovat
blok catch
. Pokud výjimka v bloku try
nastane,
program se ihned přesune do bloku catch
, kde pomocí
MessageBox
u zobrazí chybovou hlášku. Pokud bychom výjimku takto
neošetřili, způsobila by pád aplikace.
private void okButton_Click(object sender, EventArgs e) { try { spravceOsob.Pridej(jmenoTextBox.Text, narozeninyDateTimePicker.Value); Close(); } catch (Exception ex) { MessageBox.Show(ex.Message, "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } }
Ke zprávě výjimky se dostaneme přes vlastnost Message
.
Všimněte si také, že zprávě nastavujeme ikonku vykřičníčku. V metodě
již neřešíme žádnou logiku a je díky tomu poměrně krátká.
V tomto formuláři jsme skončili. Přesuneme se zpět do
PrehledForm
, tentokrát do grafické části a naklikneme
tlačítka pridatButton
a odebratButton
.
private void pridatButton_Click(object sender, EventArgs e) { OsobaForm osobaForm = new OsobaForm(spravceOsob); osobaForm.ShowDialog(); }
V obslužné metodě tlačítka pridejButton
vytvoříme novou
instanci formuláře OsobaForm
, které předáme místního
správce osob. Na instanci následně zavoláme metodu
ShowDialog()
. Ta zobrazí nový formulář (stejně jako metoda
Show()
) a k tomu ještě zablokuje zbytek aplikace, který se
zaktivní až v případě, kdy se dialog zavře. Výsledkem je, že se s
hlavním formulářem nedá pracovat dokud dialog nepotvrdíme či neukončíme.
U dialogu (rozumějte pomocného formuláře, který slouží nejčastěji k
zadání dat) se toto většinou dělá. I když nám by v podstatě nevadilo,
kdyby uživatel během zadávání nové osoby aplikaci používal a otevřel
třeba další dialog k zadávání.
Obslužná metoda tlačítka odebratButton
bude vypadat
takto:
private void odebratButton_Click(object sender, EventArgs e) { if (osobyListBox.SelectedItem != null) { spravceOsob.Odeber((Osoba)osobyListBox.SelectedItem); } }
Důležitá je podmínka, která zjišťuje, zda je v ListBox
u
vybraná nějaká položka. Jak vidíte, k vybrané položce se dostaneme přes
vlastnost SelectedItem
. Položku následně přetypujeme na
Osoba
, jelikož je typu object
(to aby byl
ListBox
univerzální). Tuto osobu předáme metodě
Odeber()
na správci, která dále vykoná fyzické odebrání z
listu.
Aplikaci si nyní můžete vyzkoušet, již půjde přidávat a odebírat
osoby. Přidané osoby se ihned objeví v ListBox
u díky
bindingům. ListBox
vždy zobrazuje to, co vrací metoda
ToString()
objektu. U osob tedy zobrazuje jejich jméno. Pokud
bychom chtěli zobrazit jinou vlastnost, zadáme její název do vlastnosti
DisplayMember
na ListBox
u (např. pro zobrazení
narozenin tedy Narozeniny
). Podobně fungují samozřejmě i
další ovládací prvky, např. ComboBox
.
Nejbližší narozeniny
Do třídy hlavního formuláře si přidáme pomocnou privátní metodu
ObnovNejblizsi()
, která obnoví popisek s nejbližšími
narozeninami.
private void ObnovNejblizsi() { if (spravceOsob.Osoby.Count > 0) { Osoba nejblizsi = spravceOsob.NajdiNejblizsi(); int vek = nejblizsi.SpoctiVek(); if (DateTime.Today != nejblizsi.Narozeniny) vek++; nejblizsiLabel.Text = nejblizsi.Jmeno + " (" + vek + " let) za " + nejblizsi.ZbyvaDni() + " dní"; } else nejblizsiLabel.Text = "Žádné osoby v seznamu"; }
V případě, že jsou ve správci osob nějaké osoby, najdeme osobu s nejbližšími narozeninami. Získáme si věk této osoby a pokud nemá narozeniny právě dnes, přičteme k němu jedničku, aby se jednalo vždy o budoucí věk osoby. Do příslušného labelu poté poskládáme jméno osoby, do závorky její budoucí věk a kolik dní do narozenin zbývá.
V případě, že ve správci žádné osoby nemáme, zobrazíme o tom v labelu zprávu uživateli.
Metodu zavoláme na konci konstruktoru formuláře a také po přidání a odebrání osoby (na konci obslužných metod tlačítek, ale samozřejmě stále v podmínkách).
Detaily osoby
Shází nám již jen zobrazovat detaily vybrané osoby. Naklikneme si
ListBox
, čímž nám Visual Studio vygeneruje obslužnou metodu
události SelectedIndexChanged
(změna vybrané položky). Zde
musíme opět zkontrolovat, zda je nějaká položka (osoba) vybraná. Pokud
ano, načteme si jí a její vlastnosti zobrazíme v příslušných labelech a
MonthCalendar
nastavíme na její datum narození.
if (osobyListBox.SelectedItem != null) { Osoba vybrana = (Osoba)osobyListBox.SelectedItem; narozeninyLabel.Text = vybrana.Narozeniny.ToLongDateString(); vekLabel.Text = vybrana.SpoctiVek().ToString(); narozenMonthCalendar.SelectionStart = vybrana.Narozeniny; }
Aplikaci si můžete vyzkoušet.
V příští lekci, Upomínač narozenin - Ukládání dat a závěr, dokončíme ukládání a načítání dat z/do souboru. Dosavadní zdrojové kódy jsou vám jako vždy k dispozici níže. Pokud jste se někde zasekli, najděte si chybu.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1532x (346.33 kB)
Aplikace je včetně zdrojových kódů v jazyce C#