Blog Dla Młodszych Programistów C#/.NET

W poprzednim artykule zaczęliśmy implementować kalkulator jako aplikacja desktopowa w windows forms. Jeżeli nie widziałeś jeszcze poprzedniego artykułu, to koniecznie od niego zacznij (część 1 – Interfejs Użytkownika) i dopiero wtedy wróć do tego materiału.

Mamy już gotowy interfejs użytkownika, więc teraz najwyższa pora na implementację całej logiki tak, aby cała aplikacja była kompletna. Oczywiście taką aplikację – kalkulator, można zaimplementować na różne sposoby, ja teraz pokażę Ci jedno z wielu podejść do napisania przykładowego kalkulatora.

Pierwsza Aplikacja Desktopowa Windows Forms w C# – Logika (2/2)

Otwórz proszę visual studio, a następnie naszą wcześniej stworzoną solucję z projektem Calculator.WindowsFormsApp. Obecnie tak wygląda nasza aplikacja:

Aplikacja Windows Forms UI - widok startowy

Żeby nasz kalkulator działał poprawnie, będziemy w naszej aplikacji musieli operować na zdarzeniach. Spis wszystkich zdarzeń, które dostępne są dla każdej kontrolki w windows forms, możesz zobaczyć w oknie Properties.

Aplikacja Windows Forms UI - Zdarzenia

W naszej aplikacji musimy wyróżnić kilka różnych zdarzeń. Moglibyśmy zrobić tak, że dla każdego przycisku zrobimy osobne zdarzenie Click i następnie w codebehind, odpowiednio to obsłużyć. Aby przejść do codebehind, czyli kodu C# formatki możesz kliknąć prawym przyciskiem myszy w formatkę i następnie View Code (F7), lub prawym przyciskiem myszy na nazwę formatki w Solution Explorer i również View Code.

Aplikacja Windows Forms UI - przejście do codebehind z formularza

Aplikacja Windows Forms UI - przejście do codebehind w solution explorer

Jednak możemy to obsłużyć dużo łatwiej. Możemy zrobić jedno wspólne zdarzenie dla wszystkich zielonych (z cyframi) przycisków i następnie w codebehind będziemy sprawdzać, za pomocą właściwości Text przycisku, który dokładnie przycisk został kliknięty. Będziemy dzięki temu wiedzieć dokładnie, co właśnie zostało kliknięte. Zaraz pokażę Ci, o co dokładnie mi chodzi. Spróbujmy dodać na tę chwilę dla 1 przycisku nowe zdarzenie. Dodamy to zdarzenie na przycisku 0. Kliknij lewym przyciskiem myszy w przycisk 0 i następnie przejdź do okna Properties i wpisz nazwę metody, którą podepniemy pod zdarzenie Click, może to być nazwa OnBtnNumberClick.

Aplikacja Windows Forms UI - dodanie pierwszego zdarzenia click

Skopiuj sobie od razu nazwę tego zdarzenia, ponieważ za chwilę nam się przyda i kliknij enter. Po kliknięciu enter w codebehind powinna zostać utworzona metoda, która zostanie wywołana, gdy to zdarzenie zostanie wyzwolone. To znaczy, jeżeli ktoś kliknie przycisk 0, to ta metoda zostanie wywołana.

private void OnBtnNumberClick(object sender, EventArgs e)
{
}

Wróć proszę do formatki i wszędzie w tych miejscach, gdzie mamy zielone przyciski, czyli tam gdzie są nasze numery, dodaj tak samo nazwę tego zdarzenia. Dzięki temu po kliknięciu dowolnego przycisku z cyfrą przejdziemy do wewnątrz metody OnBtnNumberClick i za chwilę to odpowiednio obsłużymy.

Będziemy jeszcze potrzebować kilka innych metod. Osobną metodę podepniemy pod zdarzenie Click dla wszystkich przycisków z operacjami. Może to być metoda o nazwie OnBtnOperationClick i tak samo później w codebehind będziemy weryfikować, który dokładnie przycisk z operacją został kliknięty, na podstawie tekstu tego przycisku.

Aplikacja Windows Forms UI - zdarzenie click dla operacji

private void OnBtnOperationClick(object sender, EventArgs e)
{
}

