April 2019

Band 34, Nummer 4

[Xamarin]

Neuerungen in Xamarin.Forms 4.0

Von Alessandro Del Del

Während der Konferenz Connect(); im November 2018 hat Microsoft die erste öffentliche Vorschau von Xamarin.Forms 4.0 vorgestellt, der neuesten Version der beliebten Entwicklungstechnologie, die es einfach macht, gemeinsame Benutzeroberflächen für verschiedene Betriebssysteme (einschließlich Android, iOS und Windows 10) zu erstellen. Aktualisierte Vorschauversionen sind gefolgt und geben Entwicklern einen genaueren Einblick in den Fortschritt dieser Hauptversion. Die wichtigsten neuen Funktionen, die Xamarin.Forms 4.0 so einzigartig machen, lassen sich wie folgt zusammenfassen.

Die Shell ist ein Container für Anwendungen. Sie stellt die meisten allgemeinen Funktionen bereit, die die Benutzeroberfläche benötigt. Sie stellt einen zentralen Ort zur Beschreibung der visuellen Struktur einer Anwendung dar und beinhaltet eine allgemeine Benutzeroberfläche für die Seitennavigation, einen Navigationsdienst mit Deep Linking und einen integrierten Suchhandler. Zurzeit ist die Shell nur für iOS und Android verfügbar.

CollectionView ist ein völlig neues Steuerelement, das entwickelt wurde, um mit Datenlisten effizienter und leistungsfähiger arbeiten zu können. Es ist außerdem die Grundlage für die aktualisierte Version des CarouselView-Steuerelements.

Visual ist der Name einer neuen Eigenschaft, die einige Ansichten verwenden können, um Steuerelemente basierend auf einem bestimmten Design zu rendern. Dadurch ist es einfach, konsistente plattformübergreifende Benutzeroberflächen zu erstellen.

Eine ausführliche Beschreibung des Shell-Features finden Sie in der Sonderausgabe zur Connect(); (msdn.com/magazine/mt848639), daher werde ich hier nicht darauf eingehen. Stattdessen konzentriere ich mich auf CollectionView, CarouselView, Visual und andere verschiedene Verbesserungen der vorhandenen Codebasis. Außerdem werfe ich einen kurzen Blick auf einige neue Funktionen in Visual Studio 2019 Vorschau 2 für Xamarin.Forms. Beachten Sie, dass sich die in diesem Artikel beschriebenen Features noch in der Vorschau befinden und Änderungen unterliegen können.

Erstellen und Einrichten eines Projekts

Um mit der aktuellen Vorschau von Xamarin.Forms 4.0 zu arbeiten, müssen Sie zunächst wie gewohnt ein Mobile App-Projekt (Xamarin.Forms-Projekt) in Visual Studio 2017 erstellen. Wählen Sie die iOS- und Android-Plattformen und die .NET Standard-Codefreigabestrategie aus. Wenn das neue Projekt fertig ist, stellen Sie mit dem NuGet-Paket-Manager sicher, dass Sie ein Upgrade der Xamarin.Forms-Bibliothek auf die neueste verfügbare Vorabversion durchführen (für diese Kolumne war es Version 4.0.0.0.94569-pre3). Wenn Sie diese Vorschau installieren, fügt NuGet dem iOS-Plattformprojekt auch das Xamarin.iOS.MaterialComponents-Paket hinzu, wie ich später im Zusammenhang mit der Visual-Eigenschaft erläutern werde.

Der letzte Schritt besteht darin, alle experimentellen Funktionen in der Vorschau von Xamarin.Forms 4.0 in der Datei „MainActivity.cs“ für Android und der Datei „AppDelegate.cs“ für iOS zu aktivieren. Fügen Sie in beiden Dateien vor dem Aufruf der Xamarin.Forms.Forms.Init-Methode die folgende Codezeile hinzu:

global::Xamarin.Forms.Forms.SetFlags("Shell_Experimental", "Visual_Experimental",
  "CollectionView_Experimental");

Sie sollten das Flag Shell_Experimental hinzufügen, wenn Sie mit der Shell-Funktion experimentieren möchten. Andernfalls ist es für die nächsten Themen optional.

Arbeiten mit Daten: Das CollectionView-Steuerelement

