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í.

WPF Programátorská kaklulačka - Design a CodeBehind

Tento tutoriál je zameraný na praktické využitie nadobudnutých vedomostí z C# .NET a WPF z tunajších tutoriálov. Pridáva tiež pár zatiaľ nezmiňovaných vecí a nie celkom typických riešenia, prípadne alternatív k podobným postupom v iných tutoriáloch, ako napríklad použitie "univerzálneho" typu dynamic.

Nie je zameraný na XAML ako taký, ten je popísaný v predchádzajúcich dieloch dosť obšírne. Na konci budete mať funkčnú aplikáciu, ktorá nájde uplatnenie hlavne u programátorov jednočipových MCU.

Zadania

Zadaním je programátorská kalkulačka, ktorá by mala spĺňať tieto podmienky, ktoré mi chýba u tradičných kalkulačiek:

  1. Stále on top - neschovávať sa pri každej voľbe iného okna, čo mne u bežných kalkulačiek slušne povedané "irituje" :)
  2. Zaberať čo najmenej miesta - Což vychádza z prvej podmienky, aby pokiaľ možno neprekážala. Na väčšine IDE (editorov) sa nejaké to miesto, kam ju strčiť, nájde.
  3. Zobrazovať každú hodnotu v decimálnom, hexadecimáním a binárnom tvaru naraz
  4. Prístup k akejkoľvek pozícii v zadanom čísle pre jeho zmenu
  5. V binárne a hexa sekcii oddelené jednotlivé bajty, doplnené o patričný počet núl (0F, 0001001) - pre prehľadnosť
  6. Použitie najbežnejších aritmetických a logických operácií
  7. Výber dátového typu, na ktorom sa budú operácie vykonávať
programátorská kalkulačka - Zdrojákoviště C # .NET - Okenné aplikácie WPF

Dizajn

Je minimalistiký a rýdzo účelový, všetko je podriadené podmienke čo najmenšieho okna.

Aplikácia sa skladá z deviatich textbox, troch buttonov, troch textBlocků, ComboBox a jednej čiary, ktorú reprezentuje rectangle a toť všetko. Oproti štandardným kalkulačkám je to vlastne len ich displej, všetko potrebné je predsa na klávesnici, tak na čo tam pchať veľa tlačidiel?

Všetky prvky majú svoj chlievik v gridu a ich layout je vzťahujúci práve k nemu. To a zároveň skutočnosť, že takmer všetky prvky vrátane okna a gridu majú svoje property šírky a výšky až na výnimky nastavené na auto, zabezpečí, že okno rastie rovnomerne s textom v boxoch. Textbox majú len nastavenú minimálnu šírku. Bez textu sú moc úzke a okrem toho, že to zle vyzerá, sa do nich taky zle triafa :)

Veľkosť okna je tak daná hlavne veľkosťou fontu zadaného v properties okna. Slepúch, ako som ja, si ho môžu zväčšiť.

Ďalšie úsporu miesta zabezpečí to, že sa zbavíme rámčeku okna. To docielime nastavením property WindowStyle na none alebo v XAML pridaním do riadku okna WindowStyle = "None". Tým sa ale pripravíme o akúkoľvek manipuláciu s oknom. Keď ho raz otvoríme, tak už sa ho nezbavíme. Leda v správcovi úloh - čo s tým? Musíme ovládacie prvky preniesť na okno samotnej - ale o tom až v ďalšom diele.

Implementácia

Prvý podmienku zabezpečíme nasledovne: v XAML do koreňového elementu okna zadáme

Topmost="True"

Alebo jednoducho zaškrtneme checkbox pri príslušnej vlastnosti v properties okna. Odstránením rámčeku sa zdá zbytočné zadávať oknu titulok a ikonu, ale pretože sa zobrazujú na taksbaru, tak je tam dáme.

Pre zobrazenie výsledku by som normálne použil textBlocky, ale pretože majú trochu iný dizajn a text v okienku zobrazujú trochu posunutý proti textbox, tak som z dôvodu zjednotenia vzhľadu využil textbox a vlastnosť "focusable" nastavil na false, aby sa do nich nedalo písať.

Na spodnej strane sú umiestnené tri buttony - dva pre Minimize a close a jeden, ktorý bude otvárať okno s nápovedou. Buttony nemajú žiadny text, len sú ako pozadie použité ikony stiahnuté z IconFinder a ako jediné elementy majú dané pevné rozmery.

Code Behind

Deklarácie a konštruktor

Deklarujeme / definujeme kolekciu znakov zastupujúcich jednotlivé operátormi. Tú potom odovzdáme ako ItemsSource ComboBox pre výber operácie a zriadime inštancie tried zaisťujúcich samotný prevod a výpočet:

Prevod prevody;
Vypocet vypocty;

//itemy comboBoxu
List<string> operatory = new List<string>() { "+", "-", "x", "/", "%", "&", "|", "^", "~", "<<", ">>" };