Tak samo robimy dla wszystkich operacji, czyli dla dzielenia, mnożenia, odejmowania i dodawania.

Osobna metoda będzie również dla wyświetlenia wyniku, czyli OnBtnResultClick.

Aplikacja Windows Forms UI - zdarzenie click dla wyniku

private void OnBtnResultClick(object sender, EventArgs e)
{
}

Oraz osobna metoda będzie dla przycisku Clear, czyli dla czyszczenia naszego screenu – OnBtnClearClick.

Aplikacja Windows Forms UI - zdarzenie click dla czyszczenia ekranu

private void OnBtnClearClick(object sender, EventArgs e)
{
}

Możesz teraz przebudować projekt i upewnij się, że kod się kompiluje i nie ma żadnego błędu.

Następnie przejdź do zdarzenia OnBtnNumberClick. Możemy sobie tutaj wprowadzić nową zmienną clickedValue i na podstawie przekazanego w parametrze obiektu do tego zdarzenia możemy sprawdzić, który przycisk został kliknięty w naszym interfejsie.

var clickedValue = (sender as Button).Text;

Czyli rzutujemy ten object na Button i interesuje nas jego właściwość Text – dzięki temu będziemy wiedzieć dokładnie, co zostało kliknięte. Jeżeli na przykład zostanie kliknięta cyfra 9, to zostanie wywołana ta metoda, a do metody zostanie przekazany przycisk Button 9 i my sobie wewnątrz metody OnBtnNumberClick pobierzemy Text, jaki jest na tym przycisku i będziemy wiedzieli dzięki temu, że została kliknięta 9-tka.

Następnie w naszym TextBoxie, czyli tbScreen ustawimy wartość tego przycisku, a właściwie dokleimy do tego, co już tam wcześniej zostało wpisane.

tbScreen.Text += clickedValue;

Możemy teraz od razu zweryfikować czy to działa.

Aplikacja Windows Forms UI - testy zdarzen

Jak możesz się przekonać, wszystko działa dobrze. Czyli, jeżeli klikam 9, to na ekranie pojawia się 9. Jak klikam kolejny raz, to za każdym razem na ekranie doklejają się wybrane cyfry.

Możemy jeszcze zrobić tak, żeby po uruchomieniu na ekranie wyświetlało się od razu 0. Wystarczy w konstruktorze wpisać:

tbScreen.Text = "0";

Ważne, żeby to przypisanie było po wywołaniu metody InitializeComponent(). Jeżeli teraz uruchomisz aplikacji, to od razu to 0 będzie widoczne. Mamy jednak teraz inny problem, ponieważ jeżeli klikniesz inną cyfrę, np. 9, to na ekranie wyświetla się 09, czyli 9 jest doklejana do 0. Dobrze by było, jakby ta 9, czyli pierwsza liczba podstawiła się zamiast domyślnie wstawionego 0, żeby tego 0 wtedy nie było. Tak też to w sumie często wygląda w kalkulatorach. Czyli musimy sobie w metodzie, która jest przypisana do zdarzenia OnBtnNumberClick dodać instrukcję warunkową. Jeżeli nasz tbScreen.Text ma wartość 0 (tylko 0), to wtedy to zero usuwamy i doklejamy dopiero wtedy cyfrę, która została kliknięta. Ten zapis może wyglądać w ten sposób:

if (tbScreen.Text == "0")
    tbScreen.Text = string.Empty;

Jak sobie uruchomisz aplikację, to zauważysz, że teraz wyświetla się to już prawidłowo. Na początku mamy 0, klikamy 9-tkę i 0 znika, a 9 wyświetla się prawidłowo.

Ten przycisk na tę chwilę tak może wyglądać. Za chwilę będziemy jeszcze tutaj poprawiać kilka rzeczy, dlatego na pewno tutaj jeszcze wrócimy za moment.

Spróbujmy teraz obsłużyć przyciski z operacjami. Nasza aplikacja oczekuje, że użytkownik najpierw wpisze jedną cyfrę, następnie operację, później drugą cyfrę i na koniec będzie chciał wyświetlić wynik. Także jesteśmy teraz tak jakby na drugim kroku, czyli została kliknięta jakaś operacja. Dodamy sobie w metodzie OnBtnOperationClick również nową zmienną, tym razem o nazwie operation. Podobnie jak to robiliśmy wcześniej, na podstawie tekstu sprawdzimy, który przycisk dokładnie został kliknięty. Możemy pobrać tę operację w ten sposób:

var operation = (sender as Button).Text;

Wcześniej jeszcze możemy sobie tutaj dodać nową zmienną, a właściwie, to najlepiej stworzyć pole o nazwie _firstValue i przypiszemy sobie do niego wartość z TextBoxa. Czyli dodajemy pole:

private string _firstValue;

Będzie to string, ponieważ my tutaj pobieramy wartość jeszcze z TextBoxa, także może to być string, a później go sobie przekonwertujemy. W metodzie OnBtnOperationClick będzie przypisanie wartości z ekranu do tego pola:

_firstValue = tbScreen.Text;

Czyli jeżeli ktoś kliknął operację, to cały tekst, który wcześniej był na ekranie (czyli 1 liczba) przypisujemy do pola _firstValue, dzięki czemu wiemy, jaka jest 1 liczba, która została wybrana. Następnie również w naszym TextBoxie chcemy wyświetlić, to co zostało kliknięte, czyli wartość zmiennej operation.

tbScreen.Text += $" {operation} ";

W tej zmiennej mamy przechowywaną operację, jaką będziemy wykonywać. Możemy tę operację trzymać w zmiennej string, ale myślę, że dużo lepiej będzie, jeżeli sobie wprowadzimy nowego Enum’a i tam sobie wprowadzimy wszystkie możliwe operacje. Dodaj proszę nad klasą Form1 definicję enuma Operation i uzupełnimy go wszystkimi możliwymi operacjami. Będzie to dodawanie, odejmowanie, dzielenie, mnożenie i dodamy też operację brak.

public enum Operation
{
    None,
    Addition,
    Subtraction,
    Division,
    Multiplication
}

Dodatkowo również przyda nam się nowe pole, w którym będzie przechowywana obecnie wybrana operacja:

private Operation _currentOperation = Operation.None;

Domyślna wartość to Operation.None, ponieważ na początku nie mamy wybranej żadnej operacji. Jeżeli klikniemy przycisk OnBtnOperationClick, to wtedy możemy sobie do _currentOperation przypisać wybraną operację. Najlepiej zastosować w tym przypadku switch’a:

_currentOperation = operation switch
{
    "+" => Operation.Addition,
    "-" => Operation.Subtraction,
    "/" => Operation.Division,
    "*" => Operation.Multiplication,
    _ => Operation.None,
};

Jeżeli został kliknięty np. plus, to obecną operacją będzie dodawanie, czyli Operation.Addition. Tak samo zrobiłem dla wszystkich operacji, czyli mamy odejmowanie, dzielenie, mnożenie. Na koniec wartość domyślna, czyli _, będzie to Operation.None.

Na tę chwilę w polu _firstValue mamy wartość pierwszej wybranej liczby, w _currentOperation mamy wartość wybranego działania. Potrzebujemy jeszcze przechowywać wartość drugiej liczby. Także wróćmy do zdarzenia OnBtnNumberClick i w tym miejscu dodamy instrukcję warunkową, taką, że jeżeli obecnie już została wybrana jakaś operacja, czyli wartość pola _currentOperation jest różna od Operation.None, to przypisujemy tę wartość do pola _secondValue.

if (_currentOperation != Operation.None)
    _secondValue += clickedValue;

Musimy tak samo, jak wcześniej dla pierwszej wartości, dodać właśnie takie nowe pole i dzięki temu mamy już wszystko, to co potrzebujemy, aby obliczyć wynik.

private string _secondValue;

Jeżeli teraz zostanie kliknięty nasz wynik, to będziemy wykonywać obliczenia. To znaczy, w OnBtnResultClick robimy najpierw rzutowanie tych liczb na double:

var firstNumber = double.Parse(_firstValue);
var secondNumber = double.Parse(_secondValue);

Następnie wykonujemy obliczenia:

var result = 0d;
switch (_currentOperation)
{
    case Operation.None:
        result = firstNumber;
        break;
    case Operation.Addition:
        result = firstNumber + secondNumber;
        break;
    case Operation.Subtraction:
        result = firstNumber - secondNumber;
        break;
    case Operation.Division:
        result = firstNumber / secondNumber;
        break;
    case Operation.Multiplication:
        result = firstNumber * secondNumber;
        break;
}

