Übung: Entwickeln Ihrer Xamarin.Forms-Benutzeroberfläche und -Anwendungslogik

Abgeschlossen

An diesem Punkt ist die mobile App eine einfache „Hallo Welt“-App. In dieser Lerneinheit fügen Sie die Benutzeroberfläche und die grundlegende Anwendungslogik hinzu.

Die Benutzeroberfläche der App besteht aus Folgendem:

  • Ein Steuerelement für Texteingaben, um Telefonnummern einzugeben.
  • Eine Schaltfläche, um Ihren Standort mithilfe von Azure Functions an diese Nummern zu senden.
  • Eine Bezeichnung, die eine Meldung an den Benutzer des aktuellen Status sendet, z. B. dass der Standort gesendet wurde und dass der Standort erfolgreich gesendet wird.

Xamarin.Forms unterstützt ein Entwurfsmuster, das als „Model-View-ViewModel“ (MVVM) bezeichnet wird. Weitere Informationen zu MVVM finden Sie in der Xamarin-Dokumentation zu MVVM. Das Wesentliche bei MVVM ist jedoch, dass jede Seite (Ansicht) über ein ViewModel verfügt, das Eigenschaften und Verhaltensweisen verfügbar macht.

ViewModel-Eigenschaften sind nach Name an die Komponenten der Benutzeroberfläche „gebunden“, und diese Bindung synchronisiert Daten zwischen der Ansicht und dem ViewModel. Eine string-Eigenschaft in einem ViewModel namens Name kann beispielsweise an die Text-Eigenschaft eines Steuerelements für die Texteingabe auf der Benutzeroberfläche gebunden werden. Das Steuerelement für die Texteingabe zeigt den Wert in der Name-Eigenschaft an. Wenn der Benutzer den Text auf der Benutzeroberfläche ändert, wird die Name-Eigenschaft aktualisiert. Wenn der Wert der Name-Eigenschaft im ViewModel geändert wird, wird ein Ereignis ausgelöst, damit die Benutzeroberfläche aktualisiert wird.

Das ViewModel-Verhalten wird als Befehlseigenschaften verfügbar macht. Ein Befehl ist ein Objekt, der eine Aktion umfasst, die ausgeführt wird, wenn der Befehl aufgerufen wird. Diese Befehle sind nach Namen an Steuerelemente wie Schaltflächen gebunden, und das Drücken einer Schaltfläche ruft den Befehl auf.

Erstellen eines grundlegenden ViewModels

ViewModels implementieren die INotifyPropertyChanged-Schnittstelle. Diese Schnittstelle verfügt über ein einzelnes Ereignis, PropertyChanged, mit dem die Benutzeroberfläche über Updates benachrichtigt wird. Dieses Ereignis verfügt über Ereignisargumente, die den Namen der Eigenschaft, die geändert wurde, enthalten. Es ist üblich, eine ViewModel-Basisklasse zu erstellen, die diese Schnittstelle implementiert und einige Hilfsmethoden bereitstellt.

  1. Klicken Sie mit der rechten Maustaste auf das Projekt „ImHere“, und wählen Sie Hinzufügen>Klasse aus.

  2. Nennen Sie die neue Klasse „BaseViewModel“, und wählen klicken Sie Hinzufügen aus.

  3. Fügen Sie eine using-Anweisung für System.ComponentModel und System.Runtime.CompilerServices hinzu.

     using System.ComponentModel;
     using System.Runtime.CompilerServices;
    
  4. Legen Sie die Klasse auf public fest, und führen Sie eine Ableitung von INotifyPropertyChanged durch.

      public class BaseViewModel : INotifyPropertyChanged
    
  5. Implementieren Sie die INotifyPropertyChanged-Schnittstelle, indem Sie das PropertyChanged-Ereignis hinzufügen:

    public event PropertyChangedEventHandler PropertyChanged;
    
  6. Fügen Sie die Set-Methode zum Auslösen des PropertyChanged-Ereignisses hinzu.

    protected void Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (Equals(field, value)) return;
        field = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    

    Diese Methode verweist auf die Unterstützungsvariable, den neuen Wert und den Eigenschaftennamen. Wenn das Feld nicht geändert wurde, wird die Methode zurückgegeben. Andernfalls wird das Feld aktualisiert, und das PropertyChanged-Ereignis wird ausgelöst. Der propertyName-Parameter der Set-Methode ist ein Standardparameter, der mit dem CallerMemberName-Attribut markiert ist. Wenn diese Methoden über einen Eigenschaftensetter aufgerufen wird, wird dieser Parameter üblicherweise als Standardwert beibehalten. Der Compiler legt den Parameterwert dann automatisch auf den Namen der aufrufenden Eigenschaft fest.