//konstruktor
public MainWindow()
{
    InitializeComponent();
    vypocty = new Vypocet();
    prevody = new Prevod(vypocty);
    comboBoxOperator.ItemsSource = operatory;
    comboBoxOperator.FontSize = 10;
    ComboBoxTyp.ItemsSource = prevody.dateTypeDictionary.Keys;
    ComboBoxTyp.FontSize = 10;
}

Začnem asi najzložitejšie metódou:

private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox tb = sender as TextBox;

    string s = tb.Text;
    tb.CaretIndex = tb.Text.Length;
    if (tb.IsFocused)
    {
        if (s != "")
        {
            try
            {
                prevody.prevod(s, tb.TabIndex);
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            vypocty.Result = 0;
            showResult();
            wiewDec();
            wiewHex();
            wiewBin();
        }
        else
        {
            if (tb.TabIndex % 2 == 0) clearA();
            else clearB();
            clearRes();
        }

    }
}

Je to metóda pre obsluhu udalosti textChanged a bude spoločná pre všetky textbox, pretože inak by tam bolo šesť metód, ktoré robia to isté - volajú metódu pre prevod reťazca na hodnotu premennej.

Na druhú stranu ale musíme vedieť, s ktorým textbox práve pracujeme, takže si na začiatku zriadime jeho inštanciu. Keďže sa ale sender prezentuje ako object, musíme ho na textbox pretypovať:

TextBox tb = sender as TextBox;

Pre identifikáciu použijeme jeho tabindex. Zadáme v properties alebo XAML, ako je komu libo, hodnoty od 0 do 5 pre jednotlivé textbox podľa nasledujúcej schémy:

Kalkulačka v C# .NET WPF - Zdrojákoviště C # .NET - Okenné aplikácie WPF

A pretože v tejto metóde meníme texty všetkých šiestich operandových textbox, tak sa tiež šesťkrát zavolá. Ide vlastne o rekurzívne volanie metódy (volá aj keď nepriamo sama seba), čo by narobilo pekný zmätok a tak musíme zabezpečiť, aby sa jej kód vykonal len na textbox, s ktorým pracujeme. To zistíme vlastností:

if (tb.IsFocused)

Po teste, či nie je reťazec prázdny (po mazanie Backspace) sa vykoná samotný prevod, ktorý je v bloku try-catch. To preto, aby sa niekto nepokúšal prevádzať treba 354 na byte. Ďalej zobrazíme hodnotu vo všetkých požadovaných tvaroch (dec, hex, bin)

if (s != "")
{
    try
    {
        prevody.prevod(s, tb.TabIndex);
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    vypocty.Result = 0;
    showResult();
    wiewDec();
    wiewHex();
    wiewBin();
}

Ak je prázdny, vymaže sa príslušný riadok s operandy. Ktorý riadok to je so zistí práve z tabindex. Horný riadok má párne a spodná nepárne, čo zistíme jednoducho operátorom modulo (nepárne budú mať zvyšok).

else
{
    if (tb.TabIndex % 2 == 0) clearA();
    else clearB();
    clearRes();
}

Ďalej budeme pokračovať metódami pre obsluhou vstupov z HID - teda myši a klávesnice. Vzniká tu nutnosť filtrovať znaky prichádzajúce z klávesnice a to nie na udalosť textChanged, to už je neskoro. Musíme filtrovať v metóde obsluhy udalosti textBox_Previ­ewTextInput, teda kým nie je znak do textu zapracovaný.

U decimálneho zobrazenie je to jednoduché. Potrebujeme vedieť, či sa jedná o číslicu. To sa dozvieme za pomoci:

char.IsDigit

U hex hodnoty potrebujeme pridať ešte znaky AF (af). K tomu slúži zriadená "tabuľka" string hexValue = "0123456789AB­CDEFabcdef";

Rovnako tak to bude fungovať aj pre binárne hodnoty.

// znaky 0,1,2,3,4,5,6,7,8,9,0
private void textBoxDec_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    if (!char.IsDigit(e.Text, 0)) e.Handled = true;
}

// znaky 0,1,2,3,4,5,6,7,8,9,0,A,B,C,D,E,F
private void textBoxHex_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    string hexValue = "0123456789ABCDEFabcdef";
    if (!hexValue.Contains(e.Text)) e.Handled = true;

}

// znaky 0,1
private void textBoxBin_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    string binValue = "01";
    if (!binValue.Contains(e.Text)) e.Handled = true;
}

V ďalšom diele dokončíme Code Behind a pozrieme sa na triedy vykonávajúce samotné prevody a operácie. Zdrojový kód vrátane ikoniek je priložený.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 161x (38.1 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#

 

Všetky články v sekcii
Zdrojákoviště C # .NET - Okenné aplikácie WPF
Článok pre vás napísal ostrozan
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje především embedded systémům (mikrokontrolery) a vývoji jejich GUI v C# WPF , Java.
Aktivity