HanseVision Blog - Living Transformation. Updates zu Digitale Transformation, Digitale Kollaboration, New Work und modernen Arbeitswelten

Multiplattform-Frameworks Artikel 4 von 5: .NET MAUI

Geschrieben von Jeffrey Pluntke | 11.10.2021

.NET MAUI

Bei .NET Multi-platform APP UI (MAUI) handelt es sich um ein Framework, um Apps für verschiedene Plattformen zu entwickeln (Microsoft, 2021a). In der klassischen Entwicklung für verschiedene Plattformen muss für jede Plattform eine Codebasis unterhalten und plattformspezifische Entwickler angestellt werden. Im Kontrast dazu ermöglicht MAUI mit nur einer Codebasis und Entwicklern die C# können mehrere Plattformen zu bedienen. In diesem Artikel wird zu Beginn eine Einführung in das Framework gegeben. Darauf folgt die Beschreibung des Prozesses zum Installieren von MAUI. Im Anschluss wird ein erstellter Prototyp vorgestellt, der danach für Windows und Android gebuilded wird. Es folgt abschließend eine Beschreibung von mehreren Vor- und Nachteilen des Frameworks.

Dieser Artikel ist Teil einer Reihe von Artikeln, die verschiedene Frameworks für die Multiplattform-Entwicklung vorstellt:

Was ist .NET MAUI

Bei MAUI handelt es sich um ein Opensource Framework für die Multiplattform-Entwicklung (Microsoft, 2021a). Dabei ist MAUI der Nachfolger von Xamarin.Forms (Microsoft, 2021b). Eine Applikation wird primär in C# und XAML geschrieben und im Anschluss für verschiedene Plattformen, zum Beispiel Android oder Windows, in eine native App kompiliert. Während der Entwicklung kann ein über USB verbundenes Gerät oder ein Emulator verwendet werden, um den Code zu debuggen. Ergänzend dazu wird Hot Reload verwendet: Wenn sich der Code ändert, werden diese Änderungen ohne explizites speichern auf dem Endgerät wiedergegeben (Microsoft, 2021c).

HINWEIS: MAUI ist zum Zeitpunkt der Erstellung dieses Artikels nur in einer Preview-Version verfügbar. Daher läuft das Tooling nicht stabil und die Dokumentation ist kaum vorhanden. Entsprechend sollte MAUI noch nicht in der Produktion eingesetzt werden.

Beschreibung der View

Das UI in MAUI besteht aus einer Sammlung von bereitgestellten UI Komponenten. Diese können unter anderem in der Extensible Application Markup Language (XAML) oder nach dem Model-View-Update (MVU) Pattern zur Definition der GUI verwendet werden:

  • XAML: Das Interface wird via Markup (vergleichbar mit HTML) beschrieben. Ein Interface besteht dabei aus der XAML-Datei und einer C# Datei, die die Logik beinhaltet. Ein Beispiel für eine XAML-Datei ist in Abbildung 1 zu finden:
    <?xml version="1.0" encoding="utf-8" ?>  <ContentPage  xmlns="http://schemas.microsoft.com/dotnet/2021/maui"          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"          x:Class="Maui.Pages.HelpPage"          x:Name="helpPage"          Title="Melp me, Maui!">      <ContentPage.Content>          <StackLayout>              <Button                   Text="Start Animation"                   Clicked="AnimateImage"                   x:Name="ButtonForAnimation">                              </Button>              <Image                   Source="https://source.unsplash.com/random"                   WidthRequest="100"                   HeightRequest="100"                   HorizontalOptions="Start"                  x:Name="ImageToAnimate">              </Image>             </StackLayout>      </ContentPage.Content>  </ContentPage>

    Abbildung 1: Exemplarischer XAML-Code zur Beschreibung einer GUI.

  • MVU: Das Interface wird programmatisch in C# definiert. Die folgende Abbildung präsentiert ein Beispiel in C#:
    namespace Maui.Pages  {      public partial class HelpPage : ContentPage      {          public HelpPage()          {              var button = new Button              {                  Text = "Start Animation"              };                 button.Clicked += (object sender, EventArgs e) => StartAnimation();                 var image = new Image              {                  Source = "https://source.unsplash.com/random",                  HeightRequest = 100,                  WidthRequest = 100,                  HorizontalOptions = LayoutOptions.Start,              };                 Content = new StackLayout              {                  button,                  image,              };          }             ...      }  }

    Abbildung 2: Beschreibung einer GUI via C#

Styling

Damit das UI entsprechend den definierten Designs erstellt werden kann, bietet MAUI verschiedene Möglichkeiten an. Unter anderem werden die folgenden Möglichkeiten angeboten:

  • Via CSS: Eine Möglichkeit ist die Verwendung von CSS-Dateien, die im Ordner bestehenden Resources angelegt werden. Beispielsweise kann mit dem Button-Selektor ein Styling auf alle Buttons angewendet werden.
  • Als XAML-Attribute: Styles können XAML-Elementen als Attribute definiert werden. In der zuvor gezeigten Abbildung 1 werden entsprechende Definitionen, wie zum Beispiel die Dimensionen des Images präsentiert.
  • Als Parameter im Model View Update (MVU): Wenn MVU verwendet wird, können Styles als Parameter bei der Initialisierung von Elementen übergeben werden. Beispielsweise werden Parameter für die Dimensionen des zu erstellenden Images in der zuvor präsentierten Abbildung 2 übergeben.

Anforderungen

Um mit MAUI entwickeln zu können, wird die folgende Software benötigt:

  • Visual Studio 2022 Preview 4+ (Microsoft, 2021d)
    • Zusätzlich werden die folgenden Workloads benötigt:
      • NET and web development
      • Mobile Development with .NET
        • Unter Details wird .NET MAUI benötigt.
      • Universal Windows Platform development
    • Microsoft OpenJDK (Microsoft, 2021e)
    • Android SDK 31+, welches über Android Studio installiert werden kann (Android Studio, 2021)
    • Single-project MSIX Packaging Tools for VS 2022 (Visual Studio, 2021)

Nachdem die Software installiert wurde, sollten die Pfade zu den OpenJDK und dem Android SDK in den Android-Einstellungen von Visual Studio überprüft werden.

Um die Installation zu prüfen, kann das Tool dotnet-maui-check (Github, 2021) verwendet werden. Dieses Tool wird von einem Mitglied des MAUI Teams bereitgestellt und prüft die Umgebung. Falls Fehler gefunden werden, können diese behoben werden. Zum Installieren und Ausführen werden die folgenden Befehle verwendet:

# install dotnet-maui-check  $ dotnet tool install -g Redth.Net.Maui.Check  # run the tool  $ maui-check

Abbildung 3: Befehle zum Installieren und Ausführen von dotnet-maui-check.

Initialisierung des Prototypen

Nachdem die Installation erfolgreich war, wird nun endlich angefangen, MAUI zu verwenden. Mittels MAUI soll ein einfacher Prototyp mit drei Seiten erstellt werden. Dabei soll anhand jeder Seite ein unterschiedlicher Aspekt von MAUI präsentiert werden. Die folgenden Seiten werden erstellt:

  • Index: Diese Seite ist nicht nur der Einstieg in die App, sondern auch der Einstieg in MAUI. Dabei wird die Verwendung von XAML und Integration von Komponenten präsentiert. Gleichzeitig wird die Verwendung von CSS exemplarisch vorgestellt.
  • User: Diese Seite soll eine Liste von Usern sowie Controls zum Hinzufügen eines Users anbieten. Es wird das Styling und Hinzufügen von Click-Listenern in XAML präsentiert.
  • Help: Diese Seite soll exemplarisch die Animation eines Seitenelementes über die von MAUI zur Verfügung gestellten API thematisieren.

Letztendlich sieht das Ergebnis wie in der folgenden Abbildung aus:

Abbildung 4: Die Ansichten des erstellten Prototypen: Index (links), User (Mitte) und Help (rechts).

Um das Projekt zu erstellen, werden die folgenden Schritte durchgeführt:

  1. Visual Studio 2022 öffnen.
  2. Auf den Button zum Erstellen eines neuen Projektes klicken.
  3. Als Template .NET MAUI App auswählen.
  4. Einen Namen angeben und das Projekt erstellen.

Damit die UI des erstellten Projektes auch gedebuggt werden kann, wird ein Emulator für ein Android-Gerät eingerichtet und als Startgerät ausgewählt. Ein Dialog zum Erstellen und Auswählen des Emulator kann in einem Dropdown der oberen Toolbar neben dem Start-Button gefunden werden. Beim Einrichten des Emulators kann es vorkommen, dass Virtualisierung benötigt wird. Entsprechend sollte diese im Betriebssystem aktiviert werden. Dies bedeutet ebenfalls, dass für die Entwicklung innerhalb einer VM nested virtualization benötigt wird. Wenn ein Emulator eingerichtet wurde, kann dieser als Startgerät verwendet werden. Die Toolbar sieht nun wie folgt aus:

Abbildung 5: Toolbar mit einem ausgewählten und eingerichteten Pixel 5 Emulatoren.

Erstellung der Index-Seite

Zur Erstellung der Index-Seite wird eine neue ContentPage hinzugefügt. Beim Hinzufügen ergeben sich jedoch die folgenden Probleme:

  • Die verwendeten Namespaces in der XAML- und C# Datei verwenden noch nicht die neuen MAUI-Namespaces. Daher müssen diese ausgetauscht werden.
  • Im Contructor der C#-Datei wird angemerkt, dass die Methode InitializeComponent im Kontext nicht verfügbar ist. Um diesen Fehler zu beheben können die folgenden Schritte durchgeführt werden (Stackoverflow, 2021):
    • In der .csproj-Datei Referenzen auf die neu erstellte Seite löschen
    • In der C#-Datei den Methodenaufruf entfernen
    • Das Projekt rebuilden
    • Den entfernten Methodenaufruf wieder einfügen

Da die Seite nun verwendet werden kann, wird der Aufbau in XAML wie folgt definiert:

<?xml version="1.0" encoding="utf-8" ?>  <ContentPage          xmlns="http://schemas.microsoft.com/dotnet/2021/maui"          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"          x:Class="Maui.Pages.IndexPage"          xmlns:v="clr-namespace:Maui.Components"          x:Name="indexPage"          Title="Index Page, Maui!">      <ContentPage.Content>          <!-- Menu -->          <v:NavBar              x:Name="NavBar"              Grid.Row="{OnIdiom Phone=1, Default=0}"/>      </ContentPage.Content>  </ContentPage>

Abbildung 6: XAML der index-Seite.

Dabei erhält die Seite einen über die Attribute einen Titel und es wird die zugehörige Klasse definiert. Gleichzeitig wird in den Content der Seite eine NavBar mit v:NavBar integriert. Dabei handelt es sich um das Einbetten einer Komponente NavBar in den Content. Da die NavBar aktuell noch nicht existiert, werden entsprechende Fehler geworfen. Daher wird nun die Komponente erstellt.

Navbar

Für die Navbar wird wieder eine XAML und eine C# Datei erstellt. Die XAML-Datei beinhaltet dabei ein FlexLayout als Container für zwei Buttons. Die Buttons erhalten jeweils Click-Listener zum Öffnen der entsprechenden Seiten. Abbildung 7 zeigt die XAML-Datei.

<FlexLayout      xmlns="http://schemas.microsoft.com/dotnet/2021/maui"      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"      x:Class="Maui.Components.NavBar"      Direction="Row"      JustifyContent="SpaceEvenly"      BackgroundColor="Background_Mid"  >      <Button          x:Name="OpenUserPageButton"          Text="User"          Clicked="OpenUserPage"/>      <Button          x:Name="OpenHelpPageButton"          Text="Help"          Clicked="OpenHelpPage"/>  </FlexLayout>

Abbildung 7: Die Definition der UI für die Navbar in er Navbar.xaml Datei.

In der dazugehörigen C#-Datei werden die Click-Listener definiert. Dabei erwarten diese als Parameter einen Sender und ein Event. Beim Ausführen der Listener wird die gewünschte Seite neu instanziiert und in die App gepusht. Die Abbildung 8 präsentiert den Code der Click-Listener.

using System;  using Maui.Pages;  using Microsoft.Maui.Controls;     namespace Maui.Components  {         public partial class NavBar      {          public NavBar()          {              InitializeComponent();          }             private void OpenHelpPage(object sender, EventArgs e)          {              (Application.Current.MainPage as NavigationPage).PushAsync(new HelpPage());          }             private void OpenUserPage(object sender, EventArgs e)          {              (Application.Current.MainPage as NavigationPage).PushAsync(new UserPage());          }      }  }

Abbildung 8: C#-Code der NavBar mit dem Code der Click-Listener.

Damit die Buttons sich vom Rest der App abheben, werden diese via CSS gestylt. Dabei wird die Hintergrundfarbe sowie die Höhe gesetzt. Unter ./Resources/Styles wird die Datei styles.css erstellt und der folgende Code integriert:

button{      height: 50;      background-color: deeppink;  }  

Abbildung 9: CSS Code zum Stylen der Buttons.

Jedoch wird aktuell diese Datei noch nicht verwendet. Daher wird im folgenden Abschnitt die Integration der CSS-Datei sowie das Setzen der Index-Seite als Startseite beschrieben.

Integration in die App

Damit die erstellte Index-Seite sowie die CSS-Datei in die App integriert werden, müssen Konfigurationen in den generierten App-Dateien vorgenommen werden. Für die Integration der CSS-Datei muss die XAML-Datei der App angepasst werden. Die angepasste Datei wird in der folgenden Abbildung präsentiert:

<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"               xmlns:windows="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.WindowsSpecific;assembly=Microsoft.Maui.Controls"               xmlns:local="clr-namespace:Maui"               x:Class="Maui.App"               windows:Application.ImageDirectory="Assets">      <Application.Resources>          <ResourceDictionary>                 <Color x:Key="PrimaryColor">#512bdf</Color>              <Color x:Key="SecondaryColor">White</Color>              <Color x:Key="SuccessColor">#9FF57F</Color>                 <Style TargetType="Label">                  <Setter Property="TextColor" Value="DarkSlateGray" />                  <Setter Property="FontFamily" Value="OpenSansRegular" />              </Style>                 <Style TargetType="Button">                  <Setter Property="TextColor" Value="{DynamicResource SecondaryColor}" />                  <Setter Property="FontFamily" Value="OpenSansRegular" />                  <Setter Property="BackgroundColor" Value="{DynamicResource PrimaryColor}" />                  <Setter Property="Padding" Value="14,10" />              </Style>                 <StyleSheet Source="/Resources/Styles/styles.css" />             </ResourceDictionary>      </Application.Resources>  </Application>

Abbildung 10: XAML-Datei der App-Instanz.

Am Anfang der XAML-Datei werden globale Variablen für Farben definiert. Es wurde eine Variable namens SuccessColor hinzugefügt. Um diese Farben verwenden zu können, müssen die Variablen bei geeigneten Eigenschaften verwendet werden. Ein Beispiel ist in den darauffolgenden autogenerierten Style-Tags für Buttons zu sehen. Dort wird die Schriftfarbe mit einer zuvor definierten Variable namens SecondaryColor gesetzt, indem auf ein Wert in einem ResourceDictionary verwiesen wird. Abschießend wird die zuvor erstellte CSS-Datei über den StyleSheet-Tag der App bekannt gemacht, indem der Pfad zur Datei angegeben wird.

Zum Schluss wird die Index-Seite der App hinzugefügt, indem diese als Landingpage integriert wird. Dafür wird in der CreateWindow-Methode der App.cs Datei bei der Erstellung des Windows eine neu instanziierte Index-Seite übergeben. Der Code ist in der folgenden Abbildung zu sehen:

using Microsoft.Maui;  using Microsoft.Maui.Controls;  using Application = Microsoft.Maui.Controls.Application;  using Maui.Pages;     namespace Maui  {  	public partial class App : Application  	{  		public App()  		{  			InitializeComponent();  		}     		protected override Window CreateWindow(IActivationState activationState) =>  			new Window(new NavigationPage(new IndexPage())) { Title = "Index Maui" };  	}  }

Abbildung 11: Code zur Integration der Index-Seite in der App.cs.

Erstellung der User-Seite

Die User-Seite besteht aus drei Teilen: Eine XAML- und eine C#-Datei, die zusammen die Seite beschreiben, sowie ein ViewModel, welches die Daten für User hält. In den folgenden Abschnitten wird als erstes das ViewModel und im Anschluss der Aufbau der Seite selbst beschrieben.

Das ViewModel

Das ViewModel soll eine ObserverableCollection von Usern halten und bei jeder Modifikation seinen Konsumenten über diese in Kenntnis setzt. Zu Beginn wird ein Zufallsgenerator instanziiert. Es folgt die Definition einer Property namens Users. Bei der Verwendung des Setters wird das private Feld _users gesetzt und es wird über die Methode OnPropertyChanged ein Event ausgestoßen, welches mitteilt, dass Modifikationen passiert sind. Der Getter gibt das private _users Feld zurück. Im Constructor wird das Feld _users instanziiert und es werden drei Nutzer hinzugefügt. Für das Hinzufügen der Nutzer wird AddUser verwendet. Diese Methode erstellt einen User mit einer zufallsgenerierten ID.

using System;  using System.Collections.ObjectModel;  using System.ComponentModel;  using System.Runtime.CompilerServices;  using Maui.Models;     namespace Maui.ViewModel  {      internal class UsersViewModel : INotifyPropertyChanged      {          private Random RandomGenerator = new Random();             private ObservableCollection<UserDto> _users;          public ObservableCollection<UserDto> Users {               get {                   return _users;              }               set {                   _users = value;                  OnPropertyChanged();              }           }             public UsersViewModel()          {              _users = new ObservableCollection<UserDto>();                   AddUser("Udo");              AddUser("Hans");              AddUser("Peter");          }             public void AddUser(string name)          {              Users.Add(                  new UserDto                  {                      Name = name,                      Id = (int)RandomGenerator.NextInt64(0, 100000000)                  });          }             public event PropertyChangedEventHandler PropertyChanged;          protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)          {              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));          }      }  }

Abbildung 12: Das ViewModel für User.

Der Aufbau der Seite

Im C#-Teil der Seite wird ein privates Feld _usersViewModel definiert und instanziiert. Es folgt der Constuctor, der als Erstes die Seite initialisiert und darauffolgend das Feld _usersViewModel mit dem BindingContext der Seite assoziiert. Zum Schluss wird eine Methode AddNewUser definiert, die dem ViewModel einen neuen User hinzufügt und das Eingabefeld leert. Zu beachten ist, dass auf das Eingabefeld über den im XAML-Template definierten Namen zugegriffen wird.

using Microsoft.Maui.Controls;  using System;  using Maui.ViewModel;     namespace Maui.Pages  {      public partial class UserPage : ContentPage      {          private readonly UsersViewModel _usersViewModel = new();             public UserPage()          {              InitializeComponent();                       BindingContext = _usersViewModel;             }             public void AddNewUser(object sender, EventArgs e)          {              _usersViewModel.AddUser(textInput.Text);              textInput.Text = "";          }      }  }

Abbidung 13: C#-Teil der User-Seite.

Nun wird die GUI in der XAML-Datei der Seite definiert. Dabei wird als Erstes ein Template für die User erstellt. Im Anschluss wird in einem StackLayout das Form und die Liste integriert. Die Abbildung 14 zeigt den beschriebenen grundlegenden Aufbau. Die angesprochenen Teile werden in den folgenden Abschnitten beschrieben.

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"               xmlns:m="clr-namespace:Maui.Models"               x:Class="Maui.Pages.UserPage"               x:Name="userPage"               Title="Maui, play with Users"               BackgroundColor="{DynamicResource SecondaryColor}">      <Grid>          <ScrollView>                 <ScrollView.Resources>                  <!-- define Template -->              </ScrollView.Resources>                 <StackLayout>                  <!-- form -->                                    <!-- list -->              </StackLayout>              </ScrollView>      </Grid>  </ContentPage>

Abbildung 14: Aufbau der XAML-Datei der Ansicht für User.

Template

Beim Template handelt es sich um die Repräsentation eines Users in einer Zeile. Dabei wird ein User mit einem Bild und seinem Namen dargestellt. Der Name wird einem Label als Text hinzugefügt. Das XAML-Attribut Text des Labels wird mit der Property Name des korrespondierenden Objekts belegt. Das Template selbst erhält den Key UsersListTemplate. Dieser Key wird später verwendet, um das Template für das Binding referenzieren zu können. Der XAML-Code ist in der folgenden Abbildung zu finden:

<DataTemplate x:Key="UsersListTemplate">      <Frame>          <Grid Padding="4" RowDefinitions="42,40,*">              <Image                   Source="https://source.unsplash.com/random"                   WidthRequest="50"                   HeightRequest="50"                   HorizontalOptions="Start"                   VerticalOptions="Center">                                              </Image>              <Label                   Text="{Binding Name}"                   HorizontalOptions="Center"                   VerticalOptions="Center">                                              </Label>          </Grid>      </Frame>  </DataTemplate>

Abbildung 15: Definition des Templates eines Listeneintrages in XAML.

Form

Das Form soll es ermöglichen, dass neue User hinzugefügt werden können. Dafür wird ein Entry und ein ImageButton definiert. Der Entry dient als Feld für die Texteingabe und wird mit dem Namen textInput belegt. Über diesen Namen kann das Feld im C#-Teil referenziert werden. Wiederum erhält der Button einen Click-Listener, der beim Klicken einen neuen Nutzer hinzufügt. Gleichzeitig wird die Hintergrundfarbe des Buttons mit der global definierten Hintergrundfarbe SuccessColor belegt. Der XAML-Code ist in der folgenden Abbildung zu finden:

<HorizontalStackLayout      VerticalOptions="Center"      Spacing="18"      Padding="{OnIdiom Phone='18', Default='25'}"      >      <Entry           x:Name="textInput"          HorizontalOptions="StartAndExpand"           WidthRequest="250"           Placeholder="Add User"           PlaceholderColor="DimGrey"      >                              </Entry>      <ImageButton           Clicked="AddNewUser"            BackgroundColor="{DynamicResource SuccessColor}"          Source="add_icon.png"           VerticalOptions="Center"           HorizontalOptions="Center"          >      </ImageButton>  </HorizontalStackLayout>

Abbildung 16: Das Form zum hinzufügen eines User im XAML.

Liste

Das definierte VerticalStackLayout soll die Liste von Usern anzeigen. Dabei wird für jeden User das zuvor definierte Template verwendet. Damit dies passiert, wird das Template im Binding ItemTemplate referenziert. Ebenfalls wird vom BindingContext die Eigenschaft Users als Datenquelle mit ItemsSource assoziiert. Wenn sich die Datenquelle ändert, wird die Liste neu gerendert. Der beschriebene XAML-Teil ist in der folgenden Abbildung zu finden:

<VerticalStackLayout      BindableLayout.ItemsSource="{Binding Users}"      BindableLayout.ItemTemplate="{StaticResource UsersListTemplate}"      >      <Grid          HeightRequest="132"          WidthRequest="132"          HorizontalOptions="Start"          Margin="{OnIdiom Phone=15,Default=25}">      </Grid>  </VerticalStackLayout>

Abbildung 17: Die Darstellung der Liste in XAML.

Erstellung der Hilfe-Seite

Die Hilfe-Seite besteht aus einem Button und einem Image. Dem Button wird beim Attribut Clicked die auszuführende Funktion für die Animation übergeben. Ursprünglich sollte die Animation ausgelöst werden, wenn die Seite geladen ist. Da es jedoch zum Zeitpunkt der Erstellung des Prototypen noch keine Hooks für Seiten gab, wurde ein Button zum Auslösen der Animation integriert. Das Image erhält neben seiner Source auch einen Namen, welcher für die Animation als Referenz auf das Element verwendet wird. Die folgende Abbildung zeigt den XAML-Aufbau:

<?xml version="1.0" encoding="utf-8" ?>  <ContentPage  xmlns="http://schemas.microsoft.com/dotnet/2021/maui"          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"          x:Class="Maui.Pages.HelpPage"          x:Name="helpPage"          Title="Melp me, Maui!">      <ContentPage.Content>          <StackLayout>              <Button                   Text="Start Animation"                   Clicked="AnimateImage"                   x:Name="ButtonForAnimation">                              </Button>              <Image                   Source="https://source.unsplash.com/random"                   WidthRequest="100"                   HeightRequest="100"                   HorizontalOptions="Start"                  x:Name="ImageToAnimate">              </Image>             </StackLayout>      </ContentPage.Content>  </ContentPage>

Abbildung 18: Aufbau der Hilfe-Seite in XAML.

Die zugehörige C#-Datei enthält die Methode zum Ausführen der Animation sowie die Animation selbst. Für die Animationen wird die entsprechende API von MAUI verwendet. Die folgende Abbildung präsentiert die C#-Datei:

using Microsoft.Maui.Controls;  using System;  using System.Threading.Tasks;     namespace Maui.Pages  {      public partial class HelpPage : ContentPage      {          public HelpPage()          {              InitializeComponent();          }             private void AnimateImage(object sender, EventArgs e)          {              StartAnimation();          }             private async Task StartAnimation()          {              // parallel              await Task.WhenAll(ImageToAnimate.RelScaleTo(2, 2000), ImageToAnimate.TranslateTo(0, 100, 2000));              // sequential              await ImageToAnimate.RotateXTo(360, 3000);              await ImageToAnimate.RotateXTo(0, 1);              // parallel              await Task.WhenAll(ImageToAnimate.TranslateTo(0, 0, 750), ImageToAnimate.ScaleTo(1, 500));          }      }  }  

Abbildung 19: Der C#-Teil der Hilfe-Seite inklusive der Animationen.

Die Animation wird in der Methode StartAnimation definiert und umfasst zwei parallele und zwei sequenzielle Animationen. Die Animationen werden auf dem definierten Image ausgeführt. Dafür wird die im XAML erstellte Referenz des Bildes (ImageToAnimate) verwendet. Zu Beginn wird das Bild innerhalb von zwei Sekunden relativ zu sich selbst skaliert und auf der Y-Achse verschoben. Damit diese beiden Animationen parallel ausgeführt werden können, werden diese einem Task.WhenAll übergeben, wobei auf dieses im Anschluss gewartet wird. Dies ist möglich, da die Animationen selbst asynchron sind. Im Anschluss werden sequenziell Rotationen verwendet. Als Erstes wird eine Rotation um 360 Grad getätigt. Es folgt eine Rotation auf 0 Grad. Die zweite Rotation wird benötigt, um die Rotation wieder ausführen zu können, da bei erneuter Rotation der Start- und Zielwinkel identisch ist und deshalb keine erneute Rotation ausgeführt wird. Im Anschluss wird das Bild wieder in seinen Ursprungszustand zurückgesetzt. Dabei ist interessant, dass die Animationen unterschiedlich lange andauern können. Das Ergebnis ist in der folgenden Abbildung zu sehen:


Abbildung 20: Die Animation der Hilfe-Seite

Builden für Android

Damit für Android gebuildet werden kann, muss in der .csproj-Datei bei den TargetFrameworks Android an erster Stelle stehen. Die Konfiguration sieht wie folgt aus:

<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst;</TargetFrameworks>

Abbildung 21: Konfiguration des Projektes für Android.

Nun wird eine Release-Konfiguration ausgewählt. Wenn dies geschehen ist, wird ein Rechtsklick auf das Projekt gemacht und die Option Archive ausgewählt. Wenn keine Fehler auftreten, wird ein Android App Bundle (AAB) ausgegeben.

Builden für Windows

Für das Builden einer Exe-Datei wird in der .csproj-Datei die Zeile der TargetFrameworks mit der folgenden ersetzt:

<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) and '$(MSBuildRuntimeType)' == 'Full'">$(TargetFrameworks);net6.0-windows10.0.19041</TargetFrameworks>

Abbildung 22: Konfiguration der Projektdatei für Windows.

Im Anschluss wird ein Rechtsklick auf das Projekt getätigt und die Option Publish ausgewählt. Falls noch nicht vorhanden, wird nun erst ein Publish-Profil angelegt. Im Anschluss wird nur auf Publish geklickt und es werden die Binaries mit einer Exe-Datei im Zielordner ausgegeben.

Vor- und Nachteile

Bei MAUI handelt es sich um eine junge Technologie, die nur als Preview zur Verfügung steht. Deshalb sind viele Dinge noch unklar und nicht ausgereift. Entsprechend sind nur generelle Vor- und Nachteile, die auf den gesammelten Erfahrungen basieren, ableitbar. Stattdessen werden Punkte aufgelistet, die auf den Erfahrungen basieren, die während der Entwicklung des Prototypen gesammelt wurden. Zugleich können die gelisteten Punkte sich jederzeit ändern, da es sich nur um eine Preview-Version handelte.

Vorteile

  • Es wird eine Codebasis geschrieben, die in native Apps für verschiedene Plattformen kompiliert werden können.
  • Es können verschiedene Arten zur Beschreibung des Interfaces (z. B. MVU oder XAML) verwendet werden.

Nachteile

  • Das Tooling ist unausgereift: Zum einem funktioniert der Hot Reload nur in der Hälfte der Fälle und zum anderen stürzt Visual Studio 2022 oder Emulator regelmäßig ab. Zusätzlich müssen beim Hinzufügen einer Seite umständliche Hacks vorgenommen werden, da die benötigten Konfigurationen nicht selbstständig von MAUI vorgenommen werden.
  • Die Dokumentation ist kaum vorhanden: Die Dokumentation stellt nur die Idee hinter MAUI vor. Daher wurde meistens die Xamarin-Dokumentation als Hilfe verwendet, wobei diese oft nicht 1:1 anwendbar ist.
  • Der Set-up-Prozess, insbesondere eines Emulators, kann aufwendig sein. Zusätzlich werden teilweise irritierende und sinnlose Fehler/Hinweise zu korrekten Einstellungen ausgegeben. Das größte Problem mit diesen Fehlern/Hinweisen ist, dass diese Verwirrung stiften, da die eigentlichen Ursachen an anderen Stellen verborgen sind.

Fazit

MAUI ist eine junge Technologie, die es erlaubt, mit einer Codebasis mehrere Plattformen zu bedienen. Dabei kommen Technologien wie C# und XAML zum Einsatz. Da es sich um eine junge Technologie, die nur in einer Preview-Version verfügbar ist, handelt, ist die Dokumentation spärlich und das Tooling noch unausgereift. Stattdessen muss die Dokumentation des Vorgängers (Xamarin.Forms) als Ersatz herhalten, obwohl diese nicht 1:1 übernommen werden kann. Um die getätigten Änderungen während der Entwicklung zu testen, können via USB verbundene oder emulierte Geräte verwendet werden. Im Anschluss kann die entwickelte App gebuildet werden. Als Ziele stehen zur Auswahl die mobilen Systeme Android und iOS sowie die Desktopsysteme macOS und Windows. Dabei wird eine App über wenige Klicks in Visual Studio gebuildet. Jedoch ist zu beachten, dass es sich bei MAUI um eine neue Technologie handelt, die noch nicht in der Produktion verwendet werden sollte.

Referenzen

Android Studio (2021). https://developer.android.com/studio/. (Stand: 11.10.2021).

Github (2021). https://github.com/Redth/dotnet-maui-check. (Stand: 09.09.2021).

Microsoft (2021a). https://docs.microsoft.com/en-us/dotnet/maui/. (Stand: 11.10.2021).

Microsoft (2021b). https://dotnet.microsoft.com/apps/xamarin/xamarin-forms. (Stand: 11.10.2021).

Microsoft (2021c, Februar 3.). https://devblogs.microsoft.com/xamarin/the-new-net-multi-platform-app-ui-maui/. (Stand: 11.10.2021).

Microsoft (2021d). https://visualstudio.microsoft.com/de/vs/preview/. (Stand: 11.10.2021).

Microsoft (2021e). https://www.microsoft.com/openjdk. (Stand: 11.10.2021).

Stackoverflow (2021). https://stackoverflow.com/questions/68639893/maui-project-cannot-add-a-new-page. (Stand: 11.10.2021).

Visual Studio (2021). https://marketplace.visualstudio.com/items?itemName=ProjectReunion.MicrosoftSingleProjectMSIXPackagingToolsDev17. (Stand: 21.09.2021).