Im Folgenden finden Sie den vollständigen Code für diese Klasse.

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace ImHere
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(field, value)) return;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Erstellen eines ViewModels für die Seite

Das MainPage-Objekt enthält ein Steuerelement für die Texteingabe, in das Telefonnummern eingegeben werden können, und eine Bezeichnung, um eine Meldung anzuzeigen. Diese Steuerelemente werden an die Eigenschaften in einem ViewModel gebunden.

  1. Erstellen Sie eine Klasse namens MainViewModel im .NET Standard-Projekt ImHere.

  2. Fügen Sie eine using-Anweisung für Xamarin.Forms und System.Threading.Tasks hinzu.

      using Xamarin.Forms;
      using System.Threading.Tasks;
    
  3. Legen Sie diese Klasse auf „public“ fest, und führen Sie eine Ableitung von BaseViewModel durch.

       public class MainViewModel : BaseViewModel
    
  4. Fügen Sie zwei string-Eigenschaften (PhoneNumbers und Message) hinzu, die jeweils ein Unterstützungsfeld enthalten. Verwenden Sie im Eigenschaftensetter die Methode Set der Basisklasse, um den Wert zu aktualisieren und das PropertyChanged-Ereignis auszulösen.

     string message = "";
     public string Message
     {
         get => message;
         set => Set(ref message, value);
     }
    
     string phoneNumbers = "";
     public string PhoneNumbers
     {
         get => phoneNumbers;
         set => Set(ref phoneNumbers, value);
     }
    
  5. Fügen Sie eine schreibgeschützte Befehlseigenschaft namens SendLocationCommand hinzu. Dieser Befehl weist den Typ ICommand des System.Windows.Input-Namespace auf.

    public ICommand SendLocationCommand { get; }
    
  6. Fügen Sie der Klasse einen Konstruktor hinzu, und initialisieren Sie in diesem Konstruktor den SendLocationCommand-Befehl als neuen Xamarin.Forms-Befehl Command.

    public MainViewModel()
    {
        SendLocationCommand = new Command(async () => await SendLocation());
    }
    
  7. Erstellen Sie eine async-Methode namens SendLocation, und übergeben Sie eine Lambdafunktion, die auf den Aufruf des Konstruktors wartet (await). Der Text dieser Methode wird später in diesem Modul aktualisiert.

    async Task SendLocation()
    {
    }
    

Im Folgenden finden Sie den vollständigen Code für diese Klasse.

using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

namespace ImHere
{
    public class MainViewModel : BaseViewModel
    {
        string message = "";
        public string Message
        {
            get => message;
            set => Set(ref message, value);
        }

        string phoneNumbers = "";
        public string PhoneNumbers
        {
            get => phoneNumbers;
            set => Set(ref phoneNumbers, value);
        }

        public MainViewModel()
        {
            SendLocationCommand = new Command(async () => await SendLocation());
        }

        public ICommand SendLocationCommand { get; }

        async Task SendLocation()
        {
        }
    }
}

Erstellen der Benutzeroberfläche

