Xamarin.Forms Ausführliche Erläuterungen zum Schnellstart

Im Xamarin.Forms-Schnellstart wurde die Notes-Anwendung erstellt. In diesem Artikel lassen wir die dafür erforderlichen Vorgänge noch einmal Revue passieren, sodass Sie die Funktionsweise von Xamarin.Forms-Shellanwendungen besser verstehen können.

Einführung in Visual Studio

In Visual Studio wird Code in Projektmappen und Projekten organisiert. Eine Projektmappe ist ein Container, der mindestens ein Projekt enthält. Ein Projekt kann z.B. eine Anwendung, eine unterstützende Bibliothek oder eine Testanwendung sein. Die Notes-Anwendung besteht wie im folgenden Screenshot gezeigt aus einer Projektmappe mit drei Projekten:

Visual Studio Solution Explorer

Diese Projekte sind folgende:

  • Notes: Dieses Projekt ist das .NET Standard-Klassenbibliotheksprojekt, das den gesamten freigegebenen Code und die gesamte freigegebene Benutzeroberfläche enthält.
  • Notes.Android: Dieses Projekt enthält Android-spezifischen Code und ist der Einstiegspunkt für die Android-Anwendung.
  • Notes.iOS: Dieses Projekt enthält iOS-spezifischen Code und ist der Einstiegspunkt für die iOS-Anwendung.

Struktur einer Xamarin.Forms-Anwendung

Der folgende Screenshot zeigt den Inhalt des .NET Standard-Bibliotheksprojekts „Notes“ in Visual Studio:

Phoneword .NET Standard Project Contents

Das Projekt verfügt über den Knoten Abhängigkeiten, der die Knoten NuGet und SDK enthält:

  • NuGet: die dem Projekt hinzugefügten NuGet-Pakete für Xamarin.Forms, Xamarin.Essentials, Newtonsoft.Json und sqlite-net-pcl.
  • SDK: Das NETStandard.Library-Metapaket, das alle NuGet-Pakete referenziert, die .NET Standard definieren.

Einführung in Visual Studio für Mac

Die Codeorganisation in Visual Studio für Mac baut auf Visual Studio auf und gliedert sich in Projektmappen und Projekte. Eine Projektmappe ist ein Container, der mindestens ein Projekt enthält. Ein Projekt kann z.B. eine Anwendung, eine unterstützende Bibliothek oder eine Testanwendung sein. Die Notes-Anwendung besteht wie im folgenden Screenshot gezeigt aus einer Projektmappe mit drei Projekten:

Visual Studio for Mac Solution Pane

Diese Projekte sind folgende:

  • Notes: Dieses Projekt ist das .NET Standard-Klassenbibliotheksprojekt, das den gesamten freigegebenen Code und die gesamte freigegebene Benutzeroberfläche enthält.
  • Notes.Android: Dieses Projekt enthält Android-spezifischen Code und ist der Einstiegspunkt für Android-Anwendungen.
  • Notes.iOS: Dieses Projekt enthält iOS-spezifischen Code und ist der Einstiegspunkt für iOS-Anwendungen.

Struktur einer Xamarin.Forms-Anwendung

Der folgende Screenshot zeigt den Inhalt des .NET Standard-Bibliotheksprojekts „Notes“ in Visual Studio für Mac:

Phoneword .NET Standard Library Project Contents

Das Projekt verfügt über den Knoten Abhängigkeiten, der die Knoten NuGet und SDK enthält:

  • NuGet: die dem Projekt hinzugefügten NuGet-Pakete für Xamarin.Forms, Xamarin.Essentials, Newtonsoft.Json und sqlite-net-pcl.
  • SDK: Das NETStandard.Library-Metapaket, das alle NuGet-Pakete referenziert, die .NET Standard definieren.

