Xamarin.Forms – Prism – binding + ICommand

Wstęp

W dzisiejszym poście chciałbym skupić się na opisie Xamarin.Forms oraz biblioteki Prism. Przedstawię przykład użycia bindingu oraz zastosowanie interfejsu ICommand.

Xamarin.Forms

Xamarin.Forms, warstwa abstrakcji do tworzenia aplikacji pod Android, iOS, Windows oraz macOS. Kod piszemy głównie w dzielonym projekcie a projekty poszczególnych platform tylko go wywołują. Interfejs graficzny piszemy w XAML (jest też możliwość pisania w c#), osoby które miały styczność z WPF, bardzo szybko się odnajdą w Xamarin.Forms, reszta na pewno nie będzie miała większych problemów żeby go opanować. Język XAML sam w sobie niczego nie narzuca ale wspiera wzorzec MVVM i właśnie on jest zalecany podczas pisania aplikacji.

Prism

Pisanie aplikacji w czystym XAML, z użyciem MVVM, jest troszkę skomplikowane na dłuższą metę, dlatego powstały różne frameworki wspomagające MVVM. Jednym z nich jest Prism, framework z początku wykorzystywany do pisania aplikacji w WPF, także projekt ten jest już długo rozwijany. Korzystając z Prism możemy pisać testowalny kod, dodatkowo możemy podzielić naszą aplikację na mniejsze moduły, co pozwala na łatwiejsze zarządzanie kodem.

Dodanie Prism do projektu

Pierwszy krok to utworzenie projektu. Następnie musimy dodać odpowiedni pakiet nuget. Prism korzysta z dependency injection dlatego musimy zdecydować z jakiego kontenera skorzystamy, ja dla przykładu wykorzystam Unity więc potrzebuję nuget Prism.Forms.Unity. O dependency injection na pewno powstanie jakiś post niedługo. Po instalacji pakietu musimy wprowadzić trochę zmian.

App.xaml – Główny znacznik to musi być PrismApplication, żeby to osiągnąć musimy najpierw zaimportować Prism.Unity.Forms

App.xaml.csApp musi dziedziczyć po PrismApplication, implementować klasę abstrakcyjną, oraz wyświetlić jakiś widok, najlepiej korzystając z NavigationService.

Kolejnym krokiem jest utworzenie pierwszego view modelu, dla porządku dodajmy katalog ViewModels i utwórzmy w nim klasę HomeViewModel. Prism opiera się na konwencji nazewniczej, jeśli mamy HomeView i utworzymy HomeViewModel to one się razem sparują. Rozwiązanie to jest elastyczne więc jeśli chcemy podpiąć inny view model to też jesteśmy w stanie to zrobić. Mając utworzony widok oraz view model musimy go zarejestrować w aplikacji, wchodzimy do pliku App.xaml.cs i rozszerzamy ciało metody RegisterTypes:

Przejdźmy do HomeViewModel.cs. Komunikacja pomiędzy widokiem a view modelem odbywa się korzystając z powiązań – bindingu. Wiążemy jakąś właściwość z view modelu z właściwością XAML, na przykład Label.Text. Powiązania korzystają z interfejsu INotifyPropertyChanged który składa się z eventu PropertyChanged. Prism udostępnia nam klasę która implementuje ten interfejs BindableBase i z niej skorzystamy. Tworzymy właściwość Count przechowującą ilość kliknięć przycisku, ważne jest to aby w setterze wywołać event PropertyChanged aby poinformować widok że wartość się zmieniła, do tego służy metoda RaisePropertyChanged(). Potrzebujemy jeszcze funkcję która będzie wywołana po naciśnięciu przycisku, która będzie inkrementować nasz licznik. XAML korzysta z interfejsu ICommand do przekazywania metod, więc musimy utworzyć własciwość typu ICommand i przypisać do niej metodę. Z pomocą przychodzi nam Prism który implementację ICommand zawarł w klasie DelegateCommand.

Pozostaje nam jeszcze powiązać powyższe właściwości z widokiem. Przejdźmy do HomeView.xaml. Tworzymy Label żeby wyświetlić ilość tapnięć oraz przycisk żeby zwiększać licznik. Pierwsze powiązanie będzie z Labelem, do właściwości Text dowiążemy właściwość Count view modelu. Korzystamy tutaj ze słówka Binding. Podobnie sytuacja wygląda z przyciskiem, który posiada właściwość Command.

Podsumowując mamy dwa elementy niezależne od siebie. Widok którego nie interesuje jaki view model jest do niego podpięty, tylko wie że view model ma dostarczyć właściwość Count oraz IncrementCountCommand. Mamy też view model który nic nie wie o tym do jakiego widoku jest podpięty, dzięki takiemu podejściu możemy pisać testy jednostkowe do view modelu.

Kod dostępny na github –
https://github.com/brzooz/Blog/tree/master/Xamarin.Forms/PrismExample

Xamarin.Forms – Content View

Witam. Dzisiejszy post będzie poświęcony Xamarin.Forms. Przedstawię o co chodzi z ContentView na podstawie przykładu z wyświetlaniem imienia.

Content View

Xamarin.Forms umożliwia tworzenie ContentView, własnych kontrolek z których później można korzystać. Dodatkowo te kontrolki można rozszerzać o właściwości, tzw. Bindable Properties. Dla przykładu stwórzmy ContentView który będzie wyświetlać Hello imię. Zawartość kontrolki czyli Content może zawierać tylko jeden „widok”, element który dziedziczy po klasie View. W naszym przykładzie chcemy wyświetlić tylko Hello imię więc potrzebujemy Label który dziedziczy po View. Jeśli chcielibyśmy mieć dwa Labele, to sprawa się już trochę komplikuje i trzeba to opakować np. w StackLayout. Utwórzmy ContentView z nazwą HelloName.

Powyżej zawartość pliku XAML która jest nam potrzebna do wyświetlenia tekstu. Korzystamy tutaj z bindingu który oferuje XAML oraz StringFormat żeby sformatować żądany tekst.

Przejdźmy do kodu. Żeby zrobić elastyczną kontrolkę do której możemy przekazać np. imię potrzebujemy utworzyć BindableProperty. Jest to statyczne pole w klasie które korzysta z właściwości którą również musimy utworzyć.

Parametry funkcji Create które nas interesują:

  • Nazwa właściwości – korzystamy tutaj z nameof
  • Typ właściwości – Name jest typu string.
  • Typ obiektu który posiada właściwość – W tym wypadku będzie to typ naszego ContentView

Na końcu jeszcze trzeba ustawić, w konstruktorze, BindingContext naszej kontrolki na nią samą. Wtedy w XAML będziemy mogli korzystać z naszych właściwości.

Po utworzeniu kontrolki możemy z niej korzystać na naszych widokach. Ja akurat utworzyłem ContentView w katalogu Controls dlatego namespace różni się od namespace’u mojego widoku. Jedyne co to trzeba zaimportować ten namespace i można korzystać z nowej kontrolki.

Działający kod z przykładu można znaleźć pod tym linkiem