Xamarin.Forms-Benutzeroberflächen können mithilfe von XAML erstellt werden.

  1. Öffnen Sie die MainPage.xaml-Datei über das ImHere-Projekt. Die Seite wird im XAML-Editor geöffnet.

    Hinweis

    Das ImHere.UWP-Projekt enthält ebenfalls eine Datei namens MainPage.xaml. Vergewissern Sie sich, dass Sie die Datei in der .NET Standard-Bibliothek bearbeiten.

  2. Fügen Sie den folgenden XAML-Code auf der ContentPage der obersten Ebene ein, um eine Instanz von ViewModel als Bindungskontext der Seite festzulegen.

    <ContentPage.BindingContext>
        <local:MainViewModel/>
    </ContentPage.BindingContext>
    
  3. Ersetzen Sie StackLayout durch den folgenden Code:

    <StackLayout Padding="20">
       <Label Text="Phone numbers to send to:" HorizontalOptions="Start"/>
       <Editor Text="{Binding PhoneNumbers}" HeightRequest="100"/>
    </StackLayout>
    
    • Das Steuerelement Editor wird verwendet, um Telefonnummern hinzuzufügen, und das Element Label oben beschreibt den Zweck dieses Felds für den Benutzer.
    • Die untergeordneten Steuerelemente des Stapels von StackLayout werden horizontal oder vertikal in der Reihenfolge angeordnet, in der sie hinzugefügt werden. Wenn Label also zuerst hinzugefügt wird, wird es über Editor platziert.
    • Bei Editor-Steuerelementen handelt es sich um mehrzeilige Steuerelemente für Eingaben, über die der Benutzer mehrere Telefonnummern (eine pro Zeile) eingeben kann.

    Die Text-Eigenschaft von Editor ist an die PhoneNumbers-Eigenschaft von MainViewModel gebunden. Die Syntax für die Bindung soll den Eigenschaftenwert auf "{Binding <property name>}" festlegen. Durch die geschweiften Klammern wird der XAML-Compiler darüber informiert, dass dieser Wert ein Sonderfall ist und nicht wie eine einfache Zeichenfolge (string) behandelt werden soll.

  4. Fügen Sie ein Button-Element unterhalb des Steuerelements Editor hinzu. Diese Schaltfläche wird verwendet, um den Standort des Benutzers zu senden.

    <Button Text="Send Location" BackgroundColor="Blue" TextColor="White"
            Command="{Binding SendLocationCommand}" />
    

    Die Command-Eigenschaft wird an den SendLocationCommand-Befehl von ViewModel gebunden. Beim Tippen auf die Schaltfläche wird der Befehl ausgeführt.

  5. Fügen Sie ein Label-Element unterhalb des Steuerelements Button hinzu. Statusmeldungen werden in dieser Bezeichnung angezeigt.

    <Label Text="{Binding Message}"
           HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
    

    Im Folgenden finden Sie den vollständigen Code für diese Seite.

    <?xml version="1.0" encoding="utf-8"?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:ImHere"
                 x:Class="ImHere.MainPage">
        <ContentPage.BindingContext>
            <local:MainViewModel/>
        </ContentPage.BindingContext>
        <StackLayout Padding="20">
            <Label Text="Phone numbers to send to:" HorizontalOptions="Start"/>
            <Editor Text="{Binding PhoneNumbers}" HeightRequest="100"/>
            <Button Text="Send Location" BackgroundColor="Blue" TextColor="White"
                    Command="{Binding SendLocationCommand}" />
            <Label Text="{Binding Message}"
                   HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
        </StackLayout>
    </ContentPage>
    
  6. Führen Sie die App aus, um die neue Benutzeroberfläche anzuzeigen. Wenn Sie die Bindungen an diesem Punkt überprüfen möchten, können Sie dies tun, indem Sie Breakpoints zu den Eigenschaften oder zur SendLocation-Methode hinzuzufügen.

    Hinweis

    Beim Kompilieren der App wird eine Warnung angezeigt, die darauf hinweist, dass für SendLocation die await-Modifizierer fehlen. Sie können diese Warnung ignorieren, da sie aufgelöst wird, sobald dieser Methode in der nächsten Lerneinheit weiterer Code hinzugefügt wird.

    Screenshot that shows the new app interface.

Zusammenfassung

In dieser Lerneinheit haben Sie gelernt, die Benutzeroberfläche für die App mithilfe von XAML zu erstellen. Außerdem haben Sie ein ViewModel erstellt, um die Anwendungslogik zu verarbeiten. Sie haben ebenfalls gelernt, wie das ViewModel an die Benutzeroberfläche gebunden wird. In der nächsten Lerneinheit fügen Sie dem ViewModel die Suche nach dem Standort hinzu.