Czyli na podstawie _currentOperation zostanie wykonane odpowiednie działanie. Możemy sobie najpierw zadeklarować i zainicjalizować zmienną result, typu double i na podstawie operacji wykonać odpowiednie obliczenia. W przypadku, gdy żadna operacja nie została wybrana, to zmienna result będzie równa wartości pierwszej liczby. Ponadto przy dzieleniu możemy sobie jeszcze dodać instrukcję warunkową, która sprawdzi, czy wartość drugiej liczby jest różna od 0. Jeżeli będzie to 0, to wtedy wyświetlimy odpowiedni komunikat.

if (secondNumber == 0)
{
    MessageBox.Show("Nie można dzielić przez 0!");
    result = 0;
    break;
}

Jak widzisz, ta metoda OnBtnResultClick trochę nam się rozrosła, dlatego w takim przypadku najlepiej logikę obliczeń przenieść do nowej prywatnej metody. Metoda może się nazywać Calculate, będzie przyjmowała 2 parametry i będzie zwracać wynik obliczeń typu double. Będziemy do niej przekazywać wartość pierwszej liczby i wartość drugiej liczby.

private double Calculate(double firstNumber, double secondNumber)
{
    switch (_currentOperation)
    {
        case Operation.None:
            return firstNumber;
        case Operation.Addition:
            return firstNumber + secondNumber;
        case Operation.Subtraction:
            return firstNumber - secondNumber;
        case Operation.Division:
            if (secondNumber == 0)
            {
                MessageBox.Show("Nie można dzielić przez 0!");
                return 0;
            }
            return firstNumber / secondNumber;
        case Operation.Multiplication:
            return firstNumber * secondNumber;
    }

    return 0;
}

Tak będzie wyglądać wywołanie:

var result = Calculate(firstNumber, secondNumber);

Następnie wyświetlimy wynik na ekranie:

tbScreen.Text = result.ToString();

i przygotujemy aplikację, do wykonania kolejnych obliczeń. W tym celu musimy przypisać wszystkie wartości początkowe:

_secondValue = string.Empty;
_currentOperation = Operation.None;

Pierwszej wartości nie będziemy jeszcze w tym miejscu zerować, ponieważ może być tak, że użytkownik będzie chciał dodawać ciągle po kolei jakieś kolejne liczby i wtedy nie będzie chciał sobie zerować tej pierwszej, tylko wynik dodawać do kolejnej liczby. Także nie chcemy w tym miejscu zerować pierwszej liczby tylko tę drugą. W tym momencie możemy uruchomić naszą aplikacji i spróbować ją trochę przetestować manualnie i zobaczymy czy wszystko działa, tak jak powinno.

Aplikacja Windows Forms UI - testy aplikacji kalkulator

Zauważyłem kilka rzeczy, które jeszcze musimy poprawić. Po pierwsze chcemy zrobić tak, że jeżeli wynik jest wyświetlany na ekranie i wybierzemy jakąś kolejną liczbę, to chcemy, żeby ten wynik się wykasował. Aby to zrobić, będziemy potrzebowali 1 nowe pole, które będzie nam mówiło o tym, czy obecnie jest wyświetlany wynik na ekranie.

private bool _isTheResultOnTheScreen;

Domyślnie może zostać false. Jeżeli wyświetlimy wynik, to w metodzie OnBtnResultClick ustawiamy to pole na true.

_isTheResultOnTheScreen = true;

Dzięki temu wiemy, że obecnie jest wyświetlany wynik, także w zdarzeniu OnBtnNumberClick, po pierwsze musimy sprawdzić, czy ten wynik jest wyświetlany. Jeżeli tak to ustawiamy to pole na false, tak żeby to zmienić i tbScreen.Text ustawiamy na string.Empty, tak żeby wykasować ten wynik.

if (_isTheResultOnTheScreen)
{
    _isTheResultOnTheScreen = false;
    tbScreen.Text = string.Empty;
}

Sprawdźmy, czy to wystarczy. Jak możesz zauważyć, jeżeli teraz wyświetlamy wynik i następnie klikniemy jakąś cyfrę, to ona zastępuje nam wtedy wynik, także ten przypadek już działa prawidłowo.

Pozostał nam jeszcze 1 przycisk do obsłużenia, to znaczy przycisk Clear. Zastanówmy się na początek, jak ten przycisk ma działać. Przede wszystkim musi wyczyścić ekran kalkulatora, tzn. wyświetlić 0 na ekranie. Następnie, powinien usunąć obie liczby oraz ustawić obecną operację na None. Czyli to znowu będzie ten stan początkowy.

private void OnBtnClearClick(object sender, EventArgs e)
{
    tbScreen.Text = "0";
    _firstValue = string.Empty;
    _secondValue = string.Empty;
    _currentOperation = Operation.None;
}

Możesz sprawdzić, czy wszystko działa w porządku. Wygląda, że na tę chwilę jest ok.

Sprawdźmy jeszcze jakieś brzegowe sytuacje, to znaczy co się stanie, jeżeli po uruchomieniu aplikacji najpierw zamiast cyfry klikniemy przecinek. Niestety nasza aplikacja na tę chwilę wykasuje 0 i wyświetli sam przecinek. Także tutaj mamy błąd, który musimy poprawić.

Aplikacja Windows Forms UI - testy błędu z przecinkiem

Musimy tutaj wprowadzić jakieś zabezpieczenie na te przecinki. Możemy zrobić tak, że jeżeli to jest pierwsza liczba, czyli jeżeli na ekranie jest 0 i została kliknięta inna wartość niż przecinek, to wtedy to 0 usuwamy. Jednak jeżeli na ekranie było 0, ale został kliknięty przecinek, to wtedy ten przecinek zostanie normalnie doklejony po tym zerze.

if (tbScreen.Text == "0" && clickedValue != ",")
    tbScreen.Text = string.Empty;

1 instrukcja warunkowa załatwia nam ten problem. Podobnie jednak musimy zrobić poniżej. Jeżeli jakiś wynik jest wyświetlany i został kliknięty przecinek, to wtedy możemy tutaj ustawić, że tak jakby zostało kliknięte 0 i przecinek. Dzięki temu również zabezpieczymy się przed tym błędem.

if (_isTheResultOnTheScreen)
{
    _isTheResultOnTheScreen = false;
    tbScreen.Text = string.Empty;

    if (clickedValue == ",")
        clickedValue = "0,";
}

Te 2 instrukcje załatwiają nam nasz problem.

Aplikacja Windows Forms UI - testy przecinka

Oczywiście to jeszcze nie koniec problemów. Mamy jeszcze coś do poprawy. W sytuacji, gdy ktoś kliknie cyfrę, np. 6, a później operację np. + później jeszcze raz jakąś dowolną operację, no to tutaj się pojawiają różne dziwne rzeczy. Nie powinniśmy dopuścić do takiej sytuacji.

Aplikacja Windows Forms UI - testy wiele operacji

Powinniśmy dodać na to odpowiednie zabezpieczenie. Nie możemy liczyć na to, że użytkownik zawsze będzie klikał, tak jak my tego oczekujemy. Czyli jeżeli zostanie kliknięty jakiś przycisk operacji, to drugi raz on już nie może zostać kliknięty. Możemy sobie dodać nową prywatną metodę, która pomoże nam w zarządzaniu stanem przycisków. Niech to będzie metoda o nazwie SetOperationBtnState, która będzie przyjmowała wartość bool. W zależności od tego, co przekażemy, to taki ustawi stan przycisków.

private void SetOperationBtnState(bool value)
{
    btnAdd.Enabled = value;
    btnMultiplication.Enabled = value;
    btnDivision.Enabled = value;
    btnSubtraction.Enabled = value;
}

Czyli jeżeli do tej metody zostanie przekazana wartość true, to wszystkie przyciski będą odblokowane, a jeżeli false, to wtedy będą zablokowane. Tak samo zachowają się wszystkie przyciski z operacjami. Taka sama metoda, również przyda nam się dla naszego przycisku, po kliknięciu którego wyświetlany jest wynik działania. Także dodaj, proszę jeszcze metodę o nazwie SetResultBtnState. Tutaj będzie ustawiany jeszcze stan przycisku btnResult, ponieważ będzie on blokowany w trochę innych przypadkach.

private void SetResultBtnState(bool value)
{
    btnResult.Enabled = value;
}

Czyli teraz zrobimy tak, że jeżeli został kliknięty przycisk z operacją, to wtedy ustawiamy wszystkie przyciski zablokowane. Zarówno przyciski z operacjami, jak i przycisk z wyświetleniem wyniku, ponieważ nasze działanie nie zostało jeszcze skończone, dlatego nie można wyświetlić jeszcze wyniku.

SetOperationBtnState(true);
SetResultBtnState(true);

W tej samej metodzie, to znaczy OnBtnOperationClick również powinniśmy ustawić pole _isTheResultOnTheScreen na false, wtedy gdy ma wartość true.

if (_isTheResultOnTheScreen)
    _isTheResultOnTheScreen = false;

Czyli jeżeli ktoś wyświetlił wynik, a następnie kliknął operację, to również to pole musi zostać ustawione na false. Ustawiliśmy teraz nasze przyciski zablokowane, ale musimy też pamiętać, żeby je później odblokować, a możemy je odblokować w kilku przypadkach. Po pierwsze, wtedy gdy zostanie kliknięta jakaś cyfra, czyli w metodzie OnBtnNumberClick:

SetOperationBtnState(true);

Czyli chcemy odblokować te przyciski z operacjami, ale tylko wtedy gdy jeszcze żadna operacja nie została wcześniej wybrana. Czyli to wywołanie będzie w tym miejscu w instrukcji warunkowej:

if (_currentOperation != Operation.None)
    _secondValue += clickedValue;
else
    SetOperationBtnState(true);

Jeżeli chodzi o przycisk wyniku, to możemy odblokować go tutaj w każdym przypadku, dlatego możemy dodać wywołanie:

SetResultBtnState(true);

Jeżeli zostanie kliknięty dowolny przycisk z numerem, to wtedy ten wynik może być dostępny. Tak samo jeszcze, jeżeli zostanie kliknięty przycisk wynik, to chcemy odblokować wszystkie przyciski, żeby była możliwość klikania kolejnej operacji.

SetOperationBtnState(true);
SetResultBtnState(true);

W metodzie OnBtnResultClick możemy dodać jeszcze jedną instrukcję warunkową. To znaczy, jeżeli żadna operacja nie jest wybrana, to wtedy nie ma sensu żebyśmy w ogóle, tutaj wykonywali jakieś działanie.

if (_currentOperation == Operation.None)
    return;

Wydaje mi się, że teraz już przeanalizowaliśmy wszystkie możliwe przypadki, dlatego nasza aplikacja powinna już być kompletna. Na koniec oczywiście, trzeba jeszcze przeklikać trochę aplikację i dobrze przetestować.

Tym razem już wszystko działa w porządku. Na pewno taką aplikację można jeszcze trochę rozszerzyć, ale tutaj wydaje mi się, że zabezpieczyliśmy się przed najczęściej występującymi sytuacjami, gdzie mógłby jakiś błąd wystąpić. Także ta aplikacja działa już całkiem fajnie.


Kod całej aplikacji:


using System;
using System.Windows.Forms;

namespace Calculator.WindowsFormsApp
{
    public enum Operation
    {
        None,
        Addition,
        Subtraction,
        Division,
        Multiplication
    }

    public partial class Form1 : Form
    {
        private string _firstValue;
        private string _secondValue;
        private Operation _currentOperation = Operation.None;
        private bool _isTheResultOnTheScreen;

        public Form1()
        {
            InitializeComponent();
            tbScreen.Text = "0";
        }

        private void OnBtnNumberClick(object sender, EventArgs e)
        {
            var clickedValue = (sender as Button).Text;

            if (tbScreen.Text == "0" && clickedValue != ",")
                tbScreen.Text = string.Empty;

            if (_isTheResultOnTheScreen)
            {
                _isTheResultOnTheScreen = false;
                tbScreen.Text = string.Empty;

                if (clickedValue == ",")
                    clickedValue = "0,";
            }

            tbScreen.Text += clickedValue;
            SetResultBtnState(true);

            if (_currentOperation != Operation.None)
                _secondValue += clickedValue;
            else
                SetOperationBtnState(true);
        }

