5. díl - Upomínač narozenin - Propojení prezentační a logické vrstvy

Ostatní jazyky Visual Basic .NET Windows Forms Upomínač narozenin - Propojení prezentační a logické vrstvy

V minulém dílu seriálu tutoriálů o tvorbě formulářových aplikací v VB.NET jsme naprogramovali většinu logické vrstvy aplikace pro upomínání narozenin. Dnes 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 vyhazovat 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 dílech seriálu, 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 As 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 ListBoxu 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 ListBoxu.

Public Sub New()
        InitializeComponent()

        dnesLabel.Text = DateTime.Now.ToLongDateString()
        osobyListBox.DataSource = spravceOsob.Osoby
End Sub
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 As SpravceOsob

Public Sub New(spravceOsob As SpravceOsob)
        InitializeComponent()

        Me.spravceOsob = spravceOsob
End Sub

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 TextBoxu 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í MessageBoxu zobrazí chybovou hlášku. Pokud bychom výjimku takto neošetřili, způsobila by pád aplikace.

Private Sub okButton_Click(sender As Object, e As EventArgs) Handles okButton.Click
        Try
                spravceOsob.Pridej(jmenoTextBox.Text, narozeninyDateTimePicker.Value)
        Catch ex As Exception
                MessageBox.Show(ex.Message, "Chyba", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
End Sub

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 Sub pridatButton_Click(sender As Object, e As EventArgs) Handles pridatButton.Click
        Dim dlg As New OsobaForm(spravceOsob)
        dlg.ShowDialog()
End Sub

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 Sub odebratButton_Click(sender As Object, e As EventArgs) Handles odebratButton.Click
        If Not IsNothing(osobyListBox.SelectedItem) Then
                spravceOsob.Odeber(osobyListBox.SelectedItem)
        End If
End Sub

Důležitá je podmínka, která zjišťuje, zda je v ListBoxu vybraná nějaká položka. Jak vidíte, k vybrané položce se dostaneme přes vlastnost SelectedItem. 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 ListBoxu 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 ListBoxu (např. pro zobrazení narozenin tedy Narozeniny). Podobně fungují samozřejmě i další kontrolky, např. ComboBox.

Přidávání a odebírání
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 Sub ObnovNejblizsi()
        If spravceOsob.Osoby.Count > 0 Then
                Dim nejblizsi As Osoba = spravceOsob.NajdiNejblizsi()
                Dim vek As Integer = nejblizsi.SpocitejVek()
                If DateTime.Today <> nejblizsi.Narozeniny Then
                        vek += 1
                End If
                nejblizsiLabel.Text = nejblizsi.Jmeno & " (" & vek & " let) za " & nejblizsi.ZbyvaDni() & " dní"
        Else
                nejblizsiLabel.Text = "V seznamu nejsou žádné osoby"
        End If
End Sub

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 SelectedItemChanged (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 Not IsNothing(osobyListBox.SelectedItem) Then
        Dim vybrana As Osoba = osobyListBox.SelectedItem
        narozeninyLabel.Text = vybrana.Narozeniny.ToLongDateString()
        veklabel.Text = vybrana.SpocitejVek()
        narozenMonthCalendar.SelectionStart = vybrana.Narozeniny
End If

Aplikaci si můžete vyzkoušet.

Detaily výročí

Příště 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.


 

Stáhnout

Staženo 164x (241.98 kB)
Aplikace je včetně zdrojových kódů v jazyce VB.NET

 

  Aktivity (1)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.

Jak se ti líbí článek?
Celkem (4 hlasů) :
4.54.54.54.54.5


 



 

 

Komentáře
Zobrazit starší komentáře (1)

Avatar
Vetva
Člen
Avatar
Vetva:

Aj keď tomuto :
**

private void pridatButton_Click(object sender, EventArgs e)
{
        OsobaForm osobaForm = new OsobaForm(spravceOsob);
        osobaForm.ShowDialog();
}

**
samozrejme rozumiem , nie je to VB.

 
Odpovědět 14.1.2014 15:11
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Vetva
Jan Vargovský:

Je to jen přepisovaný serial z C#. Autor to určitě opraví :)

 
Odpovědět 14.1.2014 15:13
Avatar
Vetva
Člen
Avatar
Vetva:

Je mi to jasné .Ďakujem za ďalšie znalosti a zručnosti vo VB.

 
Odpovědět 14.1.2014 15:16
Avatar
Odpovědět 14.1.2014 15:37
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Michal Štěpánek:

Mám dotaz: Otevírám formulář (ne dialog, tam je to jasné) tlačítkem, v tu chvíli vytvářím novou instanci toho formuláře. Když mám ale MDI formulář, může se mi stát, že se již otevřený formulář schová za jiný, nově otevřený. Jak ošetřit, aby se po dalším stisku tlačítka nevytvářela další 'nová' instance formu, ale aby se jen aktivoval ten již otevřený form?
Když to neudělám přes novou instanci, prostě tam jen dám do události na tlačítko

Form.Show()

tak mi stačí jen k tomu dopsat

Form.BringToFront()

a formulář (pokud je již jednou otevřený) se "šoupne" do popředí, tzn. neotevře se znovu, ale jen se zaktivuje již otevřený form.
Doufám, že jsem ten dotaz nepopsal moc chaoticky...

Editováno 16.9.2014 9:14
Odpovědět 16.9.2014 9:13
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
Michal Žůrek (misaz):

tak zavoláš BringToFront na instanci schovaného formuláře.

Odpovědět 17.9.2014 16:01
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Michal Štěpánek:

To jo, ale pokud se klikne na to tlačítko, které ten form "otevírá", tak se vytvoří nová instance. Jak tomu zabránit, resp. jak zjistit, že je již form otevřený a tím pádem netvořit instanci, ale jen volat "BringToFront"?

Odpovědět 17.9.2014 16:21
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
Michal Žůrek (misaz):

instanci si někam uložit a pokud ta instance existuje, tak to zavolat, pokud neexistuje vytvořit novou.

Editováno 17.9.2014 16:23
Odpovědět  +1 17.9.2014 16:23
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Michal Štěpánek:

Jak prosté... Vidíš, to mě nenapadlo. Díky. 8-)

Odpovědět 17.9.2014 18:30
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Vetva
Člen
Avatar
Vetva:

Dá sa použiť binding v ListView - ten totiž nemá DataSource.

 
Odpovědět 12.1.2015 12:51
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 10 zpráv z 11. Zobrazit vše