Xamarin.Forms 4.0 führt ein brandneues Steuerelement namens CollectionView ein, mit dem Sie Listen mit Daten anzeigen und bearbeiten können. Aus architektonischer Sicht bietet CollectionView einige wesentliche Vorteile. Zum einen sind die Datenvorlagen im Gegensatz zu ListView nicht mehr auf Cell-Ansichten angewiesen, was die visuelle Struktur vereinfacht. Folglich und als zweiten Vorteil codieren Sie CollectionView-Objekte mit dem gleichen bekannten Ansatz auf Basis von XAML, aber mit viel einfacherem Code. Darüber hinaus erleichtert das CollectionView-Steuerelement die Verwaltung des Layouts Ihrer Listen, indem es horizontale Layouts und Rasteransichten unterstützt. Beginnen wir mit der Erstellung einiger Beispieldaten, die in einem CollectionView-Steuerelement angezeigt werden. Fügen Sie im .NET Standard-Projekt die in Abbildung 1 gezeigte Klasse hinzu, die die vereinfachte Definition eines Produkts darstellt.

Abbildung 1A: Vereinfachte Implementierung einer Product-Klasse

public class Product : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;
  private void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChanged?.Invoke(this,
      new PropertyChangedEventArgs(propertyName));
  }
  private int _productQuantity;
  private string _productName;
  private string _productImage;
  public int ProductQuantity
  {
    get
    {
      return _productQuantity;
    }
    set
    {
      _productQuantity = value;
      OnPropertyChanged();
    }
  }
  public string ProductName
  {
    get
    {
      return _productName;
    }
    set
    {
      _productName = value;
      OnPropertyChanged();
    }
  }
  public string ProductImage
  {
    get
    {
      return _productImage;
    }
    set
    {
      _productImage = value;
      OnPropertyChanged();
    }
  }
}

Beachten Sie, wie die Product-Klasse die INotifyPropertyChanged-Schnittstelle implementiert, um Änderungsbenachrichtigungen zu unterstützen, wenn Sie sich entscheiden, eine Produktinstanz bearbeitbar zu machen. Der nächste Schritt besteht darin, ein Ansichtsmodell zu definieren, das die Produktinformationen bereitstellt, deren Daten an die Benutzeroberfläche gebunden werden. Dies wird in Abbildung 2 dargestellt.

Abbildung 2: Die ProductViewModel-Klasse stellt Dateninformationen für die Benutzeroberfläche bereit

public class ProductViewModel
{
  public ObservableCollection<Product> Products { get; set; }
  public ProductViewModel()
  {
    // Sample products
    this.Products = new ObservableCollection<Product>();
    this.Products.Add(new Product { ProductQuantity = 50, ProductName = "Cheese",
                                    ProductImage = "Cheese.png" });
    this.Products.Add(new Product { ProductQuantity = 10, ProductName = "Water",
                                    ProductImage = "Water.png" });
    this.Products.Add(new Product { ProductQuantity = 6, ProductName = "Bread",
                                    ProductImage = "Bread.png" });
    this.Products.Add(new Product { ProductQuantity = 40, ProductName = "Tomatoes",
                                    ProductImage = "Tomato.png" });
  }
}

In einem realen Szenario könnten Daten aus einer Datenbank oder aus einem Webdienst stammen, aber in diesem Fall erstelle ich zu Demonstrationszwecken einige Produkte direkt im Code. Die in Abbildung 2 verwendeten Bilddateien befinden sich im Begleitcode zu diesem Artikel. In der Datei „MainPage.xaml“ Ihres Projekts können Sie dann ein CollectionView-Steuerelement deklarieren, um die Daten anzuzeigen. Die wichtigsten Punkte sind die Zuordnung der anzuzeigenden Sammlung zur ItemsSource-Eigenschaft und die Definition einer Datenvorlage für jedes Element in der Liste. Abbildung 3 zeigt ein Beispiel.

Abbildung 3: Deklarieren einer CollectionView zum Anzeigen von Daten

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XF4_WhatsNew"
             x:Class="XF4_WhatsNew.MainPage">
  <StackLayout>
    <CollectionView x:Name="ProductList" ItemsSource="{Binding Products}">
      <CollectionView.ItemTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="24"/>
              <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Image Source="{Binding ProductImage}" HeightRequest="22" />
            <StackLayout Grid.Column="1" Orientation="Vertical" Spacing="5">
              <Label Text="{Binding ProductName}" FontSize="Medium"
                TextColor="Blue"/>
              <Label Text="{Binding ProductQuantity}" FontSize="Small"
                TextColor="Black"/>
            </StackLayout>
          </Grid>
        </DataTemplate>
      </CollectionView.ItemTemplate>
    </CollectionView>
  </StackLayout>
