Analiza przypadku aplikacji międzyplatformowych: Zadanie

TaskyPortable to prosta aplikacja listy zadań do wykonania. W tym dokumencie omówiono sposób projektowania i tworzenia, postępując zgodnie ze wskazówkami dokumentu Building Cross-Platform Applications (Tworzenie aplikacji międzyplatformowych). Omówienie obejmuje następujące obszary:

Proces projektowania

Zaleca się utworzenie planu dla tego, co chcesz osiągnąć przed rozpoczęciem kodowania. Jest to szczególnie istotne w przypadku programowania międzyplatformowego, w którym tworzysz funkcje, które będą udostępniane na wiele sposobów. Począwszy od jasnego pomysłu na to, co tworzysz, oszczędza czas i nakład pracy w dalszej części cyklu programowania.

Wymagania

Pierwszym krokiem projektowania aplikacji jest zidentyfikowanie żądanych funkcji. Mogą to być cele wysokiego poziomu lub szczegółowe przypadki użycia. Zadanie ma proste wymagania funkcjonalne:

  • Wyświetlanie listy zadań
  • Dodawanie, edytowanie i usuwanie zadań
  • Ustaw stan zadania na "gotowe"

Należy rozważyć użycie funkcji specyficznych dla platformy. Czy zadanie może korzystać z geofencingu systemu iOS lub kafelków na żywo systemu Windows Telefon? Nawet jeśli nie używasz funkcji specyficznych dla platformy w pierwszej wersji, należy zaplanować z wyprzedzeniem, aby upewnić się, że warstwy danych biznesowych i danych mogą je pomieścić.

Projekt interfejsu użytkownika

Zacznij od projektu wysokiego poziomu, który można zaimplementować na platformach docelowych. Zanotuj ograniczenia interfejsu użytkownika o specyfikacji platformy. Na przykład w TabBarController systemie iOS może być wyświetlanych więcej niż pięć przycisków, natomiast odpowiednik systemu Windows Telefon może wyświetlać maksymalnie cztery. Rysuj przepływ ekranu przy użyciu wybranego narzędzia (działa papier).

Draw the screen-flow using the tool of your choice paper works

model danych

Wiedza na temat danych, które należy przechowywać, pomoże określić, który mechanizm trwałości ma być używany. Zobacz Dostęp do danych międzyplatformowych, aby uzyskać informacje na temat dostępnych mechanizmów magazynowania i pomóc w podejmowaniu między nimi decyzji. W tym projekcie będziemy używać SQLite.NET.

Zadanie musi przechowywać trzy właściwości dla każdego elementu TaskItem:

  • Name — ciąg
  • Uwagi — ciąg
  • Gotowe — wartość logiczna

Podstawowe funkcje

Należy wziąć pod uwagę interfejs API, z którego interfejs użytkownika będzie musiał korzystać, aby spełnić wymagania. Lista zadań do wykonania wymaga następujących funkcji:

  • Wyświetl listę wszystkich zadań — aby wyświetlić listę ekranów głównych wszystkich dostępnych zadań
  • Pobierz jedno zadanie — po dotknięciu wiersza zadania
  • Zapisz jedno zadanie — gdy zadanie jest edytowane
  • Usuwanie jednego zadania — po usunięciu zadania
  • Tworzenie pustego zadania — po utworzeniu nowego zadania

Aby można było ponownie użyć kodu, ten interfejs API należy zaimplementować raz w przenośnej bibliotece klas.

Implementacja

Po uzgodnieniu projektu aplikacji zastanów się, jak można ją zaimplementować jako aplikację międzyplatformową. Stanie się to architekturą aplikacji. Zgodnie ze wskazówkami zawartymi w dokumencie Building Cross-Platform Applications (Tworzenie aplikacji międzyplatformowych) kod aplikacji powinien zostać podzielony na następujące części:

  • Wspólny kod — wspólny projekt, który zawiera kod umożliwiający ponowne użycie do przechowywania danych zadania; uwidacznianie klasy modelu i interfejsu API w celu zarządzania zapisywaniem i ładowaniem danych.
  • Kod specyficzny dla platformy — projekty specyficzne dla platformy, które implementują natywny interfejs użytkownika dla każdego systemu operacyjnego, używając wspólnego kodu jako "zaplecza".

