5. diel - Code Behind v C # .NET WPF a dokončenie kalkulačky
V minulej lekcii, Návrh formulára pre kalkulačku v C # .NET WPF , sme nakódovali formulár pre jednoduchú kalkulačku. Dnes v C# .NET tutoriálu do aplikácie pridáme jednoduchú logiku a na konci si vysvetlíme ako WPF vnútri funguje.
Code Behind
Prezentačná časť aplikácie je napísaná v XAML. Ten nám však samozrejme nestačí a preto má každé okno okrem XAML kódu ešte tzv. Code Behind (kód na pozadí), ktorý obsahuje volania logiky aplikácie. Do tohto kódu sa z dizajnérov presunieme pravým kliknutím myši a zvolením možnosti View Code. Alternatívne môžeme používať klávesové skratky Ctrl + Alt + 0 (jedná sa o nulu na alfanumerickej klávesnici) pre presun do Code Behind a Shift + F7 na presun do grafického návrhára.
Code Behind nášho formulára vyzerá asi takto (vynechal som menné priestory):
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } }
Vidíme, že formulár je reprezentovaný triedou, ktorá dedí z
Window
. Window
je trieda, predstavujúce prvok
Window
. Každý ovládací prvok má vo WPF má svoju triedu, ako
inak v objektovom jazyku V
konstruktoru formuláre sa volá záhadná metóda
InitializeComponents()
, ktorá vnútorne naparsuje XAML a vytvorí
podľa neho inštancie jednotlivých prvkov. Tým sa formulár "zostaví".
Pomenovanie ovládacích prvkov
Keď chceme s nejakým prvkom pracovať z Code Behind, musíme mu priradiť
meno. Staršie verzie Graphic Designeri ovládacie prvky nepojmenovávaly
vôbec, neskoršie je začali číslovať ako TextBlock1
a podobne.
V našom prípade budeme pri výpočte potrebovať čítať z dvoch elementov
TextBox
s číslami, elementu ComboBox
s operáciou,
písať do TextBlock
s výsledkom a obslúžiť udalosť kliknutí
na tlačidlo.
Presunieme sa späť do XAML a týmto prvkom zmeníme (v starších VS
pridáme) atribút Name
s nasledujúce hodnotou pre jednotlivé
prvky: cislo1TextBox
, cislo2TextBox
,
operaceComboBox
, vysledekTextBlock
,
vypocitejButton
. Všimnite si, že mená sme zvolili tak, aby
končila typom ovládacieho prvku. Pri väčších formulároch je to oveľa
prehľadnejšie. Určite sa vyvarujeme názvom ako tlacitko1
a
podobne.
Udalosti
WPF sú postavené na udalostiach. My budeme v kalkulačke reagovať na jedinú udalosť, ktorou je kliknutie na tlačidlo. V dizajnéri na tlačidlo poklepeme, budeme presmerovaní na Code Behind, kde sa nám vygeneruje nasledujúce metóda:
private void vypocitejButton_Click(object sender, RoutedEventArgs e) { }
Metóda sa spustí vo chvíli, keď na tlačidlo používateľ klikne. Ako zastáva docielené sa dozvieme neskôr. Udalosti môžeme priraďovať a mazať tiež v oknu Properties. Stačí prvok označiť a kliknúť na ikonu blesku, čím sa presunieme z vlastností do udalostí. Tlačidlo vedľa nás potom presunie späť na vlastnosti:
Do vygenerované metódy vložme nasledujúci kód:
// příprava proměnných string operace = operaceComboBox.Text; double cislo1 = double.Parse(cislo1TextBox.Text); double cislo2 = double.Parse(cislo2TextBox.Text); double vysledek = 0; // výpočet if (operace == "+") vysledek = cislo1 + cislo2; else if (operace == "-") vysledek = cislo1 - cislo2; else if (operace == "*") vysledek = cislo1 * cislo2; else if (operace == "/") { if (cislo2 != 0) vysledek = cislo1 / cislo2; else MessageBox.Show("Nulou nelze dělit"); } vysledekTextBlock.Text = vysledek.ToString();
Na prvých riadkoch si pripravíme premenné, do ktorých uložíme potrebné
hodnoty z ovládacích prvkov. K textu v TextBox
UIK vybranej
textovej položke ComboBox
u sa dostaneme cez vlastnosť
Text
. Vidíme tu, prečo sme prvky pomenovávali. V aplikácii
nijako neriešime situáciu, kedy užívateľ zadá nezmyselný vstup a program
tak spadne na výnimku pri parsovanie tejto hodnoty. Ako sa správne ošetrujú
chyby si ukážeme až v ďalších lekciách, môžete sa sem potom vrátiť a
validáciu dodať.
Výpočet výsledku by mal byť jasný. Zaujímavá je tu len kontrola, či
nedelíme nulou. Ak áno, zobrazíme tzv. MessageBox
, čo je okno
so správou pre užívateľov, ktoré určite dobre poznáte z iných
aplikácií. Slúži nám k tomu rovnomenná statická trieda.
MessageBox
vyzerá asi takto:
Na konci metódy už len priradíme do TextBlock
u výsledok,
ktorý musíme previesť na string
, pretože priraďujeme do
vlastnosti Text
.
Môžete si aplikáciu vyskúšať.
WPF pod pokrievkou
Než začneme zas pokročilejšie látku, venujme niekoľko odsekov tomu, ako aplikácia funguje pod pokrievkou. Je to trochu taká teória navyše, ak ste nedočítali tunajšie objektový C# .NET kurz do konca, asi nebudete všetkému rozumieť, v praktickom vytváranie aplikácií vám to však nebude nijako brániť.
Parciálny trieda
Zamerajme sa ešte raz na triedu MainWindow
(teda na Code
Behind). Bystrejší z vás si iste všimli, že trieda je parciálny (má
modifikátor partial
). To znamená, že je definovaná vo
viacerých súboroch. Tá druhá chýbajúcu časť je skrytá a môžeme do nej
prejsť tak, že klikneme na volanie metódy InitializeComponent()
a stlačíme F12, čo nás prenesie k jej implementáciu.
Dostali sme sa do pomerne škaredé triedy, ktorú nám Visual Studio samo vygenerovalo s novým oknom. Vidíme tu dve metódy: InitializeComponent () a Connect ().
InitializeComponent()
si načíta XAML a zavolá na nehoLoadComponent()
. Všimnite si nad triedou atribútov zo menného priestoruCodeDom
. Tu sú triedy pre generovanie C# kódu za behu aplikácie. Presne to metóda robí, dekóduje XAML a vytvára inštancie ovládacích prvkov podľa ich definície v XAML.- Metóda
Connect()
sprostredkováva ono magické napojenie metód v Code Behind. Vidíme tu, že je použitýEventHandler
:
vypocitejButton.Click += new System.Windows.RoutedEventHandler(this.vypocitejButton_Click);
Metóda ďalej sprístupňuje jednotlivé ovládacie prvky pod ich názvami, to je realizované tým škaredým switchom Do tohto súboru nebudeme nikdy nijako zasahovať, je však dôležité, aby sme chápali, ako WPF funguje.
Vytváranie ovládacích prvkov za behu aplikácie
Keďže ovládacie prvky sú obyčajné triedy, určite vás napadlo, či ich môžeme na formulár pridávať tak, že vytvoríme ich inštancie v Code Behind namiesto toho, aby sme ich písali do XAML. Áno, ide to. Teoreticky by sme XAML kód nemuseli vôbec používať. Prakticky by sme sa však v návrhu formulárov vôbec nevyznali.
Ukážme si nejakú časť nášho XAML, napr. Grid
. Ten vyzerá
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 by sme rovnaký výsledok dosiahli týmto zápisom:
Grid grid = new Grid(); grid.Margin = ((Thickness)(TypeDescriptor.GetConverter(typeof(Thickness)).ConvertFromInvariantString("0"))); ColumnDefinition columnDefinition = new ColumnDefinition(); columnDefinition.Width = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("*"))); grid.ColumnDefinitions.Add(columnDefinition); ColumnDefinition columnDefinition2 = new ColumnDefinition(); columnDefinition2.Width = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("50"))); grid.ColumnDefinitions.Add(columnDefinition2); ColumnDefinition columnDefinition3 = new ColumnDefinition(); columnDefinition3.Width = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("*"))); grid.ColumnDefinitions.Add(columnDefinition3); ColumnDefinition columnDefinition4 = new ColumnDefinition(); columnDefinition4.Width = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("50"))); grid.ColumnDefinitions.Add(columnDefinition4); ColumnDefinition columnDefinition5 = new ColumnDefinition(); columnDefinition5.Width = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("*"))); grid.ColumnDefinitions.Add(columnDefinition5); RowDefinition rowDefinition = new RowDefinition(); rowDefinition.Height = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("*"))); grid.RowDefinitions.Add(rowDefinition); RowDefinition rowDefinition2 = new RowDefinition(); rowDefinition2.Height = ((GridLength)(TypeDescriptor.GetConverter(typeof(GridLength)).ConvertFromInvariantString("30"))); grid.RowDefinitions.Add(rowDefinition2);
Asi uznáte, že to nie je práve prehľadné a to sa jedná o malú časť formulára. Takže práve preto sa používa XAML, kde je stromová štruktúra prehľadná a jednoduchá.
Niekedy však môže byť naopak užitočné vytvoriť nejakú časť aplikácie alebo niečo donastaviť až v Code Behind miesto v XAML. Účelom tejto časti kurzu bolo, aby ste vedeli, že to ide.
V budúcej lekcii, Riešené úlohy k 1.-5. lekciu WPF v C # .NET , začneme tvoriť robustnejšie aplikáciu, pôjde o pripomienkovej narodenín priateľov. Zdrojové kódy kalkulačky sú ako vždy na stiahnutie nižšie.
V nasledujúcom cvičení, Riešené úlohy k 1.-5. lekciu WPF v C # .NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 836x (400.42 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#