Das Projekt besteht auch aus mehreren Dateien:

  • Data\NoteDatabase.cs: Diese Klasse enthält Code, mit dem die Datenbank erstellt wird und Daten aus ihr gelesen bzw. in sie geschrieben und aus ihr gelöscht werden.
  • Models\Note.cs: Diese Klasse definiert ein Note-Modell, dessen Instanzen Daten über jede Notiz in der Anwendung speichert.
  • Views\AboutPage.xaml: das XAML-Markup für die AboutPage-Klasse, die die Benutzeroberfläche für die Infoseite definiert.
  • Views\AboutPage.xaml.cs: das CodeBehind für die AboutPage-Klasse mit der Geschäftslogik, die ausgeführt wird, wenn Benutzer mit der Seite interagieren.
  • Views\NotesPage.xaml: das XAML-Markup für die NotesPage-Klasse, das die Benutzeroberfläche für die Seite definiert, die beim Start der Anwendung angezeigt wird.
  • Views\NotesPage.xaml.cs: das CodeBehind für die NotesPage-Klasse mit der Geschäftslogik, die ausgeführt wird, wenn Benutzer mit der Seite interagieren.
  • Views\NoteEntryPage.xaml: das XAML-Markup für die NoteEntryPage-Klasse, das die Benutzeroberfläche für die Seite definiert, die angezeigt wird, wenn Benutzer Notizen eingeben.
  • Views\NoteEntryPage.xaml.cs: das CodeBehind für die NoteEntryPage-Klasse mit der Geschäftslogik, die ausgeführt wird, wenn Benutzer mit der Seite interagieren.
  • App.xaml: Das XAML-Markup für die App-Klasse, die ein Ressourcenverzeichnis für die Anwendung definiert
  • App.xaml.cs: das CodeBehind für die App-Klasse, das für die Instanziierung der Shellanwendung und die Verarbeitung von Ereignissen im Anwendungslebenszyklus zuständig ist.
  • AppShell.xaml: das XAML-Markup für die AppShell-Klasse, das die visuelle Hierarchie der Anwendung definiert.
  • AppShell.xaml.cs: das CodeBehind für die AppShell-Klasse, das eine Route für die NoteEntryPage erstellt, sodass programmgesteuert dorthin navigiert werden kann.
  • AssemblyInfo.cs: Diese Datei enthält ein Anwendungsattribut für das Projekt, das auf Assemblyebene angewendet wird.

Weitere Informationen zum Aufbau einer Xamarin.iOS-Anwendung finden Sie unter Hello, iOS: Deep Dive (Hallo iOS: Ausführliche Informationen). Weitere Informationen zum Aufbau einer Xamarin.Android-Anwendung finden Sie unter Hello, Android: Deep Dive (Hallo Android: Ausführliche Informationen).

Architektur und Anwendungsgrundlagen

Eine Xamarin.Forms-Anwendung ist genauso aufgebaut wie eine traditionelle plattformübergreifende Anwendung. Freigegebener Code wird in der Regel in einer .NET Standard-Bibliothek platziert und von plattformspezifischen Anwendungen genutzt. Die folgende Abbildung bietet für die Notes-Anwendung einen Überblick über diese Beziehung:

Notes Architecture

Xamarin.Forms-Anwendungen enthalten eine einzelne Klasse namens App, um Startcode besser wiederverwenden zu können. Diese Klasse instanziiert die Anwendung auf jeder Seite, wie im folgenden Codebeispiel gezeigt:

using Xamarin.Forms;

namespace Notes
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new AppShell();
        }
        // ...
    }
}

Dieser Code legt MainPage-Eigenschaft der App-Klasse auf das Objekt AppShell fest. Die AppShell-Klasse definiert die visuelle Hierarchie der Anwendung. Die Shell übernimmt diese visuelle Hierarchie und erzeugt die Benutzeroberfläche dafür. Weitere Informationen zum Definieren der visuellen Hierarchie einer Anwendung finden Sie unter Visuelle Anwendungshierarchie.

Außerdem enthält die Datei AssemblyInfo.cs ein einzelnes Anwendungsattribut, das auf Assemblyebene angewendet wird:

using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]

Das Attribut XamlCompilation aktiviert den XAML-Compiler, sodass XAML direkt in der Zwischensprache kompiliert wird. Weitere Informationen finden Sie unter XAML Compilation (XAML-Kompilierung).

Starten der Anwendung auf jeder Plattform

Die Art und Weise, wie die Anwendung auf den verschiedenen Plattformen gestartet wird, ist spezifisch für die jeweilige Plattform.

iOS

Zum Aufrufen der Xamarin.Forms-Startseite in iOS definiert das Notes.iOS-Projekt die Klasse AppDelegate, die von der Klasse FormsApplicationDelegate erbt:

namespace Notes.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());
            return base.FinishedLaunching(app, options);
        }
    }
}

Mit der FinishedLaunching-Außerkraftsetzung wird das Xamarin.Forms-Framework durch Aufrufen der Init-Methode initialisiert. Dadurch wird die iOS-spezifische Implementierung von Xamarin.Forms in die Anwendung geladen, bevor der Stammansichtscontroller durch den Aufruf der LoadApplication-Methode festgelegt wird.