Platform-specific projects implement a native UI for each operating system, utilizing the common code as the back end

Te dwie części opisano w poniższych sekcjach.

Wspólny kod (PCL)

Tasky Portable używa strategii biblioteki klas przenośnych do udostępniania wspólnego kodu. Aby zapoznać się z opisem opcji udostępniania kodu, zobacz dokument Sharing Code Options (Opcje udostępniania kodu).

Cały wspólny kod, w tym warstwa dostępu do danych, kod bazy danych i kontrakty, jest umieszczany w projekcie biblioteki.

Kompletny projekt PCL przedstawiono poniżej. Cały kod w bibliotece przenośnej jest zgodny z każdą platformą docelową. Po wdrożeniu każda aplikacja natywna będzie odwoływać się do tej biblioteki.

When deployed, each native app will reference that library

Na poniższym diagramie klas przedstawiono klasy pogrupowane według warstwy. Klasa SQLiteConnection jest standardowy kod z pakietu Sqlite-NET. Pozostałe klasy to niestandardowy kod zadania. Klasy TaskItemManager i TaskItem reprezentują interfejs API, który jest udostępniany aplikacjom specyficznym dla platformy.

The TaskItemManager and TaskItem classes represent the API that is exposed to the platform-specific applications

Oddzielenie warstw przy użyciu przestrzeni nazw ułatwia zarządzanie odwołaniami między poszczególnymi warstwami. Projekty specyficzne dla platformy powinny zawierać tylko instrukcję using dla warstwy biznesowej. Warstwa dostępu do danych i warstwa danych powinny być hermetyzowane przez interfejs API uwidoczniony TaskItemManager w warstwie biznesowej.

Informacje

Przenośne biblioteki klas muszą być używane na wielu platformach, z których każda ma różne poziomy obsługi funkcji platformy i platformy. W związku z tym istnieją ograniczenia dotyczące pakietów i bibliotek platformy, których można używać. Na przykład platforma Xamarin.iOS nie obsługuje słowa kluczowego c# dynamic , więc przenośna biblioteka klas nie może używać żadnego pakietu zależnego od kodu dynamicznego, mimo że taki kod będzie działać w systemie Android. Visual Studio dla komputerów Mac uniemożliwi dodawanie niezgodnych pakietów i odwołań, ale należy pamiętać o ograniczeniach, aby uniknąć niespodzianek później.

Uwaga: Zobaczysz, że biblioteki platform odwołań do projektów, których nie użyto. Te odwołania są uwzględniane jako część szablonów projektów platformy Xamarin. Po skompilowaniu aplikacji proces łączenia spowoduje usunięcie nieużywanego kodu, więc mimo System.Xml odwołania nie zostanie on uwzględniony w końcowej aplikacji, ponieważ nie używamy żadnych funkcji Xml.

Warstwa danych (DL)

Warstwa danych zawiera kod, który wykonuje fizyczny magazyn danych — zarówno do bazy danych, plików prostych, jak i innych mechanizmów. Warstwa danych Tasky składa się z dwóch części: biblioteki SQLite-NET i kodu niestandardowego dodanego do połączenia.

Zadanie opiera się na pakiecie NuGet Sqlite-net (opublikowanym przez Franka Kruegera) w celu osadzenia kodu SQLite-NET, który udostępnia interfejs bazy danych mapowania obiektów (ORM). Klasa TaskItemDatabase dziedziczy SQLiteConnection i dodaje wymagane metody Create, Read, Update, Delete (CRUD), aby odczytywać i zapisywać dane w sqlite. Jest to prosta implementacja standardowych metod CRUD, które mogą być ponownie używane w innych projektach.

Element TaskItemDatabase jest pojedynczym elementem zapewniającym, że cały dostęp występuje względem tego samego wystąpienia. Blokada służy do zapobiegania równoczesnym dostępowi z wielu wątków.

SqLite w systemie Windows Telefon

Chociaż systemy iOS i Android są dostarczane z sqLite w ramach systemu operacyjnego, system Windows Telefon nie zawiera zgodnego aparatu bazy danych. Aby udostępnić kod na wszystkich trzech platformach, wymagana jest natywna dla systemu Windows wersja SQLite. Aby uzyskać więcej informacji na temat konfigurowania projektu Telefon systemu Windows dla usługi Sqlite, zobacz Praca z lokalną bazą danych.

Używanie interfejsu do uogólniania dostępu do danych

Warstwa danych przyjmuje zależność, BL.Contracts.IBusinessIdentity aby mogła implementować abstrakcyjne metody dostępu do danych, które wymagają klucza podstawowego. Każda klasa warstwy biznesowej, która implementuje interfejs, może być utrwalana w warstwie danych.

Interfejs określa tylko właściwość liczby całkowitej, która będzie działać jako klucz podstawowy:

public interface IBusinessEntity {
    int ID { get; set; }
}

Klasa bazowa implementuje interfejs i dodaje atrybuty SQLite-NET, aby oznaczyć je jako automatycznie zwiększający klucz podstawowy. Każda klasa w warstwie biznesowej, która implementuje tę klasę bazową, może być utrwalana w warstwie danych:

public abstract class BusinessEntityBase : IBusinessEntity {
    public BusinessEntityBase () {}
    [PrimaryKey, AutoIncrement]
    public int ID { get; set; }
}

Przykładem metod ogólnych w warstwie danych używającej interfejsu jest następująca GetItem<T> metoda:

public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return Table<T>().FirstOrDefault(x => x.ID == id);
    }
}

Blokowanie w celu uniemożliwienia dostępu współbieżnego

Blokada jest implementowana w klasie, TaskItemDatabase aby uniemożliwić współbieżny dostęp do bazy danych. Ma to na celu zapewnienie, że współbieżny dostęp z różnych wątków jest serializowany (w przeciwnym razie składnik interfejsu użytkownika może próbować odczytać bazę danych w tym samym czasie, gdy wątek w tle jest aktualizowany). Przykład implementacji blokady przedstawiono tutaj:

static object locker = new object ();
public IEnumerable<T> GetItems<T> () where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return (from i in Table<T> () select i).ToList ();
    }
}
public T GetItem<T> (int id) where T : BL.Contracts.IBusinessEntity, new ()
{
    lock (locker) {
        return Table<T>().FirstOrDefault(x => x.ID == id);
    }
}

Większość kodu warstwy danych może być ponownie używana w innych projektach. Jedynym kodem specyficznym dla aplikacji w warstwie jest CreateTable<TaskItem> wywołanie w konstruktorze TaskItemDatabase .

Warstwa dostępu do danych (DAL)

Klasa TaskItemRepository hermetyzuje mechanizm przechowywania danych za pomocą silnie typizowanego interfejsu API, który umożliwia TaskItem tworzenie, usuwanie, pobieranie i aktualizowanie obiektów.

Korzystanie z kompilacji warunkowej

Klasa używa kompilacji warunkowej do ustawiania lokalizacji pliku — jest to przykład implementacji rozbieżności platformy. Właściwość zwracająca ścieżkę kompiluje się do innego kodu na każdej platformie. W tym miejscu przedstawiono dyrektywy kompilatora kodu i kompilatora specyficzne dla platformy:

public static string DatabaseFilePath {
    get {
        var sqliteFilename = "TaskDB.db3";
#if SILVERLIGHT
        // Windows Phone expects a local path, not absolute
        var path = sqliteFilename;
#else
#if __ANDROID__
        // Just use whatever directory SpecialFolder.Personal returns
        string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); ;
#else
        // we need to put in /Library/ on iOS5.1+ to meet Apple's iCloud terms
        // (they don't want non-user-generated data in Documents)
        string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
        string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder
#endif
        var path = Path.Combine (libraryPath, sqliteFilename);
                #endif
                return path;
    }
}