</ContentPage>

Die Deklaration von CollectionView und die Zuweisung der ItemTemplate-Eigenschaft an ein DataTemplate-Objekt in XAML funktioniert genau so wie mit dem ListView-Steuerelement. Der wichtige Unterschied besteht darin, dass Sie sich nicht mehr mit Cell-Ansichten beschäftigen müssen. Anschließend erstellen Sie eine Instanz der ProductViewModel-Klasse und weisen sie der BindingContext-Eigenschaft der Seite zu, damit die Datenbindung funktionieren kann, wie im folgenden Code, der in die Datei „MainPage.xaml.cs“ geschrieben wird:

public partial class MainPage : ContentPage
{
  private ProductViewModel ViewModel { get; set; }
  public MainPage()
  {
    InitializeComponent();
    this.ViewModel = new ProductViewModel();
    this.BindingContext = this.ViewModel;
  }
}

Wenn Sie diesen Code ausführen, sehen Sie ein Ergebnis wie das in Abbildung 4 gezeigte.

Anzeigen von Listen mit Daten mit CollectionView
Abbildung 4: Anzeigen von Listen mit Daten mit CollectionView

Wie Sie sehen werden, bietet CollectionView weitere interessante Eigenschaften zur Implementierung verschiedener Layouts und zur Verarbeitung der Artikelauswahl.

Ausrichtung und Layout : Wenn Sie Erfahrung mit dem ListView-Steuerelement in Xamarin.Forms haben, wissen Sie, dass es keine integrierte Option zum Festlegen der Ausrichtung als horizontal gibt. Dies kann sicherlich mithilfe von benutzerdefinierten Renderern erreicht werden, aber es erhöht die Komplexität Ihres Codes. Ebenso gibt es keine integrierte Option, um das Layout von einer Listenansicht in eine Rasteransicht zu ändern. Mit dem CollectionView-Steuerelement ist es jedoch sehr einfach, verschiedene Layoutoptionen über die ItemsLayout-Eigenschaft festzulegen, die mit Eigenschaften aus der ListItemsLayout-Klasse wie VerticalList und HorizontalList zugewiesen werden können. Standardmäßig wird die ItemsLayout-Eigenschaft mit ListItemsLayout.VerticalList zugewiesen, sodass Sie sie bei einem vertikalen Layout nicht explizit zuweisen müssen. Um jedoch eine horizontale Ausrichtung zu implementieren, fügen Sie Ihrem XAML den folgenden Codeausschnitt hinzu:

<CollectionView ItemsSource="{Binding Products}"
  It­emsLayout="{x:Static ListItemsLayout.HorizontalList}">
  ...
</CollectionView>

Tatsächlich können Sie auch mit der ItemsLayout-Eigenschaft eine Rasteransicht definieren. In diesem Fall verwenden Sie wie im folgenden Beispiel, das zeigt, wie eine horizontale Rasteransicht erstellt wird, die GridItemsLayout-Klasse anstelle von ListItemsLayout:

<CollectionView x:Name="ProductList" ItemsSource="{Binding Products}" >
  <CollectionView.ItemsLayout>
    <GridItemsLayout Orientation="Horizontal" Span="3" />
  </CollectionView.ItemsLayout>
    ...
</CollectionView>

Standardmäßig zeigt GridItemsLayout Elemente in einer einzigen Zeile mit dem horizontalen Layout an, sodass Sie die Span-Eigenschaft festlegen können, um zu entscheiden, wie viele Zeilen das Raster enthalten soll. Wenn der datengebundenen Liste Elemente hinzugefügt werden, wächst die Rasteransicht horizontal. Mit dem folgenden Code können Sie eine vertikale Rasteransicht erhalten:

<CollectionView x:Name="ProductList" ItemsSource="{Binding Products}" >
  <CollectionView.ItemsLayout>
    <GridItemsLayout Orientation="Vertical" Span="2" />
  </CollectionView.ItemsLayout>
    ...
</CollectionView>

Ebenso zeigt ein vertikales Raster Elemente standardmäßig in einer einzigen Spalte an, sodass Sie die Span-Eigenschaften ändern und die Anzahl der Spalten für das Raster festlegen können.

Verwalten der Elementauswahl : Das CollectionView-Steuerelement ermöglicht die Auswahl einzelner oder mehrerer Elemente und die Deaktivierung der Auswahl. Der SelectionMode-Eigenschaft können Werte aus der Xamarin.Forms.SelectionMode-Enumeration zugewiesen werden: „None“, „Single“ und „Multiple“. Mit „None“ können Sie die Elementauswahl sehr einfach deaktivieren. Die SelectedItem-Eigenschaft vom Typ „object“ stellt mindestens ein ausgewähltes Element in der Liste dar. Das SelectionChanged-Ereignis wird dann ausgelöst, wenn der Benutzer ein Element in der CollectionView auswählt. Ein solches Ereignis funktioniert nur, wenn SelectionMode entweder „Single“ (Standardeinstellung, wenn SelectionMode nicht angegeben wurde) oder „Multiple“ zugewiesen wurde. In Ihrem XAML-Code haben Sie also vielleicht die folgenden Zuordnungen:

<CollectionView x:Name="ProductList" ItemsSource="{Binding Products}"
  SelectionMode="Single" SelectionChanged="ProductList_SelectionChanged">
...
</CollectionView>

Dann ermöglicht der SelectionChanged-Ereignishandler die Verwaltung der Elementauswahl über einen Parameter vom Typ Xamarin.Forms.SelectionChangedEventArgs. Dieses Objekt stellt zwei nützliche Eigenschaften bereit, CurrentSelection und PreviousSelection. Wie die Namen schon andeuten, gibt die erste Eigenschaft die aktuell ausgewählten Objekte zurück, während die zweite Eigenschaft Objekte zurückgibt, die zuvor ausgewählt waren. Dies ist sehr nützlich, da Sie unter bestimmten Umständen wissen müssen, welche Objektinstanzen vor der neuen Auswahl tatsächlich ausgewählt waren. Beide Eigenschaften sind vom Typ IReadOnlyList<object> und zeigen die Liste der ausgewählten Elemente an. Wenn SelectionMode als „Single“ festgelegt ist, können Sie die Instanz des ausgewählten Elements wie folgt abrufen:

private void ProductList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  var selectedProduct = this.ProductList.SelectedItem as Product;
  var singleProduct = e.CurrentSelection.FirstOrDefault() as Product;
}

Unabhängig davon, ob Sie die CollectionView.SelectedItem-Eigenschaft oder das erste Element in der Sammlung verwenden, müssen Sie das sich ergebende Objekt in den erwarteten Typ (in diesem Fall „Product“) umwandeln. Wenn SelectionMode auf „Multiple“ festgelegt ist, müssen Sie zunächst die schreibgeschützte Sammlung der ausgewählten Elemente wie im folgenden Beispiel in eine Liste von Objekten des erwarteten Typs umwandeln:

private void ProductList_SelectionChanged(object sender,
  SelectionChangedEventArgs e)
{
  var selectedItems = e.CurrentSelection.Cast<Product>();
  foreach(var product in selectedItems)
  {
    // Handle your object properties here...
  }
}

Der gleiche Ansatz würde für die SelectionChangedEventArgs.PreviousSelection-Eigenschaft sowohl für die Einzel- als auch für die Mehrfachauswahl von Elementen funktionieren. Als moderne Ansicht bietet CollectionView auch Unterstützung für das MVVM-Muster (Model-View-ViewModel) bei der Verarbeitung der Elementauswahl, sodass Sie die SelectionChangedCommand-Eigenschaft verwenden können, die an eine Instanz der Command-Klasse in Ihrem View-Modell gebunden werden kann, sowie den SelectionChangedCommandParameter, der die Übergabe eines Parameters an den Befehl ermöglicht. Erweitern wir beispielsweise die ProductViewModel-Klasse, um eine SelectedProduct-Eigenschaft hinzuzufügen, die datengebunden an die SelectedItem-Eigenschaft der CollectionView ist, und um einen neuen Befehl für die Auswahlverarbeitung. Der Einfachheit halber verwendet die Eigenschaft vom Typ „Command“ weder die generische Implementierung noch den Befehlsparameter. Abbildung 5 zeigt, wie das Ansichtsmodell aussieht.

Abbildung 5: Erweitern des Ansichtsmodells mit MVVM-Unterstützung

public class ProductViewModel: INotifyPropertyChanged
{
  public ObservableCollection<Product> Products { get; set; }
  private Product _selectedProduct;
  public Product SelectedProduct
  {
    get
    {
      return _selectedProduct;
    }
    set
    {
      _selectedProduct = value;
      OnPropertyChanged();
    }
  }
  private Command _productSelectedCommand;
  public Command ProductSelectedCommand
  {
    get
    {
      return _productSelectedCommand;
    }
      set
      {
        _productSelectedCommand = value;
        OnPropertyChanged();
      }
    }
  public ProductViewModel()
  {
    // Sample products
    this.Products = new ObservableCollection<Product>();
    this.Products.Add(new Product { ProductQuantity = 50,
      ProductName = "Cheese", ProductImage = "Cheese.png" });
    this.Products.Add(new Product { ProductQuantity = 10,
      ProductName = "Water", ProductImage = "Water.png" });
    this.Products.Add(new Product { ProductQuantity = 6,
      ProductName = "Bread", ProductImage = "Bread.png" });
    this.Products.Add(new Product { ProductQuantity = 40,
      ProductName = "Tomatoes", ProductImage = "Tomato.png" });
    this.ProductSelectedCommand =
      new Command(ExecuteProductSelectedCommand,
        CanExecuteProductSelectedCommand);
  }
  private bool CanExecuteProductSelectedCommand(object arg)
  {
    return this.SelectedProduct != null;
  }
  private void ExecuteProductSelectedCommand(object obj)
  {
    // Handle your object here....
    var currentProduct = this.SelectedProduct;
  }
  public event PropertyChangedEventHandler PropertyChanged;
  private void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    PropertyChanged?.Invoke(this,
      new PropertyChangedEventArgs(propertyName));
  }
}

Weisen Sie dann in Ihrem XAML-Code die Auswahleigenschaften wie folgt zu:

<CollectionView x:Name="ProductList" ItemsSource="{Binding Products}"
                SelectedItem="{Binding SelectedProduct, Mode=TwoWay}"
                SelectionChangedCommand="{Binding ProductSelectionCommand}"
                SelectionMode="Single">
</CollectionView>

Mit diesem Ansatz können Sie anhand der ausgewählten Objekte im Ansichtsmodell arbeiten, d.h. an dem Ort, an dem Sie die Geschäftslogik implementieren, und die Arbeit an den Daten von den Ansichten entkoppelt halten.

Verwalten leerer Listen : Eine der wichtigsten Funktionen von CollectionView und definitiv einer meiner Favoriten ist die integrierte Option, ohne weitere Kosten eine andere Ansicht anzuzeigen, wenn die datengebundene Liste leer ist. Dies ist über die EmptyView-Eigenschaft möglich, die es ermöglicht, die Ansicht anzugeben, die bei leeren Daten angezeigt werden soll. Sie funktioniert folgendermaßen:

<CollectionView>
...           
  <CollectionView.EmptyView>
     <Label Text="No data is available" TextColor="Red"
       FontSize="Medium"/>
  </CollectionView.EmptyView>
</CollectionView>

Dieser Code generiert das in Abbildung 6 gezeigte Ergebnis. Mit diesem Ansatz müssen Sie keine Datenvorlage für leere Zustände erstellen oder Selektoren für Datenvorlagen implementieren.

Bereitstellen einer Ansicht für leere Zustände
Abbildung 6: Bereitstellen einer Ansicht für leere Zustände

Alternativ können Sie die EmptyViewTemplate-Eigenschaft verwenden, wenn Sie eine benutzerdefinierte Ansicht implementieren möchten. Der folgende Code veranschaulicht beispielsweise, wie sowohl ein Bild als auch eine Textnachricht mit leeren Listen angezeigt werden kann:

<CollectionView.EmptyViewTemplate>
  <DataTemplate>
    <StackLayout Orientation="Vertical" Spacing="20">
      <Image Source="EmptyList.png" Aspect="Fill"/>
      <Label Text="No data is available" TextColor="Red"/>
    </StackLayout>
  </DataTemplate>
</CollectionView.EmptyViewTemplate>

ScrollingCollectionView stellt auch die ScrollTo-Methode zur Verfügung, mit der Sie in der Liste programmgesteuert zu einem bestimmten Element scrollen können. Das folgende Beispiel scrollt zum dritten Element in der Liste:

 

ProductList.ScrollTo(2);

Einfachere API-Oberfläche: Das CollectionView-Steuerelement stellt eine einfachere API-Oberfläche als ListView zur Verfügung. Beispielsweise verfügt CollectionView nicht über Eigenschaften, um mit Separatoren zu arbeiten (wie SeparatorVisibility und SeparatorColor), sodass Sie eigene Separatoren mit Ansichten wie BoxView in der Datenvorlage implementieren können. CollectionView implementiert keine Eigenschaft wie ListView.RowHeight, da die Höhe eines Elements nun durch das erste Element in der Liste bestimmt wird. Die HasUnevenRows-Eigenschaft in ListView besitzt ein Gegenstück in CollectionView namens ItemSizingStrategy. Im Hinblick auf Pull-to-Refresh-Techniken sind Eigenschaften wie IsPullToRefreshEnabled, IsRefreshing und RefreshCommand, die von ListView bereitgestellt werden, im CollectionView-Steuerelement nicht verfügbar. Microsoft arbeitet jedoch an der Implementierung von Eigenschaften, die Ansichten für Aktualisierungszustände unterstützen. Das Xamarin.Forms.CollectionView Spec-Dokument auf GitHub (bit.ly/2N6iw8a) enthält eine ausführliche Erläuterung zu Aktualisierungsoptionen und auch zu anderen API-Implementierungen, einschließlich Architekturentscheidungen.

Einführung in CarouselView

Das CarouselView-Steuerelement ist nicht neu in Xamarin.Forms 4.0. Es wurde jedoch vollständig auf der Grundlage der Struktur und Leistung von CollectionView überarbeitet.

Mit CarouselView können Sie jeweils ein Objekt in der Liste im Kartenformat anzeigen. Abbildung 7 (entnommen aus dem offiziellen Xamarin-Blog (bit.ly/2BwWMNV)) zeigt, wie CarouselView eine Möglichkeit bietet, zwischen Elementen zu blättern.

CarouselView zeigt Elemente in Form von Karten an und ermöglicht die Wischgeste
Abbildung 7: CarouselView zeigt Elemente in Form von Karten an und ermöglicht die Wischgeste

In Bezug auf den zuvor beschriebenen Beispielcode können Sie mit CarouselView die Liste der Produkte als Karten anzeigen, wie in Abbildung 8 gezeigt.

Abbildung 8: Anzeigen von Elementen als Karten mit CarouselView

<CarouselView x:Name="ProductList" ItemsSource="{Binding Products}">
  <CarouselView.ItemsLayout>
    <GridItemsLayout Orientation="Horizontal"
                     SnapPointsAlignment="Center"
                     SnapPointsType="Mandatory"/>
  </CarouselView.ItemsLayout>
  <CarouselView.ItemTemplate>
    <DataTemplate>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="24"/>
          <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Image Source="{Binding ProductImage}" HeightRequest="22" />
        <StackLayout Grid.Column="1" Orientation="Vertical"
                     Spacing="5">
          <Label Text="{Binding ProductName}" FontSize="Medium"
                 TextColor="Blue"/>
          <Label Text="{Binding ProductQuantity}" FontSize="Small"
                 TextColor="Black"/>
        </StackLayout>
      </Grid>
    </DataTemplate>
  </CarouselView.ItemTemplate>
  <CarouselView.EmptyView>
    <Label Text="No data is available" TextColor="Red"
           FontSize="Medium"/>
  </CarouselView.EmptyView>
</CarouselView>

Konzentrieren wir uns auf die wichtigsten Punkte im Code.

Deklarieren von CarouselView: Das Deklarieren von CarouselView in XAML ist sehr ähnlich wie das Deklarieren von CollectionView. Sie müssen die Eigenschaft ItemsSource immer noch an die Sammlung der Daten binden, die Sie anzeigen möchten. Beachten Sie, dass Sie auch Ansichten für leere Zustände bereitstellen können, genau wie mit CollectionView.

Ausrichtung: CarouselView unterstützt horizontale und vertikale Ausrichtung. Sie weisen der ItemsLayout-Eigenschaft eine Instanz von GridItemsLayout zu und übergeben entweder „Horizontal“ oder „Vertikal“ an die Orientation-Eigenschaft.