Android

Zum Aufrufen der Xamarin.Forms-Startseite in Android enthält das Notes.Android-Projekt Code, der eine Aktivität (Activity) mit dem Attribut MainLauncher erstellt, wobei die Aktivität von der Klasse FormsAppCompatActivity erbt:

namespace Notes.Droid
{
    [Activity(Label = "Notes",
              Icon = "@mipmap/icon",
              Theme = "@style/MainTheme",
              MainLauncher = true,
              ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
    }
}

Mit der OnCreate-Außerkraftsetzung wird das Xamarin.Forms-Framework durch Aufrufen der Init-Methode initialisiert. Dadurch wird die Android-spezifische Implementierung von Xamarin.Forms in die Anwendung geladen, bevor die Xamarin.Forms-Anwendung geladen wird.

Visuelle Anwendungshierarchie

Xamarin.Forms-Shellanwendungen definieren die visuelle Hierarchie der Anwendung in einer Klasse, die die Klasse Shell in Unterklassen unterteilt. In der Notes-Anwendung ist dies die Appshell-Klasse:

<Shell xmlns="http://xamarin.com/schemas/2014/forms"
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
       xmlns:views="clr-namespace:Notes.Views"
       x:Class="Notes.AppShell">
    <TabBar>
        <ShellContent Title="Notes"
                      Icon="icon_feed.png"
                      ContentTemplate="{DataTemplate views:NotesPage}" />
        <ShellContent Title="About"
                      Icon="icon_about.png"
                      ContentTemplate="{DataTemplate views:AboutPage}" />
    </TabBar>
</Shell>

Dieser XAML-Code besteht aus zwei Hauptobjekten:

  • TabBar. TabBar stellt die untere Registerkartenleiste dar und sollte verwendet werden, wenn das Navigationsmuster für die Anwendung Registerkarten unten verwendet. Das TabBar-Objekt ist dem Shell-Objekt untergeordnet.
  • ShellContent stellt die ContentPage-Objekte für jede Registerkarte in der TabBar dar. Jedes ShellContent-Objekt ist ein untergeordnetes Objekt des TabBar-Objekts.

Diese Objekte repräsentieren keine Benutzeroberfläche, sondern die Anordnung der visuellen Hierarchie einer Anwendung. Die Shell wird diese Objekte übernehmen und die Benutzeroberfläche für die Navigation der Inhalte erstellen. Daher definiert die AppShell-Klasse zwei Seiten, in denen über die unteren Registerkarten navigiert werden kann. Die Seiten werden bedarfsbasiert und als Reaktion auf die Navigation erstellt.

Weitere Informationen zu Shellanwendungen finden Sie unter Xamarin.Forms-Shell.

Benutzeroberfläche

Beim Erstellen der Benutzeroberfläche einer Xamarin.Forms-Anwendung kommen verschiedene Steuerelementgruppen zum Einsatz:

  1. Seiten: Xamarin.Forms-Seiten stellen Bildschirme plattformübergreifender mobiler Anwendungen dar. Die Notes-Anwendung verwendet die ContentPage-Klasse, um einzelne Bildschirme anzuzeigen. Weitere Informationen zu Seiten finden Sie unter Xamarin.Forms-Seiten.
  2. Ansichten: Xamarin.Forms-Ansichten sind die auf der Benutzeroberfläche angezeigten Steuerelemente, z. B. Bezeichnungen, Schaltflächen und Texteingabefelder. Die fertige Notes-Anwendung verwendet die Ansichten CollectionView, Editor und Button. Weitere Informationen zu Ansichten finden Sie unter Xamarin.Forms-Ansichten.
  3. Layouts: Xamarin.Forms-Layouts sind Container, die zum Erstellen von Ansichten in Form von logischen Strukturen verwendet werden. Die Notes-Anwendung verwendet die Klasse StackLayout, um Ansichten in einem vertikalen Stapel anzuordnen, und die Klasse Grid, um Schaltflächen horizontal anzuordnen. Weitere Informationen zu Layouts finden Sie unter Xamarin.Forms-Layouts.

Zur Laufzeit wird jedes Steuerelement seinem nativen Äquivalent zugeordnet. Dieses wird dann gerendert.

Layout

Die Notes-Anwendung verwendet die Klasse StackLayout, um die plattformübergreifende Anwendungsentwicklung zu vereinfachen, indem Anzeigen unabhängig von der Bildschirmgröße automatisch angeordnet werden. Alle untergeordneten Elemente werden nacheinander horizontal oder vertikal in der Reihenfolge positioniert, in der sie hinzugefügt wurden. Wie viel Speicherplatz das StackLayout verwendet, hängt davon ab, wie die Eigenschaften HorizontalOptions und VerticalOptions festgelegt sind. Das StackLayout versucht jedoch standardmäßig, den gesamten Bildschirm zu verwenden.

Der folgende XAML-Code zeigt ein Beispiel für die Verwendung einer StackLayout-Klasse zur Gestaltung von NoteEntryPage:

<?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="Notes.Views.NoteEntryPage"
             Title="Note Entry">
    ...    
    <StackLayout Margin="{StaticResource PageMargin}">
        <Editor Placeholder="Enter your note"
                Text="{Binding Text}"
                HeightRequest="100" />
        <Grid>
            ...
        </Grid>
    </StackLayout>    
</ContentPage>

Standardmäßig geht die Klasse StackLayout von einer vertikalen Ausrichtung aus. Wenn aber eine horizontale Ausrichtung gewünscht wird, kann die Eigenschaft StackLayout.Orientation auf den Enumerationsmember StackOrientation.Horizontal festgelegt werden.

Hinweis

Die Größe der Ansichten kann mithilfe der Eigenschaften HeightRequest und WidthRequest festgelegt werden.

Weitere Informationen zur StackLayout-Klasse finden Sie unter Xamarin.Forms StackLayout.

Reagieren auf eine Benutzerinteraktion

Ein in XAML definiertes Objekt kann ein Ereignis auslösen, das in der CodeBehind-Datei behandelt wird. Das folgende Codebeispiel zeigt die Methode OnSaveButtonClicked im CodeBehind für die Klasse NoteEntryPage, die als Reaktion auf das Ereignis Clicked ausgeführt wird, das über die Schaltfläche Speichern ausgelöst wird.

async void OnSaveButtonClicked(object sender, EventArgs e)
{
    var note = (Note)BindingContext;
    note.Date = DateTime.UtcNow;
    if (!string.IsNullOrWhiteSpace(note.Text))
    {
        await App.Database.SaveNoteAsync(note);
    }
    await Shell.Current.GoToAsync("..");
}

Die Methode OnSaveButtonClicked speichert die Notiz in der Datenbank und wechselt zurück zur vorherigen Seite. Weitere Informationen zur Navigation finden Sie unter Navigation.

Hinweis

Die CodeBehind-Datei für eine XAML-Klasse kann auf ein Objekt zugreifen, das mit dem Namen, der ihm mit dem x:Name-Attribut zugewiesen wurde, in XAML definiert wurde. So wie bei C#-Variablen muss der diesem Attribut zugewiesene Wert mit einem Buchstaben oder Unterstrich beginnen und darf keine eingebetteten Leerzeichen enthalten.

Die Verknüpfung der Schaltfläche „Speichern“ mit der OnSaveButtonClicked-Methode erfolgt im XAML-Markup für die Klasse NoteEntryPage:

<Button Text="Save"
        Clicked="OnSaveButtonClicked" />

Listen

CollectionView ist für die Anzeige einer Sammlung von Elementen auf dem Bildschirm zuständig. Standardmäßig werden Listenelemente vertikal angezeigt, und jedes Element wird in einer einzelnen Zeile angezeigt.

Das folgende Codebeispiel zeigt die Klasse CollectionView über die NotesPage:

<CollectionView x:Name="collectionView"
                Margin="{StaticResource PageMargin}"
                SelectionMode="Single"
                SelectionChanged="OnSelectionChanged">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                           ItemSpacing="10" />
    </CollectionView.ItemsLayout>
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <StackLayout>
                <Label Text="{Binding Text}"
                       FontSize="Medium" />
                <Label Text="{Binding Date}"
                       TextColor="{StaticResource TertiaryColor}"
                       FontSize="Small" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Das Layout jeder Zeile in der Klasse CollectionView wird im Element CollectionView.ItemTemplate definiert und verwendet Datenbindung, um sämtliche Notizen anzuzeigen, die von der Anwendung abgerufen werden. Die Eigenschaft CollectionView.ItemsSource ist in NotesPage.xaml.cs auf die Datenquelle festgelegt:

protected override async void OnAppearing()
{
    base.OnAppearing();

    collectionView.ItemsSource = await App.Database.GetNotesAsync();
}

Dieser Code füllt den CollectionView mit allen in der Datenbank gespeicherten Notizen auf und wird ausgeführt, wenn die Seite angezeigt wird.

Bei Auswahl eines Elements in CollectionView wird das Ereignis SelectionChanged ausgelöst. Ein Ereignishandler mit dem Namen OnSelectionChanged wird ausgeführt, wenn das Ereignis ausgelöst wird:

async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        // ...
    }
}

Das Ereignis SelectionChanged kann auf das Objekt zugreifen, das dem Element über die Eigenschaft e.CurrentSelection zugeordnet wurde.

Weitere Informationen zur Klasse CollectionView finden Sie unter Xamarin.Forms: CollectionView.

Die Navigation erfolgt in einer Shell-Anwendung durch Angabe eines URI, zu dem navigiert werden soll. Navigations-URIs bestehen aus drei Komponenten:

  • Eine Route, die den Pfad zu Inhalt definiert, der als Teil der visuellen Shell-Hierarchie vorhanden ist.
  • Eine Seite. Seiten, die in der visuellen Shell-Hierarchie nicht vorhanden sind, können von überall innerhalb einer Shell-Anwendung per Push an den Navigationsstapel übertragen werden. Beispielsweise wird die NoteEntryPage nicht in der visuellen Shellhierarchie definiert, sondern kann bei Bedarf per Push an den Navigationsstapel übertragen werden.
  • Mindestens ein Abfrageparameter. Abfrageparameter sind Parameter, die während der Navigation an die Zielseite übergeben werden können.

Ein Navigations-URI muss nicht alle drei Komponenten enthalten, aber wenn dies der Fall ist, wird diese Struktur verwendet: //route/page?queryParameters.

Hinweis

Routen können über die Eigenschaft Route für Elemente in der visuellen Shellhierarchie definiert werden. Wenn die Eigenschaft Route jedoch nicht festgelegt ist (z. B. in der Notes-Anwendung), wird zur Laufzeit eine Route generiert.

Weitere Informationen zur Shellnavigation finden Sie unter Navigation in der Xamarin.Forms-Shell.

Registrieren von Routen

Zum Navigieren zu einer Seite, die in der visuellen Hierarchie der Shell nicht vorhanden ist, muss die Seite zuerst beim Shellroutingsystem registriert werden. Dafür wird die Routing.RegisterRoute-Methode verwendet. In der Notes-Anwendung erfolgt dies im AppShell-Konstruktor:

public partial class AppShell : Shell
{
    public AppShell()
    {
        // ...
        Routing.RegisterRoute(nameof(NoteEntryPage), typeof(NoteEntryPage));
    }
}

In diesem Beispiel wird eine Route mit namens NoteEntryPage für den NoteEntryPage-Typ registriert. Diese Seite kann dann von überall in der Anwendung per URI-basierter Navigation aufgerufen werden.

Durchführen der Navigation

Die Navigation wird von der GoToAsync-Methode ausgeführt. Diese akzeptiert ein Argument, das die Route darstellt, zu der navigiert werden soll:

await Shell.Current.GoToAsync("NoteEntryPage");

In diesem Beispiel wird zu NoteEntryPage navigiert.

Wichtig

Ein Navigationsstapel wird erstellt, wenn zu einer Seite navigiert wird, die sich nicht in der visuellen Shellhierarchie befindet.

Beim Navigieren zu einer Seite können Daten als Abfrageparameter an die Seite übergeben werden:

async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        // Navigate to the NoteEntryPage, passing the ID as a query parameter.
        Note note = (Note)e.CurrentSelection.FirstOrDefault();
        await Shell.Current.GoToAsync($"{nameof(NoteEntryPage)}?{nameof(NoteEntryPage.ItemId)}={note.ID.ToString()}");
    }
}

Dieses Beispiel ruft das aktuell ausgewählte Element in CollectionView ab und navigiert zu NoteEntryPage. Dabei wird der Wert der ID-Eigenschaft des Note-Objekts als Abfrageparameter an die NoteEntryPage.ItemId-Eigenschaft übergeben.

Um die übergebenen Daten zu empfangen, wird die NoteEntryPage-Klasse mit dem QueryPropertyAttribute versehen.

[QueryProperty(nameof(ItemId), nameof(ItemId))]
public partial class NoteEntryPage : ContentPage
{
    public string ItemId
    {
        set
        {
            LoadNote(value);
        }
    }
    // ...
}

Das erste Argument für das QueryPropertyAttribute gibt an, dass die Eigenschaft ItemId die Daten empfangen soll, das zweite Argument gibt die Abfrageparameter-ID an. Das QueryPropertyAttribute im oben stehenden Beispiel legt somit fest, dass die ItemId-Eigenschaft die im ItemId-Abfrageparameter übergebenen Daten vom URI im GoToAsync-Methodenaufruf erhält. Die ItemId-Eigenschaft ruft dann die LoadNote-Methode auf, um die Notiz vom Gerät abzurufen.

Die Rückwärtsnavigation wird ausgeführt, indem ".." als Argument für die GoToAsync-Methode angegeben wird:

await Shell.Current.GoToAsync("..");

Weitere Informationen zur Rückwärtsnavigation finden Sie unter Rückwärtsnavigation.

Datenbindung

Datenbindung wird verwendet, um zu vereinfachen, wie eine Xamarin.Forms-Anwendung Daten anzeigt und mit ihnen interagiert. Sie stellt eine Verbindung zwischen der Benutzeroberfläche und der zugrundeliegenden Anwendung her. Die BindableObject-Klasse beinhaltet einen Großteil der Infrastruktur, um die Datenbindung zu unterstützen.

Bei der Datenbindung werden zwei Objekte miteinander verbunden: die Quelle und das Ziel. Das Quellobjekt stellt die Daten bereit. Das Zielobjekt verwendet Daten aus dem Quellobjekt (und zeigt diese häufig an). Mit einem Editor (Zielobjekt) wird die zugehörige Eigenschaft Text beispielsweise häufig an eine öffentliche string-Eigenschaft in einem Quellobjekt gebunden. Das folgende Diagramm veranschaulicht die Bindungsbeziehung:

Data Binding

Der Hauptvorteil der Datenbindung ist, dass Sie Daten zwischen Ihren Ansichten und der Datenquelle nicht mehr synchronisieren müssen. Änderungen im Quellobjekt werden automatisch mithilfe von Push intern vom Bindungsframework in das Zielobjekt übertragen, und Änderungen im Zielobjekt können optional wieder zurück in das Quellobjekt übertragen werden.

Die Datenbindung wird in zwei Schritten eingerichtet:

  • Die Eigenschaft BindingContext des Zielobjekts muss auf die Quelle festgelegt werden.
  • Zwischen dem Ziel und der Quelle muss eine Bindung eingerichtet werden. In XAML wird dies mit der Binding-Markuperweiterung erreicht.

In der Notes-Anwendung ist der Editor, der eine Notiz anzeigt, das Bindungsziel, während die Instanz Note, die als die Eigenschaft BindingContext von NoteEntryPage festgelegt ist, die Bindungsquelle darstellt. Anfänglich wird der BindingContext der NoteEntryPage festgelegt, wenn der Seitenkonstruktor ausgeführt wird:

public NoteEntryPage()
{
    // ...
    BindingContext = new Note();
}

In diesem Beispiel wird der BindingContext der Seite auf ein neues Note-Element festgelegt, wenn die NoteEntryPage erstellt wird. Damit wird das Szenario des Hinzufügens einer neuen Notiz zur Anwendung verarbeitet.

Außerdem kann der BindingContext der Seite auch festgelegt werden, wenn die Navigation zur NoteEntryPage erfolgt, vorausgesetzt, dass auf der NotesPage eine vorhandene Notiz ausgewählt wurde:

[QueryProperty(nameof(ItemId), nameof(ItemId))]
public partial class NoteEntryPage : ContentPage
{
    public string ItemId
    {
        set
        {
            LoadNote(value);
        }

        async void LoadNote(string itemId)
        {
            try
            {
                int id = Convert.ToInt32(itemId);
                // Retrieve the note and set it as the BindingContext of the page.
                Note note = await App.Database.GetNoteAsync(id);
                BindingContext = note;
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to load note.");
            }
        }    
        // ...    
    }
}

In diesem Beispiel wird bei Ausführung einer Seitennavigation der BindingContext der Seite auf das ausgewählte Note-Objekt festgelegt, nachdem es aus der Datenbank abgerufen wurde.

Wichtig

Die Eigenschaft BindingContext der einzelnen Zielobjekte kann einzeln festgelegt werden, dies ist jedoch nicht erforderlich. BindingContext ist eine spezielle Eigenschaft, die von allen zugehörigen untergeordneten Elementen geerbt wird. Wenn die Eigenschaft BindingContext auf der Seite ContentPage auf eine Note-Instanz festgelegt wird, verfügen folglich alle untergeordneten Elemente der Seite ContentPage über die gleiche BindingContext-Eigenschaft und können eine Bindung an öffentliche Eigenschaften des Note-Objekts vornehmen.

Der Editor auf der Seite NoteEntryPage bindet dann die Eigenschaft Text des Objekts Note:

<Editor Placeholder="Enter your note"
        Text="{Binding Text}" />

Zwischen der Eigenschaft Editor.Text und der Eigenschaft Text des Quellobjekts wird eine Bindung eingerichtet. Am Editor vorgenommene Änderungen werden automatisch an das Note-Objekt weitergegeben. Gleichermaßen aktualisiert die Xamarin.Forms-Bindungs-Engine auch die Inhalte von Editor, wenn Änderungen an der Eigenschaft Note.Text vorgenommen werden. Dies wird als bidirektionale Bindung bezeichnet.

Weitere Informationen zur Datenbindung finden Sie unter Xamarin.Forms-Datenbindung.

Format

Xamarin.Forms-Anwendungen enthalten häufig mehrere visuelle Elemente, die identisch dargestellt werden. Es kann sehr eintönig und fehleranfällig sein, die Darstellung der visuellen Elemente einzeln festzulegen. Stattdessen können Formatvorlagen, die die Darstellung definieren, erstellt und anschließend auf die erforderlichen visuellen Elemente angewendet werden.

Die Klasse Style gruppiert eine Sammlung von Eigenschaftswerten in ein Objekt, das anschließend auf mehrere Instanzen von visuellen Elementen angewendet werden kann. Formatvorlagen werden entweder auf Anwendungs-, auf Ansichts- oder auf Seitenebene in einer ResourceDictionary-Klasse gespeichert. Die Entscheidung, wo Sie eine Style-Klasse definieren, hat Einfluss darauf, wo Sie sie verwenden können:

  • Eine auf Anwendungsebene definierte Style-Instanz können Sie für die gesamte Anwendung nutzen.
  • Eine auf Seitenebene definierte Style-Instanz können Sie nur auf die jeweilige Seite und deren untergeordneten Seiten anwenden.
  • Eine auf Ansichtsebene definierte Style-Instanz können Sie nur auf die jeweilige Ansicht und deren untergeordneten Ansichten anwenden.

Wichtig

Alle Formatvorlagen, die in der gesamten Anwendung verwendet werden, werden im Ressourcenverzeichnis der Anwendung gespeichert, damit eine Duplizierung verhindert wird. XAML-Code, der für eine Seite spezifisch ist, sollte jedoch nicht im Ressourcenverzeichnis der Anwendung enthalten sein, da die Ressourcen dann beim Starten der Anwendung analysiert werden und nicht, wenn dies auf einer Seite erforderlich ist. Weitere Informationen finden Sie unter Verringern der Größe des Ressourcenverzeichnisses der Anwendung.

Jede Style-Instanz enthält eine Sammlung mit mindestens einem Setter-Objekt. Dabei weist jedes Setter-Objekt eine Property und einen Value auf. Property ist der Name der bindbaren Eigenschaft des Elements, auf das die Formatvorlage angewendet wird, und Value ist der Wert, der auf die Eigenschaft angewendet wird. Das folgende Codebeispiel zeigt eine Formatvorlage von NoteEntryPage:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Notes.Views.NoteEntryPage"
             Title="Note Entry">
    <ContentPage.Resources>
        <!-- Implicit styles -->
        <Style TargetType="{x:Type Editor}">
            <Setter Property="BackgroundColor"
                    Value="{StaticResource AppBackgroundColor}" />
        </Style>
        ...
    </ContentPage.Resources>
    ...
</ContentPage>

Diese Formatvorlage wird auf alle Editor-Instanzen auf der Seite angewendet.

Wenn Sie eine Style-Instanz erstellen, wird immer die Eigenschaft TargetType benötigt.

Hinweis

Xamarin.Forms-Anwendungen werden normalerweise mithilfe von XAML-Formatvorlagen formatiert. Xamarin.Forms unterstützt jedoch auch das Formatieren von visuellen Elementen mithilfe von Cascading Stylesheets (CSS). Weitere Informationen finden Sie unter Formatieren von Xamarin.Forms-Apps mithilfe von Cascading Stylesheets (CSS).

Weitere Informationen zu XAML-Formatvorlagen finden Sie unter Formatieren von Xamarin.Forms-Apps mithilfe von XAML-Formatvorlagen.

Testen und Bereitstellen

Sowohl Visual Studio für Mac als auch Visual Studio stellen viele Optionen zum Testen und Bereitstellen einer Anwendung bereit. Das Debuggen von Anwendungen ist ein üblicher Vorgang im Lebenszyklus der Anwendungsentwicklung und trägt dazu bei, Codeprobleme zu diagnostizieren. Weitere Informationen finden Sie unter Festlegen eines Haltepunkts, Step Through Code (Detailliertes Durchlaufen von Code) und Output Information to the Log Window (Ausgabeinformationen an das Protokollfenster).

Simulatoren eigenen sich hervorragend für die Bereitstellung und das Testen einer Anwendung. Außerdem bieten sie nützliche Funktionen zum Testen von Anwendungen. Allerdings verwenden Benutzer die endgültige Anwendung nicht in einem Simulator. Daher sollte die Anwendungen frühzeitig und häufig auf echten Geräten getestet werden. Weitere Informationen zur Bereitstellung von iOS-Geräten finden Sie unter Device Provisioning (Gerätebereitstellung). Weitere Informationen zur Bereitstellung von Android-Geräten finden Sie unter Set Up Device for Development (Einrichten eines Geräts für die Entwicklung).

Nächste Schritte

In diesem Artikel wurden die Grundlagen der Anwendungsentwicklung mit der Xamarin.Forms-Shell erläutert. Vorgeschlagene nächste Schritte umfassen das Lesen über folgende Funktionen:

  • Die Xamarin.Forms-Shell reduziert die Komplexität der Entwicklung mobiler Anwendungen, indem die grundlegenden Features bereitgestellt werden, die von den meisten mobilen Anwendungen benötigt werden. Weitere Informationen finden Sie unter Xamarin.Forms-Shell.
  • Beim Erstellen der Benutzeroberfläche einer Xamarin.Forms-Anwendung kommen verschiedene Steuerelementgruppen zum Einsatz. Weitere Informationen finden Sie unter Steuerelementreferenz.
  • Bei der Datenbindung werden die Eigenschaften von zwei Objekten verknüpft. Dadurch werden Änderungen an einer Eigenschaft automatisch in der anderen widergespiegelt. Weitere Informationen finden Sie unter Datenbindung.
  • Xamarin.Forms stellt abhängig vom verwendeten Seitentyp eine Reihe unterschiedlicher Seitennavigationsfunktionen bereit. Weitere Informationen finden Sie unter Navigation.
  • Stile können repetitives Markup reduzieren und erleichtern Änderungen an der Darstellung von Anwendungen. Weitere Informationen finden Sie unter Formatieren von Xamarin.Forms-Apps.
  • Datenvorlagen bieten die Möglichkeit, die Darstellung von Daten für unterstützte Ansichten zu definieren. Weitere Informationen finden Sie unter Datenvorlagen.
  • Zudem können durch Effekte native Steuerelemente auf den einzelnen Plattformen angepasst werden. Effekte werden in plattformspezifischen Projekten erstellt, indem Unterklassen für die PlatformEffect-Klasse erstellt werden. Sie werden verarbeitet, indem sie an das entsprechende Xamarin.Forms-Steuerelement angefügt werden. Weitere Informationen finden Sie unter Effekte.
  • Die einzelnen Seiten, Layouts und Ansichten werden auf jeder Plattform auf unterschiedliche Weise über eine Renderer-Klasse gerendert. Diese erstellt ein natives Steuerelement, ordnet dieses auf dem Bildschirm an und fügt das im freigegebenen Code angegebene Verhalten hinzu. Entwickler können ihre eigenen benutzerdefinierten Renderer-Klassen implementieren, um die Darstellung und/oder das Verhalten eines Steuerelements anzupassen. Weitere Informationen finden Sie unter Custom Renderers (Benutzerdefinierte Renderer).
  • Freigegebener Code kann über die DependencyService-Klasse auf eine native Funktion zugreifen. Weitere Informationen finden Sie unter Accessing Native Features with DependencyService (Zugreifen auf native Funktionen über DependencyService).

Auf Channel 9 und auf YouTube finden Sie weitere Videos zu Xamarin.