W zależności od platformy dane wyjściowe będą mieć wartość "<app path>/Library/TaskDB.db3" dla systemu iOS, "<ścieżka> aplikacji/Documents/TaskDB.db3" dla systemu Android lub tylko "TaskDB.db3" dla systemu Windows Telefon.

Warstwa biznesowa (BL)

Warstwa biznesowa implementuje klasy Model i fasadę do zarządzania nimi. W obszarze Tasky model jest klasą TaskItem i TaskItemManager implementuje wzorzec fasady w celu zapewnienia interfejsu API do zarządzania TaskItems.

Fasada

TaskItemManager Opakowuje DAL.TaskItemRepository metodę Get, Save and Delete, do których będą odwoływać się warstwy aplikacji i interfejsu użytkownika.

W razie potrzeby reguły biznesowe i logika zostaną umieszczone w tym miejscu — na przykład wszystkie reguły weryfikacji, które muszą zostać spełnione przed zapisaniem obiektu.

Interfejs API dla kodu specyficznego dla platformy

Po napisaniu wspólnego kodu interfejs użytkownika musi zostać skompilowany w celu zbierania i wyświetlania danych udostępnianych przez nie. Klasa TaskItemManager implementuje wzorzec fasady, aby zapewnić prosty interfejs API dla kodu aplikacji w celu uzyskania dostępu.

Kod napisany w każdym projekcie specyficznym dla platformy będzie zwykle ściśle powiązany z natywnym zestawem SDK tego urządzenia i uzyskuje dostęp tylko do wspólnego kodu przy użyciu interfejsu API zdefiniowanego TaskItemManagerprzez . Obejmuje to metody i klasy biznesowe, które uwidacznia, takie jak TaskItem.

Obrazy nie są udostępniane między platformami, ale dodawane niezależnie do każdego projektu. Jest to ważne, ponieważ każda platforma obsługuje obrazy inaczej, używając różnych nazw plików, katalogów i rozwiązań.

W pozostałych sekcjach omówiono szczegóły implementacji specyficzne dla platformy interfejsu użytkownika zadania.

Aplikacja systemu iOS

Istnieje tylko kilka klas wymaganych do zaimplementowania aplikacji Tasky systemu iOS przy użyciu wspólnego projektu PCL do przechowywania i pobierania danych. Pełny projekt platformy Xamarin.iOS dla systemu iOS jest pokazany poniżej:

iOS project is shown here

Klasy są wyświetlane na tym diagramie pogrupowane w warstwy.

The classes are shown in this diagram, grouped into layers

Informacje

Aplikacja systemu iOS odwołuje się do bibliotek zestawu SDK specyficznych dla platformy — np. Xamarin.iOS i MonoTouch.Dialog-1.

Musi również odwoływać się do TaskyPortableLibrary projektu PCL. Lista odwołań jest wyświetlana tutaj:

The references list is shown here

Warstwa aplikacji i warstwa interfejsu użytkownika są implementowane w tym projekcie przy użyciu tych odwołań.

Warstwa aplikacji (AL)

Warstwa aplikacji zawiera klasy specyficzne dla platformy wymagane do powiązania obiektów uwidocznionych przez PCL z interfejsem użytkownika. Aplikacja specyficzna dla systemu iOS ma dwie klasy ułatwiające wyświetlanie zadań:

  • EditingSource — ta klasa służy do wiązania list zadań z interfejsem użytkownika. Ponieważ MonoTouch.Dialog została użyta na liście Zadań, musimy zaimplementować ten pomocnik, aby włączyć funkcję szybkiego przesunięcia do usunięcia w elemecie UITableView . Szybkie przesunięcie do usunięcia jest powszechne w systemie iOS, ale nie w systemie Android lub Windows Telefon, więc projekt specyficzny dla systemu iOS jest jedynym, który go implementuje.
  • TaskDialog — ta klasa służy do powiązania pojedynczego zadania z interfejsem użytkownika. Używa interfejsu MonoTouch.Dialog API Emocje ion do zawijania TaskItem obiektu z klasą zawierającą poprawne atrybuty, aby umożliwić poprawne formatowanie ekranu wejściowego.

Klasa TaskDialog używa MonoTouch.Dialog atrybutów do utworzenia ekranu na podstawie właściwości klasy. Klasa wygląda następująco:

public class TaskDialog {
    public TaskDialog (TaskItem task)
    {
        Name = task.Name;
        Notes = task.Notes;
        Done = task.Done;
    }
    [Entry("task name")]
    public string Name { get; set; }
    [Entry("other task info")]
    public string Notes { get; set; }
    [Entry("Done")]
    public bool Done { get; set; }
    [Section ("")]
    [OnTap ("SaveTask")]    // method in HomeScreen
    [Alignment (UITextAlignment.Center)]
    public string Save;
    [Section ("")]
    [OnTap ("DeleteTask")]  // method in HomeScreen
    [Alignment (UITextAlignment.Center)]
    public string Delete;
}

Zwróć uwagę, że OnTap atrybuty wymagają nazwy metody — te metody muszą istnieć w klasie, w której MonoTouch.Dialog.BindingContext jest tworzona (w tym przypadku HomeScreen klasa omówiona w następnej sekcji).

Warstwa interfejsu użytkownika

Warstwa interfejsu użytkownika składa się z następujących klas:

  1. AppDelegate — zawiera wywołania interfejsu API wyglądu w celu stylu czcionek i kolorów używanych w aplikacji. Zadanie jest prostą aplikacją, więc nie ma innych zadań inicjowania uruchomionych w programie FinishedLaunching .
  2. Ekrany — podklasy UIViewController definiujące każdy ekran i jego zachowanie. Ekrany łączą interfejs użytkownika z klasami warstw aplikacji i wspólnym interfejsem API ( TaskItemManager ). W tym przykładzie ekrany są tworzone w kodzie, ale mogły zostać zaprojektowane przy użyciu konstruktora interfejsu Xcode lub projektanta scenorysu.
  3. Obrazy — elementy wizualne są ważną częścią każdej aplikacji. Zadanie ma ekran powitalny i obrazy ikon, które dla systemu iOS muszą być dostarczane w regularnej rozdzielczości i Siatkówki.

Ekran główny

Ekran główny to MonoTouch.Dialog ekran przedstawiający listę zadań z bazy danych SQLite. Dziedziczy i DialogViewController implementuje kod, aby ustawić Root obiekt w taki sposób, aby zawierał kolekcję TaskItem obiektów do wyświetlenia.

It inherits from DialogViewController and implements code to set the Root to contain a collection of TaskItem objects for display

Dwie główne metody związane z wyświetlaniem listy zadań i interakcją z nią są następujące:

  1. PopulateTable — używa metody warstwy TaskManager.GetTasks biznesowej do pobrania kolekcji TaskItem obiektów do wyświetlenia.
  2. Selected — po dotknięciu wiersza zadanie zostanie wyświetlone na nowym ekranie.

Ekran szczegółów zadania

Szczegóły zadania to ekran wejściowy, który umożliwia edytowanie lub usuwanie zadań.

Funkcja Tasky używa MonoTouch.Dialoginterfejsu API Emocje ion do wyświetlania ekranu, więc nie UIViewController ma implementacji. HomeScreen Zamiast tego klasa tworzy wystąpienie i wyświetla klasę używającą DialogViewControllerTaskDialog z warstwy aplikacji.

Ten zrzut ekranu przedstawia pusty ekran przedstawiający ustawienie atrybutu Entry tekstu znaku wodnego w polach Nazwa i Uwagi :

This screenshot shows an empty screen that demonstrates the Entry attribute setting the watermark text in the Name and Notes fields

