Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 8 - Upomínač narozenin v C# .NET WPF - Propojení vrstev

V minulé lekci, Upomínač narozenin v C# .NET WPF - Logická vrstva, jsme naprogramovali většinu logické vrstvy naší aplikace Upomínače narozenin.

V dnešním WPF tutoriálu začneme propojovat logickou a prezentační vrstvu aplikace k upomínání narozenin. Naučíme se výjimky, dialogy a bindovat ObservableCollection na element ListBox.

Budeme rozšiřovat naši aplikaci z lekce Upomínač narozenin v C# .NET WPF - Logická vrstva.

Oddělení prezentace a logiky

Nyní máme dokončenou tak zvanou prezentační část aplikace (formuláře) a logickou část (třídy). Tyto dvě vrstvy se v aplikaci striktně oddělují, jelikož jinak by byl kód velmi nepřehledný.

Nikdy bychom 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á.

Naše jednoduchá kalkulačka, kterou jsme vytvořili v prvních lekcích kurzu, byla návrhově špatně. 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 její metody bychom z formuláře pouze volali. XAML a i jeho Code Behind je tedy stále prezentační vrstva aplikace.

XAML definuje jak formulář vypadá, Code Behind volá logiku, kterou neobsahuje.

Dnes si tedy ukážeme, jak se to dělá správně.

Propojení prezentace a logiky v naší aplikaci

Přejdeme do Code Behind formuláře MainWindow a třídě přidáme privátní atribut typu SpravceOsob, ve kterém rovnou vytvoříme instanci správce:

private readonly SpravceOsob spravceOsob = new();

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.

Přidání osob

Abychom něco konečně také viděli, přejdeme k přidání osob.

Kód formuláře OsobaWindow

Nejprve přejdeme do kódu formuláře OsobaWindow, 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 readonly SpravceOsob spravceOsob;

public OsobaWindow(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 elementu DatePicker přistoupíme pomocí vlastnosti SelectedDate, která je nullovatelného typu DateTime?.

Metoda OkButton_Click()

V lekci Upomínač narozenin v C# .NET WPF - Logická vrstva jsme zadali, že metoda Pridej() vyvolá výjimku v případě příliš krátkého jména, nevyplněného data nebo data v budoucnosti. Proto kód 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í okna MessageBox zobrazí chybovou hlášku:

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);
    }
}

Pokud bychom výjimku neošetřili blokem try-catch, způsobila by pád aplikace.

Ke zprávě výjimky se dostaneme přes vlastnost Message. Zprávě nastavujeme ikonu 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.

Kód formuláře MainWindow

Přesuneme se zpět do třídy MainWindow, tentokrát do grafického návrháře. Naklikneme tlačítko pridatButton a jeho obslužnou metodu upravíme takto:

private void PridatButton_Click(object sender, RoutedEventArgs e)
{
    OsobaWindow osobaWindow = new(spravceOsob);
    osobaWindow.ShowDialog();
}

V obslužné metodě tlačítka pridatButton vytvoříme novou instanci formuláře OsobaWindow, 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 dialogů se toto většinou dělá (dialogy rozumějme pomocné formuláře, který slouží nejčastěji k zadání dat). 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í.

Když bychom aplikaci nyní spustili, osobu bychom sice přidali do kolekce ObservableCollection, nicméně bychom ji v elementu ListBox neviděli. Je to samozřejmě z toho důvodu, že ListBox není na tuto kolekci napojený. Toho docílíme pomocí bindingu.

Při naklikávání tlačítek se metoda Click() vygeneruje v souladu s názvem tlačítka. To znamená, že metoda bude začínat malým písmenem. Opravu je nejlépe nechat provést Visual Studio pomocí Quick Actions.

Binding

Pokud chceme bindovat, musíme oknu nejprve nastavit tak zvaný kontext. To je objekt, jehož vlastnosti budeme bindovat. To uděláme nejjednodušeji v konstruktoru třídy MainWindow:

DataContext = spravceOsob;

Instance správce osob je nyní nastavena jako datový kontext hlavního okna a my v tomto okně můžeme zobrazovat její vlastnosti.

Přesuneme se do XAML a elementu <ListBox> dodáme atribut ItemsSource:

<ListBox Name="osobyListBox" Grid.Column="0" Grid.Row="2" Margin="0, 0, 0, 10" ItemsSource="{Binding Osoby}"/>

Tím říkáme, že zdrojem položek v elementu ListBox je vlastnost Osoby na kontextu, kterým je správce osob.

Testování

Nyní si aplikaci spustíme a přidáme nějaké osoby:

upomínač narozenin přidání jmen - WPF - Okenní aplikace v C# .NET

Přidané osoby se ihned objeví v elementu ListBox díky bindingům. ListBox vždy zobrazuje to, co vrací metoda ToString() jeho položek. U osob tedy zobrazuje jejich jméno. Podobně fungují samozřejmě i další ovládací prvky, např. ComboBox.

Odebrání osob

Obslužná metoda tlačítka odebratButton v kódu formuláře MainWindow bude vypadat takto:

private void OdebratButton_Click(object sender, RoutedEventArgs e)
{
    if (osobyListBox.SelectedItem != null)
    {
        spravceOsob.Odeber((Osoba)osobyListBox.SelectedItem);
    }
}

Důležitá je podmínka, která zjišťuje, zda je v elementu ListBox vybraná nějaká položka. 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 ObservableCollection.

Dnešní projekt je níže ke stažení a já se na vás těším v příští lekci, Upomínač narozenin v C# .NET WPF - Bindingy, kdy budeme pokračovat v bindingu.


 

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.

Předchozí článek
Upomínač narozenin v C# .NET WPF - Logická vrstva
Všechny články v sekci
WPF - Okenní aplikace v C# .NET
Přeskočit článek
(nedoporučujeme)
Upomínač narozenin v C# .NET WPF - Bindingy
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
69 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity