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

W C#, a konkretnie w Xamarin Forms możesz również tworzyć aplikacje mobilne. Co więcej, jeżeli już znasz WPF'a i wzorzec MVVM, to napisanie takiej aplikacji nie będzie stanowiło dla ciebie problemu. Podobnie jak w WPF'ie, tutaj sam widok możesz stworzyć w XAML'u. Możesz zbindować właściwości i zdarzenia z kodem napisanym w C# w ViewModel'ach. Aplikacje mobilne możemy również uruchamiać i testować na Windows'ie. Wystarczy użyć do tego symulatora i uruchomić przez Visual Studio. Jeżeli instalowałeś Visual Studio zgodnie z moimi wcześniejszymi instrukcjami, to powinieneś mieć już taki symulator zainstalowany na swoim komputerze. W tym artykule pokażę Ci, w jaki sposób napisać prosty kalkulator, aby działał na urządzeniach mobilnych. Stworzymy najpierw nowy projekt mobilny w Xamarin'ie oraz zaimplementujemy interfejs użytkownika. W kolejnym materiale natomiast przejdziemy do implementacji logiki aplikacji.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# – UI w XAML (1/2)


Tworzenie nowego projektu Xamarin Forms


Podobnie jak wcześniej, do pisania aplikacji mobilnej potrzebujemy środowiska Visual Studio. Otwórz, proszę teraz naszą wcześniej utworzoną solucję i pokaże Ci jak stworzyć naszą aplikację.

Na początek dodajmy do naszej solucji nowy projekt. Kliknij w solucji, a następnie Add ... New Project. W wyszukiwarce wpisz mobile app i wybierz Xamarin.Forms.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – Nowy projekt

Kliknij Next. Wybierz odpowiednią nazwę, zgodnie z naszą konwencję będzie to: Calculator.XamarinFormsApp.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – nazwa projektu

Kliknij Create. Następnie wybieramy szablon. Mamy do wyboru Flyout, Tabbed oraz Blank. Możemy sobie wybrać Tabbed. Poniżej jeszcze możemy wybrać, czy chcemy rozwijać aplikację pod Android'a, czy pod iOS'a. Możemy też w jednym projekcie rozwijać naszą aplikację zarówno pod Android'a oraz pod iOS'a.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – wybor szablonu

Klikamy Create i po chwili do naszej wcześniej utworzonej solucji zostaną dodane nowe projekty.


Nowe projekty w naszej solucji


Zauważ, że są to aż 3 nowe projekty. Projekt wspólny: Calculator.XamarinFormsApp, dedykowany projekt dla Androida: Calculator.XamarinFormsApp.Android oraz dedykowany dla iOS'a: Calculator.XamarinFormsApp.iOS.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – utworzone projekty

My akurat w tym przypadku będziemy tworzyli cały kod w projekcie wspólnym. Jeżeli jednak będziesz pisał aplikacje bardziej zaawansowane, to prawdopodobnie będziesz musiał pisać również kod dedykowany pod Android'a, a także iOS'a.

Spróbujmy sobie na początek uruchomić projekt startowy. Będziemy uruchamiać projekt w Androidzie, czyli w solucji kliknij prawym przyciskiem myszy na projekt Androida i wybierz Set as Startup Project.


Uruchomienie aplikacji mobilnej w symulatorze


Na górze w Visual Studio możesz sobie wybrać 1 z Twoich zainstalowanych symulatorów. Ja mam tylko jeden, także otworzę sobie tę aplikację na tym symulatorze.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – wybor symulatora

Standardowo w celu uruchomienia naszej aplikacji w symulatorze użyj skrótu: Ctrl+F5. Po chwili powinien się u Ciebie uruchomić odpowiedni symulator.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – pierwsze uruchomienie symulatora

Co warto podkreślić, to pierwsze uruchomienie może być troszkę dłuższe, ale przy kolejnych już zawsze powinno być szybciej. Dodatkowo, jeżeli rozwijasz jakąś aplikację, to najlepiej sobie zostawić ten symulator uruchomiony i później tylko sobie przebudujesz i uruchomisz aplikację w visual studio, a sama aplikacja w symulatorze będzie się aktualizowała automatycznie. Także nie będziesz musiał tracić czasu, aż cały symulator się uruchomi.


Xamarin MVVM


Przejdźmy do widoku. Będziemy chcieli stworzyć widok główny w miejscu, w którym obecnie uruchamia się aplikacja, czyli zamiast strony About, którą teraz widzisz, będzie wyświetlała się nasza strona główna, która za chwilę stworzymy.

Wróćmy do naszej stworzonej solucji w Visual Studio. Mamy tutaj stworzony podział podobny jak w WPF'ie.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – solucja mvvm

Standardowo w folderze Views mamy widoki, w folderze ViewModels znajdują się ViewModele. W tym szablonie ViewModele są już gotowe, także na pewno zaoszczędzi nam to trochę czasu. Będzie tylko wprowadzać kilka modyfikacji. W tym artykule będziemy cały nasz widok tworzyć w folderze Views i pliku AboutPage. Nazwę również zaraz dostosujemy. Jeżeli sobie otworzysz ten plik XAML, to zauważ, że nie ma tutaj podglądu, tak jak było to wcześniej w aplikacji WPF. Także tutaj jest troszkę utrudnienie, ale na pewno sobie z tym poradzimy.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – about page

Będziemy bazować na tym widoku, ale na razie możemy sobie cały kod XAML z tego pliku usunąć. Zostawmy tylko ustawiony BindingContext.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Calculator.XamarinFormsApp.Views.AboutPage"
             xmlns:vm="clr-namespace:Calculator.XamarinFormsApp.ViewModels"
             Title="{Binding Title}">
    
    <ContentPage.BindingContext>
        <vm:AboutViewModel />
    </ContentPage.BindingContext>    
    
</ContentPage>


Dostosowanie nazwy


Następnie uporządkujmy jeszcze nazwy, to znaczy zamiast AboutPage będzie MainPage. Musimy to pozmieniać w naszej solucji oraz we wszystkich plikach XAML i code behind. Również AboutViewModel zmienimy na MainViewModel. Zweryfikuj czy nie masz żadnych błędów i jeżeli jest ok, to możemy przejść już do faktycznej implementacji.

W MainViewModel ustawimy sobie wyświetlany tytuł na "Kalkulator".

namespace Calculator.XamarinFormsApp.ViewModels
{
    public class MainViewModel : BaseViewModel
    {
        public MainViewModel()
        {
            Title = "Kalkulator";
            OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));
        }

        public ICommand OpenWebCommand { get; }
    }
}

Tak samo musisz pamiętać, o zaktualizowaniu kodu XAML dla MainPage:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Calculator.XamarinFormsApp.Views.MainPage"
             xmlns:vm="clr-namespace:Calculator.XamarinFormsApp.ViewModels"
             Title="{Binding Title}">
    
    <ContentPage.BindingContext>
        <vm:MainViewModel />
    </ContentPage.BindingContext>
       
</ContentPage>

W WPF'ie robiliśmy to w CodeBehind, ale tak samo można ustawić context widoku po stronie XAML'a.


Implementacja widoku głównego kalkulatora


Także na początek stwórzmy sobie odpowiednią siatkę w widoku głównym. Dla kalkulatora potrzebujemy 5 wierszy i 5 kolumn. Możemy sobie też od razu ustawić margines, żeby tę naszą siatkę troszkę oddalić od krawędzi.

<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

</Grid>

Teraz potrzebujemy dodać kontrolkę, na której będą wyświetlane wszystkie te liczby w naszym kalkulatorze. Ta kontrolka w xamarin forms nazywa się Entry. Chcemy, żeby zajmowała 5 kolumn i była w 1 wierszu, także domyślnie GridRow jest ustawione na 0 i GridColumn również na 0. W związku z tym, nie musimy tutaj tego zmieniać.

<Entry Grid.ColumnSpan="5" />

Potrzebujemy również dodać 17 przycisków i każdemu musimy ustawić odpowiedni wiersz i kolumnę.

<Entry Grid.ColumnSpan="5" />

<Button Grid.Row="1" Text="7" />

<Button Grid.Row="1" Grid.Column="1" Text="8" />

<Button Grid.Row="1" Text="9" Grid.Column="2" />

<Button Grid.Row="2" Text="4" />

<Button Grid.Row="2" Grid.Column="1" Text="5" />

<Button Grid.Row="2" Text="6" Grid.Column="2" />

<Button Grid.Row="3" Text="1" />

<Button Grid.Row="3" Grid.Column="1" Text="2" />

<Button Grid.Row="3" Grid.Column="2" Text="3" />

<Button Grid.Row="4" Grid.ColumnSpan="2" Text="0" />

<Button Grid.Row="4" Grid.Column="2"  Text="," />

<Button Grid.Row="1" Grid.Column="3" Text="/" />

<Button Grid.Row="2" Grid.Column="3" Text="-" />

<Button Grid.Row="3" Grid.Column="3" Text="*" />

<Button Grid.Row="4" Grid.Column="3" Text="C" />

<Button Grid.Row="1" Grid.Column="4" Grid.RowSpan="2" Text="+" />

<Button Grid.Row="3" Grid.Column="4" Grid.RowSpan="2" Text="=" />

Możemy zobaczyć, jak to wygląda w symulatorze. Zaktualizujmy aplikację w symulatorze, kliknij Ctrl+F5 i przejdź do symulatora. Zobaczmy, jak teraz wygląda nasza aplikacja.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – widok uruchomienie aplikacji

Wygląda to już całkiem dobrze. Mamy tutaj nasze przyciski, mamy kontrolkę do wyświetlania obliczeń, wszystko tak jak oczekiwaliśmy.


Ustawienie styli


Musimy teraz tylko jeszcze poprawić troszkę style, żeby to się wszystko ładnie wyświetlało. Także nasze style możemy tak samo, jak w WPF'ie wprowadzać w kilku miejscach. Możemy to robić w osobnych plikach i stosować je dla całej aplikacji, ale w takiej małej aplikacji jak kalkulator, to możemy jak najbardziej stworzyć bezpośrednio w naszym widoku MainPage. Także musimy tutaj dodać do zasobów ContentPage ResourceDictionary i w nim zdefiniować odpowiednie style.

<ContentPage.Resources>
    <ResourceDictionary>            

    </ResourceDictionary>
</ContentPage.Resources>

Spróbujmy najpierw ustawić style dla kontrolki Entry. Ustawiamy tutaj, podobnie jak to robiliśmy w WPF'ie. Na początek FontSize na 46. Margines na 5 z każdej strony. Wyrównanie tekstu do prawej strony. Wyrównanie w pionie do środka, czyli Center. Ustawimy też tę kontrolkę na tylko do odczytu, czyli IsReadOnly na True.

<Style TargetType="Entry">
    <Setter Property="FontSize" Value="46" />
    <Setter Property="Margin" Value="5" />
    <Setter Property="HorizontalTextAlignment" Value="End" />
    <Setter Property="VerticalTextAlignment" Value="Center" />
    <Setter Property="IsReadOnly" Value="True" />
</Style>

Możemy zweryfikować, jak to wygląda w naszej aplikacji. Wcześniej jednak spróbujmy dodać jakąś wartość testową, tak żeby coś się w tej kontrolce już wyświetlało.

<Entry Grid.ColumnSpan="5" Text="392011231" />

Teraz Ctrl+F5 i zobaczmy na symulator.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – style entry

I jak widzisz, całkiem fajnie to już wygląda. Możemy zatem usunąć testowe dane, tak żeby o tym później nie zapomnieć.

<Entry Grid.ColumnSpan="5" />

Pozostaje nam jeszcze poprawić style dla naszych przycisków. Dodajmy do ResourceDictionary informacje o nowych stylach. Najpierw wprowadzimy sobie taki nasz bazowy styl dla wszystkich przycisków. Niech to będzie styl o kluczu BaseButton, TargetType ustawiamy na Button. Ustawimy sobie FontSize na 46 oraz marginesy na 5.

<Style x:Key="BaseButton" TargetType="Button">
    <Setter Property="FontSize" Value="46" />
    <Setter Property="Margin" Value="5" />
</Style>

Będziemy potrzebowali ustawić więcej stylów, ponieważ mamy sporo przycisków i chcemy, żeby bazowały właśnie na tym stylu wcześniej stworzonym, ale każdy z nich będzie miał inny kolor tła. Ustawmy teraz, aby wszystkie nasze przyciski domyślnie korzystały z tego bazowego przycisku. Także ustawiamy TargetType na Button, BasedOn BaseButton.

<Style TargetType="Button" BasedOn="{StaticResource BaseButton}">                
</Style>

W tym momencie wszystkie style przycisków, które za chwile będzie tworzyć, będą korzystać już z tego naszego bazowego stylu. Jeżeli teraz uruchomimy naszą aplikację, to zauważ, że wygląda to już trochę lepiej.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – widok style bazowe przyciski

Mamy już tutaj marginesy i czcionkę również jest powiększona. Tak jak Ci wcześniej wspomniałem, będziemy chcieli ustawić odpowiednie kolory dla różnych przycisków. W związku z tym będziemy potrzebować kilka nowych stylów.

<Style x:Key="BtnNumber" TargetType="Button" BasedOn="{StaticResource BaseButton}">
    <Setter Property="Background" Value="#29AF29" />
</Style>

<Style x:Key="BtnOperation" TargetType="Button" BasedOn="{StaticResource BaseButton}">
    <Setter Property="Background" Value="#FF787878" />
</Style>

<Style x:Key="BtnClear" TargetType="Button" BasedOn="{StaticResource BaseButton}">
    <Setter Property="Background" Value="#FFE64848" />
</Style>

<Style x:Key="BtnResult" TargetType="Button" BasedOn="{StaticResource BaseButton}">
    <Setter Property="Background" Value="#FF0D37E3" />
</Style>

Dla cyfr będzie to kolor zielony. Dla operacji szary, dla przycisku wyczyść kolor czerwony, a dla przycisku wyświetlającego wynik kolor niebieski.

Te zmiany jeszcze na tę chwilę nie będą widoczne, ponieważ musimy jeszcze jawnie ustawić, z których styli, który przycisk ma korzystać. Czyli dla cyfr będzie to styl BtnNumber, dla operacji BtnOperation, dla Clear BtnClear i dla Result BtnResult.

<Button Grid.Row="1" Text="7" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="1" Grid.Column="1" Text="8" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="1" Text="9" Grid.Column="2" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="2" Text="4" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="2" Grid.Column="1" Text="5" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="2" Text="6" Grid.Column="2" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="3" Text="1" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="3" Grid.Column="1" Text="2" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="3" Grid.Column="2" Text="3" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="4" Grid.ColumnSpan="2" Text="0" Style="{StaticResource BtnNumber}" />

<Button Grid.Row="4" Grid.Column="2"  Text="," Style="{StaticResource BtnNumber}" />

<Button Grid.Row="1" Grid.Column="3" Text="/" Style="{StaticResource BtnOperation}" />

<Button Grid.Row="2" Grid.Column="3" Text="-" Style="{StaticResource BtnOperation}" />

<Button Grid.Row="3" Grid.Column="3" Text="*" Style="{StaticResource BtnOperation}" />

<Button Grid.Row="4" Grid.Column="3" Text="C" Style="{StaticResource BtnClear}" />

<Button Grid.Row="1" Grid.Column="4" Grid.RowSpan="2" Text="+" Style="{StaticResource BtnOperation}" />

<Button Grid.Row="3" Grid.Column="4" Grid.RowSpan="2" Text="=" Style="{StaticResource BtnResult}" />


Widok główny naszej aplikacji


Uruchommy naszą aplikację i zobaczmy czy wszystko działa wg założeń.

PIERWSZA APLIKACJA Mobilna XAMARIN w C# XAML – widok kompletny

Kolory mamy takie jak chcieliśmy, czyli zielone dla liczb, dla operacji szare, dla wyniku mamy niebieski i dla czyszczenia mamy czerwony. Także tak może wyglądać na ten moment nasza aplikacja.


Cały kod MainPage.xaml


<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Calculator.XamarinFormsApp.Views.MainPage"
             xmlns:vm="clr-namespace:Calculator.XamarinFormsApp.ViewModels"
             Title="{Binding Title}">

    <ContentPage.BindingContext>
        <vm:MainViewModel />
    </ContentPage.BindingContext>

    <ContentPage.Resources>
        <ResourceDictionary>

            <Style TargetType="Entry">
                <Setter Property="FontSize" Value="46" />
                <Setter Property="Margin" Value="5" />
                <Setter Property="HorizontalTextAlignment" Value="End" />
                <Setter Property="VerticalTextAlignment" Value="Center" />
                <Setter Property="IsReadOnly" Value="True" />
            </Style>

            <Style x:Key="BaseButton" TargetType="Button">
                <Setter Property="FontSize" Value="46" />
                <Setter Property="Margin" Value="5" />
            </Style>

            <Style TargetType="Button" BasedOn="{StaticResource BaseButton}">
            </Style>

            <Style x:Key="BtnNumber" TargetType="Button" BasedOn="{StaticResource BaseButton}">
                <Setter Property="Background" Value="#29AF29" />
            </Style>

            <Style x:Key="BtnOperation" TargetType="Button" BasedOn="{StaticResource BaseButton}">
                <Setter Property="Background" Value="#FF787878" />
            </Style>

            <Style x:Key="BtnClear" TargetType="Button" BasedOn="{StaticResource BaseButton}">
                <Setter Property="Background" Value="#FFE64848" />
            </Style>

            <Style x:Key="BtnResult" TargetType="Button" BasedOn="{StaticResource BaseButton}">
                <Setter Property="Background" Value="#FF0D37E3" />
            </Style>

        </ResourceDictionary>
    </ContentPage.Resources>

    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Entry Grid.ColumnSpan="5" />

        <Button Grid.Row="1" Text="7" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="1" Grid.Column="1" Text="8" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="1" Text="9" Grid.Column="2" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="2" Text="4" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="2" Grid.Column="1" Text="5" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="2" Text="6" Grid.Column="2" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="3" Text="1" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="3" Grid.Column="1" Text="2" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="3" Grid.Column="2" Text="3" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="4" Grid.ColumnSpan="2" Text="0" Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="4" Grid.Column="2"  Text="," Style="{StaticResource BtnNumber}" />

        <Button Grid.Row="1" Grid.Column="3" Text="/" Style="{StaticResource BtnOperation}" />

        <Button Grid.Row="2" Grid.Column="3" Text="-" Style="{StaticResource BtnOperation}" />

        <Button Grid.Row="3" Grid.Column="3" Text="*" Style="{StaticResource BtnOperation}" />

        <Button Grid.Row="4" Grid.Column="3" Text="C" Style="{StaticResource BtnClear}" />

        <Button Grid.Row="1" Grid.Column="4" Grid.RowSpan="2" Text="+" Style="{StaticResource BtnOperation}" />

        <Button Grid.Row="3" Grid.Column="4" Grid.RowSpan="2" Text="=" Style="{StaticResource BtnResult}" />

    </Grid>

</ContentPage>


PODSUMOWANIE


Widok naszej aplikacji mobilnej jest już gotowy. Jak widzisz, napisaliśmy ten widok, bardzo podobnie do tego, jak to wcześniej robiliśmy w WPF'ie. Co więcej, logika będzie również bardzo podobna i zaimplementujemy ją w kolejnym artykule.

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 Webowa ASP.NET Core w C# – Logika MVC (2/2).
Następny artykuł - Pierwsza Aplikacja Mobilna Xamarin w C# – Logika MVVM (2/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
Dodaj komentarz

Wyszukiwarka

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