Funkcjonalność ekranu Szczegóły zadania (na przykład zapisywanie lub usuwanie zadania) musi być zaimplementowana w HomeScreen klasie, ponieważ jest to miejsce, w którym MonoTouch.Dialog.BindingContext jest tworzony. HomeScreen Następujące metody obsługują ekran Szczegóły zadania:

  1. ShowTaskDetails — tworzy obiekt MonoTouch.Dialog.BindingContext , aby renderować ekran. Tworzy ekran wejściowy przy użyciu odbicia w celu pobrania nazw właściwości i typów z TaskDialog klasy. Dodatkowe informacje, takie jak tekst znaku wodnego dla pól wejściowych, są implementowane z atrybutami we właściwościach.
  2. SaveTask — ta metoda jest przywołynięta w TaskDialog klasie za pośrednictwem atrybutu OnTap . Jest on wywoływany po naciśnięciu klawisza Zapisz i używa elementu , MonoTouch.Dialog.BindingContext aby pobrać dane wprowadzone przez użytkownika przed zapisaniem zmian przy użyciu polecenia TaskItemManager .
  3. DeleteTask — ta metoda jest przywoływała się w TaskDialog klasie za pośrednictwem atrybutu OnTap . Używa TaskItemManager ich do usuwania danych przy użyciu klucza podstawowego (właściwości ID).

Aplikacja dla systemu Android

Kompletny projekt platformy Xamarin.Android został na zdjęciu poniżej:

Android project is pictured here

Diagram klas z klasami pogrupowanych według warstwy:

The class diagram, with classes grouped by layer

Informacje

Projekt aplikacji systemu Android musi odwoływać się do zestawu Xamarin.Android specyficznego dla platformy, aby uzyskać dostęp do klas z zestawu Android SDK.

Musi również odwoływać się do projektu PCL (np. TaskyPortableLibrary) w celu uzyskania dostępu do wspólnych danych i kodu warstwy biznesowej.

TaskyPortableLibrary to access the common data and business layer code

Warstwa aplikacji (AL)

Podobnie jak w przypadku wersji systemu iOS, którą omówiliśmy wcześniej, warstwa aplikacji w wersji systemu Android zawiera klasy specyficzne dla platformy wymagane do "powiązania" obiektów uwidocznionych przez core z interfejsem użytkownika.

TaskListAdapter — aby wyświetlić listę<T> obiektów, musimy zaimplementować adapter do wyświetlania obiektów niestandardowych w obiekcie ListView. Karta steruje układem używanym dla każdego elementu na liście — w tym przypadku kod używa wbudowanego układu systemu SimpleListItemCheckedAndroid.

Interfejs użytkownika

Warstwa interfejsu użytkownika aplikacji systemu Android jest kombinacją kodu i znaczników XML.

  • Resources/Layout — układy ekranu i projekt komórki wiersza zaimplementowany jako pliki AXML. Kod AXML można napisać ręcznie lub wizualnie za pomocą interfejsu użytkownika platformy Xamarin Projektant dla systemu Android.
  • Resources/Drawable — obrazy (ikony) i przycisk niestandardowy.
  • Ekrany — podklasy działań definiujące każdy ekran i jego zachowanie. Łączy interfejs użytkownika z klasami warstw aplikacji i wspólnym interfejsem API (TaskItemManager).

Ekran główny

Ekran główny składa się z podklasy HomeScreen Activity i HomeScreen.axml pliku, który definiuje układ (położenie przycisku i listy zadań). Ekran wygląda następująco:

The screen looks like this

Kod ekranu głównego definiuje programy obsługi służące do klikania przycisku i klikania elementów na liście, a także wypełniania listy w metodzie OnResume (tak aby odzwierciedlały zmiany wprowadzone na ekranie szczegółów zadania). Dane są ładowane przy użyciu warstwy TaskItemManager biznesowej i TaskListAdapter warstwy aplikacji.

Ekran szczegółów zadania

Ekran szczegółów zadania składa się również z Activity podklasy i pliku układu AXML. Układ określa lokalizację kontrolek wejściowych, a klasa C# definiuje zachowanie ładowania i zapisywania TaskItem obiektów.

The class defines the behavior to load and save TaskItem objects

Wszystkie odwołania do biblioteki PCL są za pośrednictwem TaskItemManager klasy .

Aplikacja Telefon systemu Windows

Kompletny projekt Telefon systemu Windows:

Windows Phone App The complete Windows Phone project

Na poniższym diagramie przedstawiono klasy pogrupowane w warstwy:

This diagram presents the classes grouped into layers

Informacje

Projekt specyficzny dla platformy musi odwoływać się do wymaganych bibliotek specyficznych dla platformy (takich jak Microsoft.Phone i System.Windows), aby utworzyć prawidłową aplikację systemu Windows Telefon.

Musi również odwoływać się do projektu PCL (np. TaskyPortableLibrary) w celu korzystania z TaskItem klasy i bazy danych.

TaskyPortableLibrary to utilize the TaskItem class and database

Warstwa aplikacji (AL)

Ponownie, podobnie jak w przypadku wersji systemów iOS i Android, warstwa aplikacji składa się z elementów innych niż wizualne, które ułatwiają powiązanie danych z interfejsem użytkownika.

Modele widoków

Modele ViewModel zawierają dane z PCL ( TaskItemManager) i przedstawiają je w sposób, który może być używany przez powiązanie danych Silverlight/XAML. Jest to przykład zachowania specyficznego dla platformy (zgodnie z opisem w dokumencie Aplikacje międzyplatformowe).

Interfejs użytkownika

Język XAML ma unikatową funkcję powiązania danych, którą można zadeklarować w znacznikach i zmniejszyć ilość kodu wymaganego do wyświetlania obiektów:

  1. Pages — pliki XAML i ich kodbehind definiują interfejs użytkownika i odwołują się do modelu ViewModels oraz projektu PCL do wyświetlania i zbierania danych.
  2. Obrazy — ekran powitalny, obrazy tła i ikon są kluczowym elementem interfejsu użytkownika.

Strona główna

Klasa MainPage używa klasy TaskListViewModel do wyświetlania danych przy użyciu funkcji powiązania danych XAML. DataContext Strona jest ustawiona na model widoku, który jest wypełniany asynchronicznie. Składnia {Binding} w języku XAML określa sposób wyświetlania danych.

TaskDetailsPage

Każde zadanie jest wyświetlane przez powiązanie elementu TaskViewModel z XAML zdefiniowanym w pliku TaskDetailsPage.xaml. Dane zadania są pobierane za pośrednictwem TaskItemManager elementu w warstwie biznesowej.

Wyniki

Wynikowe aplikacje wyglądają następująco na każdej platformie:

iOS

Aplikacja używa standardowego projektu interfejsu użytkownika systemu iOS, takiego jak przycisk "Dodaj" umieszczony na pasku nawigacyjnym i używając wbudowanej ikony plusa (+). Używa również domyślnego UINavigationController zachowania przycisku "Wstecz" i obsługuje polecenie "swipe-to-delete" w tabeli.

It also uses the default UINavigationController back button behavior and supports swipe-to-delete in the tableIt also uses the default UINavigationController back button behavior and supports swipe-to-delete in the table

Android

Aplikacja systemu Android używa wbudowanych kontrolek, w tym wbudowanego układu wierszy, które wymagają wyświetlenia "znacznika". Zachowanie zaplecza sprzętu/systemu jest obsługiwane oprócz przycisku wstecz na ekranie.

The hardware/system back behavior is supported in addition to an on-screen back buttonThe hardware/system back behavior is supported in addition to an on-screen back button

Windows Phone

Aplikacja Windows Telefon używa standardowego układu, wypełniając pasek aplikacji w dolnej części ekranu zamiast paska nawigacyjnego u góry.

The Windows Phone app uses the standard layout, populating the app bar at the bottom of the screen instead of a nav bar at the topThe Windows Phone app uses the standard layout, populating the app bar at the bottom of the screen instead of a nav bar at the top

Podsumowanie

Ten dokument zawiera szczegółowe wyjaśnienie sposobu stosowania zasad projektowania aplikacji warstwowych do prostej aplikacji w celu ułatwienia ponownego użycia kodu na trzech platformach mobilnych: iOS, Android i Windows Telefon.

Opisał on proces używany do projektowania warstw aplikacji i omawiał, jakie funkcje i kod zostały zaimplementowane w każdej warstwie.

Kod można pobrać z usługi github.