        private void OnBtnOperationClick(object sender, EventArgs e)
        {
            _firstValue = tbScreen.Text;

            var operation = (sender as Button).Text;

            _currentOperation = operation switch
            {
                "+" => Operation.Addition,
                "-" => Operation.Subtraction,
                "/" => Operation.Division,
                "*" => Operation.Multiplication,
                _ => Operation.None,
            };

            tbScreen.Text += $" {operation} ";

            if (_isTheResultOnTheScreen)
                _isTheResultOnTheScreen = false;

            SetOperationBtnState(false);
            SetResultBtnState(false);
        }

        private void OnBtnResultClick(object sender, EventArgs e)
        {
            if (_currentOperation == Operation.None)
                return;

            var firstNumber = double.Parse(_firstValue);
            var secondNumber = double.Parse(_secondValue);

            var result = Calculate(firstNumber, secondNumber);

            tbScreen.Text = result.ToString();
            _secondValue = string.Empty;
            _currentOperation = Operation.None;
            _isTheResultOnTheScreen = true;
            SetOperationBtnState(true);
            SetResultBtnState(true);
        }

        private double Calculate(double firstNumber, double secondNumber)
        {
            switch (_currentOperation)
            {
                case Operation.None:
                    return firstNumber;
                case Operation.Addition:
                    return firstNumber + secondNumber;
                case Operation.Subtraction:
                    return firstNumber - secondNumber;
                case Operation.Division:
                    if (secondNumber == 0)
                    {
                        MessageBox.Show("Nie można dzielić przez 0!");
                        return 0;
                    }
                    return firstNumber / secondNumber;
                case Operation.Multiplication:
                    return firstNumber * secondNumber;
            }

            return 0;
        }

        private void OnBtnClearClick(object sender, EventArgs e)
        {
            tbScreen.Text = "0";
            _firstValue = string.Empty;
            _secondValue = string.Empty;
            _currentOperation = Operation.None;
        }

        private void SetOperationBtnState(bool value)
        {
            btnAdd.Enabled = value;
            btnMultiplication.Enabled = value;
            btnDivision.Enabled = value;
            btnSubtraction.Enabled = value;
        }

        private void SetResultBtnState(bool value)
        {
            btnResult.Enabled = value;
        }
    }
}


PODSUMOWANIE


Nasza aplikacja jest gotowa. Udało nam się napisać pierwszą aplikację desktopową w windows forms w języku C#. Nie jest to jeszcze jakaś rozbudowana aplikacja, ale od czegoś trzeba zacząć. Dzięki praktyce, pisaniu różnych aplikacji, na pewno będziesz podnosił swoje umiejętności. W kolejnych materiałach przedstawię Ci również jak tworzyć aplikację w innych frameworkach np. w WPFie, ASP.NET i Xamarinie.

Jeżeli taki artykuł Ci się spodobał, to koniecznie dołącz do mojej społeczności. Zapisz się na darmowy newsletter, gdzie co tydzień dzielę się wartościowymi materiałami w szczególności dotyczącymi C# i platformy .NET (darmowy zapis – newsletter).

Poprzedni artykuł - Pierwsza Aplikacja Desktopowa Windows Forms w C# – UI (1/2).
Następny artykuł - Pierwsza Aplikacja Desktopowa WPF w C# – UI w XAML (1/2)
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
CTO & Founder - FindSolution.pl
Programista C#/.NET. Specjalizuje się w Blazor, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Komentarze (3)
Koto
KOTO, poniedziałek, 26 kwietnia 2021 11:52
Hej, fajny wstępniak. W podsumowaniu dodałbym uwagi że w "prawdziwej" implementacji: bralibyśmy delimiter cyfry z CultureInfo i oddzielilibyśmy UI od Logiki samego kalkulatora.
Dirofilarioza
DIROFILARIOZA, sobota, 13 maja 2023 01:22
Co w przypadku kiedy chciałabym żeby kalkulator dodawał czy robił coś jednocześnie z kilkoma liczbami na raz, mam z tym lekki problem i nie mogę nigdzie znaleźć podpowiedzi?
Błąd
BŁĄD , czwartek, 6 czerwca 2024 13:39
Dlaczego operation switch pokazuje mi na czerwono
Dodaj komentarz

Wyszukiwarka

© Copyright 2024 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Regulamin. Polityka prywatności. Design by Kazimierz Szpin