Hinzufügen von Ausrichtungspunkten: Mit den SnapPointsAlignment- und SnapPointsType-Eigenschaften für ItemsLayout können Sie das Verhalten der Karte konfigurieren. Beispielsweise stellen die SnapPointsType- und SnapPointsAlignment-Eigenschaften in Abbildung 8 sicher, dass die Karte zentriert angezeigt wird. Ohne diese Zuweisungen würden die Karte zwischen den anderen Karten nur teilweise angezeigt. Zulässige Werte für SnapPointsAlignment sind „Center“, „End“ und „Start“. Zulässige Werte für SnapPointsType sind „Mandatory“, „MandatorySingle“ und „None“.

Wie bei CollectionView ist zu beachten, dass die endgültigen Funktionen eine andere API-Implementierung bereitstellen können. Mit der aktuellen Vorschau kann es auch zu einer InvalidCastException kommen, wenn die App die Ansicht rendert. Dies ist ein instabiler Build, daher sind solche Probleme zu erwarten.

Erstellen konsistenter Benutzeroberflächen mit der Visual-Eigenschaft

Xamarin.Forms 4.0 bietet Entwicklern eine neue Möglichkeit, Benutzeroberflächen zu erstellen, die unter Android und iOS weitgehend identisch aussehen, und das fast ohne Aufwand. Der Schlüssel ist eine neue Eigenschaft namens Visual, die von der VisualElement-Klasse bereitgestellt wird. Die Visual-Eigenschaft stellt sicher, dass neue, zusätzliche Renderer anstelle des Standardrenderers verwendet werden, um visuelle Elemente zu zeichnen. Xamarin.Forms 4.0 beinhaltet in seinem aktuellen Stand der Vorschau einen experimentellen Renderingmechanismus, der auf dem Materialdesign basiert und derzeit für die folgenden Ansichten verfügbar ist: Button, Entry, Frame und ProgressBar. Sie können das neue visuelle Renderings wie folgt aktivieren:

 

<Entry Visual="Material" />

Abbildung 9 (entnommen aus den Microsoft-Versionshinweisen für Xamarin.Forms 4.0 (bit.ly/2BB4MxA)) zeigt ein Beispiel für eine konsistente Benutzeroberfläche unter Android und iOS, die mit der Visual-Eigenschaft erstellt wurde.

Konsistente Benutzeroberfläche mit der Visual-Eigenschaft
Abbildung 9: Konsistente Benutzeroberfläche mit der Visual-Eigenschaft

Sie können die Visual-Eigenschaft auch auf der Ebene der ContentPage zuweisen, um sicherzustellen, dass jede der unterstützten Ansichten in Ihrem Code das angegebene Design verwendet. Um Visual verwenden zu können, muss Ihr Projekt einige Anforderungen erfüllen:

  • Im iOS-Projekt muss das NuGet-Paket Xamarin.iOS.MaterialComponents installiert sein. Dieses wird jedoch automatisch installiert, wenn Sie ein Upgrade Ihres Xamarin.Forms-Pakets auf Version 4.0 vornehmen.
  • Für Android muss Ihr Projekt auf API 29 basieren, und die Supportbibliotheken müssen Version 28 verwenden. Zusätzlich muss das App-Design von einem der Material Components-Designs erben.

Es ist erwähnenswert, dass die Entwicklung von Visual wirklich gerade erst begonnen hat, sodass Entwickler mit Recht zahlreiche Updates erwarten können. Im Allgemeinen ist diese Eigenschaft eine äußerst nützliche Ergänzung, die Ihnen viel Zeit spart, wenn Sie plattformübergreifend identische Benutzeroberflächen erstellen müssen.

Verschiedene Verbesserungen

In Xamarin.Forms 4.0 können Sie nun eine Farbe für den Wartekreisel angeben, wenn Pull-to-Refresh aktiviert ist. Dies wird erreicht, indem die RefreshControlColor-Eigenschaft wie folgt zugewiesen wird:

<ListView RefreshControlColor="Green"/>

Darüber hinaus ist es in ListView möglich, die Scrollleisten auszublenden, ohne eigene Renderer zu schreiben, indem einfach die Eigenschaften HorizontalScrollBarVisibility und VerticalScrollBarVisibility zugewiesen werden:

<ListView HorizontalScrollBarVisibility="Always"
  VerticalScrollBarVisibility="Never"/>

Mögliche Werte sind „Always“ (immer sichtbar), „Never“ (nie sichtbar) und „Default“ (basierend auf der Standardeinstellung der Zielplattform).  Außerdem bietet das Editor-Steuerelement nun Unterstützung für die Textvorhersage (wie im Entry-Steuerelement). Sie können die IsTextPredictionEnabled-Eigenschaft einfach mit TRUE oder FALSE zuweisen:

<Editor IsTextPredictionEnabled="True" />

Mit Xamarin.Forms 4.0 erhält die SwitchCell-Ansicht die OnColor-Eigenschaft, genau wie die Switch-Ansicht in den vorherigen Hauptversionen. So können Sie nun bei der Verwendung von SwitchCell in Ihren Datenvorlagen eine andere Farbe für den aktiven Zustand festlegen:

<SwitchCell OnColor="Red"/>

Dies sind die aus praktischer Sicht interessantesten Verbesserungen, aber die vollständige Liste der Updates und behobenen Probleme ist auf der Seite mit den Versionshinweisen verfügbar und wird später aktualisiert, sobald Xamarin.Forms 4.0 schließlich für die Produktion freigegeben wird.

Ein kurzer Blick auf Xamarin.Forms in Visual Studio 2019

Microsoft hat kürzlich Visual Studio 2019 Vorschau 3 (bit.ly/2QcOK6z) veröffentlicht, das einen frühen Blick auf die Zukunft der nächsten Hauptversion von Visual Studio bietet, einschließlich Unterstützung für Xamarin.Forms 4.0. So ist beispielsweise eine neue Projektvorlage mit dem Namen „Shell“ nun im Dialogfeld „Neue plattformübergreifende App“ verfügbar (siehe Abbildung 10). Diese Vorlage generiert ein neues Projekt basierend auf der Shell-Funktion, wobei auf mehrere Ansichten im Shell-Objekt im XAML-Code der Hauptseite verwiesen wird.

Die neue Projektvorlage basierend auf der Shell
Abbildung 10: Die neue Projektvorlage basierend auf der Shell

Visual Studio 2019 stellt Xamarin.Forms auch einen neuen Eigenschaftenbereich zur Verfügung, der in Abbildung 11 gezeigt wird und der bereits für andere Entwicklungsplattformen verfügbar war. Er zeigt Eigenschaftswerte an, sobald Sie auf eine Ansicht in Ihrem XAML-Code oder in der Xamarin.Forms-Vorschau klicken.

Der neue Eigenschaftenbereich
Abbildung 11: Der neue Eigenschaftenbereich

Wenn Sie Eigenschaftswerte über den Eigenschaftenbereich ändern, wird der XAML-Code automatisch aktualisiert, um Ihre Änderungen zu berücksichtigen. Beachten Sie, dass für einige Typen spezifische Editoren zur Verfügung stehen, z.B. der Farb-Editor für Eigenschaften vom Typ Xamarin.Forms.Color.

Zusammenfassung

Wie bei den vorherigen Hauptversionen zeigt Xamarin.Forms 4.0, dass Microsoft enorme Investitionen tätigt, um die Entwicklungserfahrung nicht nur mit neuen Funktionen zu verbessern, sondern auch die vorhandenen Tools und die Codebasis immer zuverlässiger zu gestalten. Genau dies benötigen Entwickler in ihren realen Projekten. Es wird interessant zu sehen sein, welche weiteren Neuigkeiten auf der kommenden Microsoft Build-Konferenz vorstellt werden, die vom 6. bis 8. Mai in Seattle stattfindet.


Alessandro Del Sole *ist seit 2008 Microsoft MVP und Xamarin Certified Developer. Er ist Autor zahlreicher Bücher, eBooks, Videoanleitungen und Artikel zur .NET-Entwicklung mit Visual Studio. Del Sole arbeitet für Fresenius Medical Care als Senior Software Engineer und konzentriert sich auf die Entwicklung von .NET- und mobilen Apps mit Xamarin für den Gesundheitsbereich. Sie können ihm auf Twitter folgen: {3&gt;@progalex\<3}*.

Unser Dank gilt dem folgenden technischen Experten bei Microsoft für die Durchsicht dieses Artikels: Paul DiPietro