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 5 - Code Behind v VB.NET WPF a dokončení kalkulačky

V minulém dílu, Návrh formuláře pro kalkulačku v VB.NET WPF, jsme nakódovali formulář pro jednoduchou kalkulačku.

Dnes do aplikace přidáme jednoduchou logiku a na konci si vysvětlíme jak WPF uvnitř funguje.

Code Behind

Prezentační část aplikace je napsaná v XAMLu. Ten nám však samozřejmě nestačí a proto má každé okno kromě XAML kódu ještě tzv. Code Behind (kód na pozadí), který obsahuje volání logiky aplikace. Do tohoto kódu se z designeru přesuneme pravým kliknutím myši a zvolením možnosti View Code. Alternativně můžeme používat klávesové zkratky CTRL + ALT + 0 (jedná se o nulu na alfanumerické klávesnici) pro přesun do Code Behind a Shift + F7 pro přesun do grafického návrháře.

Code Behind našeho formuláře vypadá asi takto (vynechal jsem jmenné prostory):

Class MainWindow

End Class

Na pozadí tato třída dědí od třídy Window a má konstruktor, ve kterém se volá metoda InitializeCom­ponent.

Pojmenování kontrolek

Když chceme s nějakou kontrolkou pracovat z Code Behind, musíme ji přiřadit jméno. V našem případě budeme při výpočtu potřebovat číst z dvou TextBoxů s čísly, ComboBoxu s operací, psát do TextBlocku s výsledkem a obsloužit událost kliknutí na tlačítko.

Přesuneme se zpět do XAMLu a těmto kontrolkám přiřadíme atribut Name s následující hodnotou pro jednotlivé kontrolky: cislo1TextBox, cislo2TextBox, operaceComboBox, vysledekTextBlock, vypocitejButton. Všimněte si, že jména jsme zvolili tak, aby končila názvem kontrolky. Při větších formulářích je to mnohem přehlednější. Určitě se vyvarujte názvům jako tlacitko1 a podobně.

Události

WPF jsou postavené na událostech. My budeme v kalkulačce reagovat na jedinou událost, kterou je kliknutí na tlačítko. V designeru na tlačítko poklepeme, budeme přepnuti do Code Behind, kde se nám vygeneruje následující metoda:

Private Sub vypocitejButton_Click(sender As Object, e As RoutedEventArgs) Handles vypocitejButton.Click

End Sub

Metoda se spustí ve chvíli, kdy na tlačítko uživatel klikne. Využívá se jednoduše klíčového slova Handles, se kterým jsme se již setkali ve Windows Forms. Události můžeme přiřazovat a mazat také v oknu Properties. Stačí kontrolku označit a kliknout na ikonu blesku, čímž se přesuneme z vlastností do událostí. Tlačítko vedle nás poté přesune zpět na vlastnosti:

Události ve WPF v VB.NET Visual Studio - Okenní aplikace ve VB.NET WPF

Do vygenerované metody vložme následující kód:

'Příprava proměnných
Dim cislo1 As Double = cislo1TextBox.Text
Dim cislo2 As Double = cislo2TextBox.Text
Dim operace As String = operaceComboBox.Text
Dim vysledek As Double = 0
'Výpočet
Select Case operace
    Case "+"
        vysledek = cislo1 + cislo2
    Case "-"
        vysledek = cislo1 - cislo2
    Case "*"
        vysledek = cislo1 * cislo2
    Case "/"
        If cislo2 = 0 Then
            MessageBox.Show("Nelze dělit nulou")
            Exit Sub
        End If
        vysledek = cislo1 / cislo2
End Select
vysledekTextBlock.Text = vysledek

Na prvních řádcích si připravíme proměnné, do kterých uložíme potřebné hodnoty z kontrolek. K textu v TextBoxu i k vybrané textové položce ComboBoxu se dostaneme přes vlastnost Text. Vidíme zde, proč jsme kontrolky pojmenovávali. V aplikaci nijak neřešíme situaci, kdy uživatel zadá nesmyslný vstup a program tak spadne na výjimku při parsování této hodnoty. Jak se správně ošetřují chyby si ukážeme až v dalších dílech, můžete se sem poté vrátit a validaci dodat.

Výpočet výsledku by měl být jasný. Zajímavá je zde pouze kontrola, zda nedělíme nulou. Pokud ano, zobrazíme tzv. MessageBox, což je okno se zprávou pro uživatele, které jistě dobře znáte z jiných aplikací. Slouží nám k tomu stejnojmenná statická třída. MessageBox vypadá asi takto:

MessageBox v VB.NET - Okenní aplikace ve VB.NET WPF

Na konci metody již jen přiřadíme do vlastnosti Text TextBlocku výsledek.

Můžete si aplikaci vyzkoušet.

Kompletní kalkulačka v VB.NET WPF - Okenní aplikace ve VB.NET WPF

WPF pod pokličkou

Než začneme zas pokročilejší látku, věnujme několik odstavců tomu, jak aplikace funguje pod pokličkou. Je to trochu taková teorie navíc, pokud jste nedočetli zdejší objektový seriál do konce, asi nebudete všemu rozumět, v praktickém vytváření aplikací vám to však nebude nijak bránit.

Parciální třída

Zaměřme se ještě jednou na třídu MainWindow (tedy na Code Behind). Třída je parciální. To znamená, že je definována ve více souborech. Ta druhá chybějící část je skrytá a můžeme do ni přejít tak, že v Solution Exploreru rozbalíte MainWindow tak, abyste viděli metodu InicializeCom­ponents. Do metody přejdeme.

InicializeComponents - Okenní aplikace ve VB.NET WPF

Dostali jsme se do poměrně ošklivé třídy, kterou nám Visual Studio samo vygenerovalo s novým oknem. Vidíme zde dvě metody: InitializeCom­ponent() a Connect().

InitializeCom­ponent() si načte XAML a zavolá na něj LoadComponent(). Všimněte si nad třídou atributů ze jmenného prostoru CodeDom. Zde jsou třídy pro generování VB kódu za běhu aplikace. Přesně to metoda dělá, parsuje XAML a vytváří podle něj instance kontrolek.

Metoda Connect() zprostředkovává ono magické napojení metod v CodeBehind.

Metoda zpřístupňuje jednotlivé kontrolky pod jejich názvy, to je realizované tím ošklivým Select Case :) Do tohoto souboru nebudeme nikdy nijak zasahovat, je však důležité, abychom chápali, jak WPF funguje.

Vytváření kontrolek za běhu aplikace

Jelikož kontrolky jsou obyčejné třídy, určitě vás napadlo, zda je můžeme na formulář přidávat tak, že vytvoříme jejich instance v Code Behind místo toho, abychom je psali do XAMLu. Ano, jde to. Teoreticky bychom XAML kód nemuseli vůbec používat. Prakticky bychom se však v návrhu formulářů vůbec nevyznali.

Ukažme si nějakou část našeho XAMLu, např. Grid. Ten vypadal takto:

<Grid Margin="0">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="50"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="50"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="30"/>
    </Grid.RowDefinitions>
</Grid>

V Code Behind bychom stejného výsledku dosahli tímto zápisem:

Dim grid As New Grid()
grid.Margin = DirectCast(TypeDescriptor.GetConverter(GetType(Thickness)).ConvertFromInvariantString("0"), Thickness)
Dim columnDefinition As New ColumnDefinition()
columnDefinition.Width = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("*"), GridLength)
grid.ColumnDefinitions.Add(columnDefinition)
Dim columnDefinition2 As New ColumnDefinition()
columnDefinition2.Width = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("50"), GridLength)
grid.ColumnDefinitions.Add(columnDefinition2)
Dim columnDefinition3 As New ColumnDefinition()
columnDefinition3.Width = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("*"), GridLength)
grid.ColumnDefinitions.Add(columnDefinition3)
Dim columnDefinition4 As New ColumnDefinition()
columnDefinition4.Width = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("50"), GridLength)
grid.ColumnDefinitions.Add(columnDefinition4)
Dim columnDefinition5 As New ColumnDefinition()
columnDefinition5.Width = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("*"), GridLength)
grid.ColumnDefinitions.Add(columnDefinition5)
Dim rowDefinition As New RowDefinition()
rowDefinition.Height = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("*"), GridLength)
grid.RowDefinitions.Add(rowDefinition)
Dim rowDefinition2 As New RowDefinition()
rowDefinition2.Height = DirectCast(TypeDescriptor.GetConverter(GetType(GridLength)).ConvertFromInvariantString("30"), GridLength)
grid.RowDefinitions.Add(rowDefinition2)

Asi uznáte, že to není zrovna přehledné a to se jedná o malou část formuláře. Takže právě proto se používá XAML, kde je stromová struktura přehledná a jednoduchá.

Někdy však může být naopak užitečné vytvořit nějakou část aplikace nebo něco donastavit až v Code Behind místo v XAMLu. Účelem této části seriálu bylo, abyste věděli, že to jde.

Příště, Upomínač narozenin v VB .NET WPF - Návrh oken, začneme tvořit robustnější aplikaci, půjde o upomínač narozenin přátel. Zdrojové kódy kalkulačky jsou jako vždy ke stažení níže.


 

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 118x (221.47 kB)
Aplikace je včetně zdrojových kódů v jazyce VB

 

Předchozí článek
Návrh formuláře pro kalkulačku v VB.NET WPF
Všechny články v sekci
Okenní aplikace ve VB.NET WPF
Přeskočit článek
(nedoporučujeme)
Upomínač narozenin v VB .NET WPF - Návrh oken
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
3 hlasů
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.
Aktivity