
Warum von Xamarin zu .NET MAUI migrieren?
Mit .NET MAUI modernisiert Microsoft Xamarin Forms zu einem besseren plattformübergreifenden UI-Framework, das nicht nur architektonische und Implementierungsänderungen mit sich bringt, sondern auch den Wechsel zu anderen Zielplattformen wie Android, iOS, Mac OS (mit Mac Catalyst) und Windows ermöglicht. Volle Unterstützung für Samsungs Tizen wird ebenfalls geboten.
Sind Xamarin und Xamarin Forms vom Aussterben bedroht? Wenn Sie Xamarin nur als einen Produktnamen betrachten, dann ja. Xamarin als Framework wird als Teil von .NET MAUI und .NET für Android/ iOS unter neuen Namen weiterleben.
Ist es möglich, Xamarin in MAUI zu verwenden?
Die kurze Antwort ist nein. Die lange Antwort lautet, dass das MAUI-Team vieles von dem, was Xamarin-Entwickler an dem Framework kennen und lieben, in .NET MAUI und .NET für Android/ iOS integriert hat. Der Kompatibilitätsmodus in .NET MAUI ermöglicht es Ihnen, die meisten Ihrer benutzerdefinierten Xamarin Forms-Renderer und XAML-Layouts weiterhin zu verwenden. Eine Migration ist jedoch unvermeidlich, da sich viele kleine Dinge wie Namespaces zusammen mit der Projektstruktur geändert haben.
Wie migriert oder aktualisiert man Xamarin auf .NET MAUI?
Mit den folgenden 7 Schritten konnten wir unsere .NET MAUI-Projekte erfolgreich von Xamarin.Forms wegmigrieren:
Bevor Sie beginnen, sollten Sie einige Voraussetzungen erfüllen:
- Ich empfehle Ihnen, Ihre Xamarin.Forms-App auf mindestens Xamarin.Forms 5.0 zu aktualisieren, da diese Version MAUI am ähnlichsten ist.
- Android 5.0 (API 21) oder höher
- iOS 10 oder höher
- Das vollständige Umgebungssetup für .NET MAUI einschließlich aller erforderlichen Workloads muss installiert sein
Alle Projekte zum .NET SDK-Stil konvertieren
Microsoft hat die Struktur der Projekt- und Lösungsdatei mit .NET Core geändert und setzt diese fort. Diese Änderung wurde für Xamarin-Projekte noch nicht übernommen und wird nun mit .NET für Android und .NET für iOS sowie für .NET MAUI nachgeholt. Um Ihre Projektdatei zu ändern, öffnen Sie die csproj-Datei des Xamarin.Forms-Projekts und passen Sie sie entsprechend dem folgenden Beispiel an. Zum besseren Verständnis habe ich die wichtigsten Einträge mit Kommentaren versehen.
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Specify which platforms should be supported in your app -->
<TargetFrameworks>net7.0-ios;net7.0-android</TargetFrameworks>
<!-- Distinguishes .NET for Android or iOS from a MAUI project -->
<UseMaui>True</UseMaui>
<OutputType>Library</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Specify which version of a platform should be supported in your app -->
<SupportedOSPlatformVersion Condition="'$(TargetFramework)' == 'net7.0-ios'">15.4</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(TargetFramework)' == 'net7.0-android'">31.0</SupportedOSPlatformVersion>
<!-- Required for C# Hot Reload -->
<UseInterpreter Condition="'$(Configuration)' == 'Debug'">True</UseInterpreter>
</PropertyGroup>
<ItemGroup>
<MauiFont Include="Resources\*" />
</ItemGroup>
<ItemGroup>
<!-- If you used CommunityToolkit -->
<PackageReference Include="CommunityToolkit.Maui" Version="1.3.0" />
<!-- Add NuGet-references of your old project file here -->
</ItemGroup>
</Project>
Wenn Sie zu Beginn der Migration nicht komplett auf die neue „Einzelprojekt“-Struktur umsteigen wollen, können Sie die bestehenden Android- und iOS-Projekte beibehalten. Allerdings müssen diese Projekte dann auch auf den SDK-Stil umgestellt werden. Die Struktur ist die gleiche wie oben mit einer kleinen Anpassung - der OutputType-Wert ändert sich dann von Library zu Exe.
NuGet-Pakete aktualisieren
Wie zuvor beschrieben, müssen die NuGet-Referenzen hinzugefügt werden. Die Verweise auf Xamarin.Forms und Xamarin.Essentials werden nicht mehr benötigt.
Da nun alle Paketreferenzen in einer Projektdatei zusammengefasst sind, muss es eine Möglichkeit geben, sie je nach Plattform zu unterscheiden. Dazu fügen Sie der ItemGroup einfach eine Bedingung für jede Plattform hinzu. Am Beispiel des Google PlayService für Android sieht dies wie folgt aus:
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
<PackageReference Include="Xamarin.GooglePlayServices.Maps" Version="118.0.2" />
</ItemGroup>
Meiner Erfahrung nach reicht es in der Regel aus, für verwendete NuGet-Pakete auf neuere Versionen zu wechseln. Problematisch sind nur sehr alte Pakete, für die keine neuen Versionen mehr verfügbar sind. In diesem Fall hilft es meist, nach geeigneten Alternativen zu suchen oder, wenn es sich um ein Open-Source-Projekt handelt, die Änderung selbst vorzunehmen.
Ein Wort zu Xamarin.Essentials und Xamarin.CommunityToolkit. Während Xamarin.CommunityToolkit durch CommunityToolkit.Maui ersetzt wird, wird Xamarin.Essentials nicht mehr unterstützt. Das Ersetzen von Xamarin.CommunityToolkit ist ein wichtiger Schritt im Migrationsprozess, da er sicherstellt, dass die App weiterhin die Erweiterungen des Toolkits verwenden kann. Um das CommunityToolkit in MAUI zu verwenden, muss die Methode UseMauiCommunityToolkit im MauiApp-Builder hinzugefügt werden. Mehr dazu später im folgenden Abschnitt.
Während wir in Xamarin.Forms plattformspezifische Projekte hatten, wurde die App mit dem plattformspezifischen Code über die Methode Xamarin.Forms.Init gestartet. In .NET MAUI gibt es einen einzigen plattformübergreifenden App-Einstiegspunkt mit MauiProgram.cs. Über diesen statischen Einstiegspunkt wird auf jeder unterstützten Plattform eine MauiApp-Instanz erstellt und zurückgegeben. Wir müssen also eine neue Datei zum .NET MAUI-Projekt (oder dem alten Xamarin Forms-Projekt) hinzufügen und sie MauiProgram.cs nennen. .NET MAUI verwendet das bereits aus .NET Core bekannte Builder-Prinzip, was zu der untenstehenden Struktur von MauiProgram.cs führt:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
return builder.Build();
}
}
Android-spezifische Anwendungsänderungen
Damit .NET MAUI auf Android funktioniert, müssen noch drei grundlegende Änderungen am alten Xamarin Android-Projekt vorgenommen werden.
- Aktualisieren Sie die AndroidManifest.xml, indem Sie die android:targetSdkVersion auf 31 ändern.
- Passen Sie die MainActivity so an, dass sie nun von MauiAppCompatActivity abgeleitet ist. Entfernen Sie die Methode
OnRequestPermissionsResult
und löschen Sie den Aufruf der Methode LoadApplication
. - MAUI benötigt eine Android-Anwendungsdatei, die von MauiApplication abgeleitet ist und CreateMauiApp übersteuert. Wenn Ihr Projekt noch keine Anwendungsdatei hat, erstellen Sie eine neue Klasse und nennen Sie sie MainApplication. Die genaue Struktur finden Sie im Bitbucket Repository: MAUI-Migration.
iOS-spezifische Änderungen an der Anwendung
Einige Änderungen müssen auch im iOS-Projekt vorgenommen werden.
- Aktualisieren Sie die MinimumOSVersion in Ihrer Info.plist auf 15.2.
- Passen Sie Ihr AppDelegate so an, dass es sich von MauiUIApplicationDelegate ableitet.
- In Ihrem AppDelegate müssen wir auch CreateMauiApp außer Kraft setzen.
- Entfernen Sie die FinishedLaunching Methode
.NET MAUI verwendet, wie Xamarin.Forms, ebenfalls XAML-Layouts. Sie können also Ihre bestehenden XAML-Layouts mit .NET MAUI weiterverwenden. Dazu müssen Sie die XML-Namespaces wie folgt ersetzen:
xmlns=„http://xamarin.com/schemas/2014/forms“
wird zu xmlns=„http://schemas.microsoft.com/dotnet/2021/maui“
.- Aus
using Xamarin.Forms
wird entweder using Microsoft.Maui
oder using Microsoft.Maui.Controls
, je nach Anwendungsfall. - Aus
Xamarin.Forms.Xaml
wird Microsoft.Maui.Controls.Xaml
.
Aus Performance-Gründen wurde in MAUI das Horizontal- und VerticalStackLayout eingeführt. Es ersetzt das oft verwendete StackLayout. Sie sollten also auch hier Zeit investieren und Ihre Layouts dafür optimieren. Bitte werfen Sie einen Blick in die Microsoft-Dokumentation für weitere Informationen.
Es gibt auch andere Bereiche, in denen der Namensraum angepasst werden muss. Hier sind einige bekannte API-Änderungen, die Sie während der Migration sehen könnten:
Colors
wurde nach Microsoft.Maui.Graphics
verschoben.Shapes
wurde nach Microsoft.Maui.Controls
verschoben.BorderColor
für Frames existiert nicht in MAUIIcon
für ToolbarItems wird zu IconImageSource
.Image
für Buttons wird zu ImageSource
- Die
ForegroundColor
für Span existiert nicht in MAUI
Sobald Sie mit den Schritten fertig sind, können Sie die Lösung in Visual Studio oder Visual Studio für Mac starten. Es ist sehr wahrscheinlich, dass weitere projektspezifische Fehler auftreten, z. B. durch API-Änderungen aufgrund neuerer NuGet-Paketversionen oder Namensraumänderungen, die Sie dann Schritt für Schritt beheben müssen.
Typischerweise gibt es Meldungen, die sich auf die AssemblyInfo.cs beziehen. Diese können Sie entfernen, da die meisten dieser Eigenschaften jetzt in der csproj sind. Wenn Sie mehr darüber erfahren möchten, wie Sie diese Eigenschaften einstellen, empfehle ich Ihnen, equivalent-to-assemblyinfo-in-dotnet-core-csproj auf Stackoverflow zu lesen.
Je nach Komplexität und Anzahl der Fehler ist es in manchen Fällen am einfachsten, ein neues MAUI-Projekt zu erstellen und dann Layouts, Dienste und NuGet-Referenzen hinzuzufügen. Dann, wenn Ihr Projekt startet, können Sie beginnen, Ihren Code Stück für Stück zu kopieren, um die Fehlerquelle besser zu lokalisieren.
Wir hier bei Cayas Software kennen kein Xamarin Forms-Projekt, in dem nicht mindestens ein Custom Renderer erstellt werden musste. Je nachdem, wie viele es in Ihrem Projekt gibt, lohnt es sich, diese gleich in die neue Handler-Struktur zu konvertieren. Wenn es doch zu viele sind, können Sie Ihre benutzerdefinierten Renderer weiter verwenden, indem Sie alles, was mit Xamarin.Forms.*
zu tun hat, auf Microsoft.Maui.*
aktualisieren und die ExportRenderer-Direktiven entfernen, da sie nicht mehr benötigt werden. Danach müssen Sie noch den Kompatibilitätsmodus in MauiProgram.cs über den Builder mit UseMauiCompatibility()
aktivieren.
// shortened
var builder = MauiApp.CreateBuilder();
.UseMauiCompatibility()
.ConfigureMauiHandlers((handlers) =>
{
handlers.AddCompatibilityRenderer(typeof("Your view"),typeof("Your renderer"));
});
Ich würde jedoch empfehlen, den benutzerdefinierten Handler zu verwenden, da er eine bessere Leistung und Erweiterbarkeit bietet. In unserem Artikel Erstellen eines .NET MAUI-Maps-Steuerelements zeigen wir, wie Sie einen benutzerdefinierten Handler erstellen können.
Dependency-Injection-Änderungen in .NET MAUI
In .NET MAUI ist es jetzt viel einfacher, Dependency Injection durchzuführen. MAUI verfügt bereits über einen Container, in dem Sie Ihre Dienste registrieren und sie direkt in Ihre Klasse laden können, z. B. mit Hilfe von Contructor Injection. Sie brauchen also den DependecyService nicht mehr. Registrieren Sie einfach Ihren Dienst in der MauiProgram.cs wie unten gezeigt und entfernen Sie das Attribut [assembly: Dependency())]
aus Ihrer Dienstklasse.
// shortened
var builder = MauiApp.CreateBuilder();
builder.Services.AddSingleton(typeof(BluetoothService));
Um Ihren Dienst in Ihre Klasse zu bekommen, müssen Sie ihn nur über die Parameter übergeben und können ihn dann verwenden.
public partial class BluetoothSettingsPage : ContentPage
{
public BluetoothSettingsPage(BluetoothService bluetoothService)
{
InitializeComponent();
var isBluetoothOn = bluetoothService.IsBluetoothOn();
}
}
Aktualisierungen der .NET MAUI-Projektstruktur
Um die neue .NET MAUI-Einzelprojektstruktur zu verwenden, müssen Sie die folgenden Schritte durchführen. Sie sind optional, bringen Ihr Projekt aber näher an die .NET MAUI-Projektstruktur heran.
- Erstellen Sie im .NET MAUI- oder im alten Xamarin.Forms-Projekt einen Ordner mit dem Namen „Plattformen“ mit jeweils einem Unterordner für „Android“ und „iOS“.
- In den Android-Ordner kopieren Sie Ihre Android-spezifischen Dateien wie die Application-Klasse, die MainActivity-Klasse, die Services oder den Custom-Randerer.
- Kopieren Sie in den iOS-Ordner Ihre iOS-spezifischen Dateien wie die AppDelegate-Klasse, die Dienste oder den Custom-Randerer.
- Fügen Sie außerdem einen Ordner
Resources
zum Maui-Projekt hinzu, falls es noch keinen gibt, und kopieren Sie alle Bilder dorthin.
Danach können Sie Ihre Projekte Forms.iOS und Forms.Android löschen.
.NET Upgrade Assistant zur Automatisierung der .NET MAUI-Konvertierung
Microsoft stellt mit dem .NET Upgrade Assistant ein Tool zur Verfügung, das viele der hier beschriebenen Schritte automatisch durchführt. Der Vorteil des .NET Upgrade Assistant ist, dass sowohl Projektdateien, NuGet-Pakete als auch Teile des Quellcodes aktualisiert werden. Zum Zeitpunkt der Erstellung dieses Artikels müssen jedoch noch viele Stellen manuell angepasst werden. Außerdem unterstützt der Upgrade Assistant nur C# und Visual Basic, wodurch F# (F-Sharp) auf der Strecke bleibt.
Um auszuprobieren, ob er in Ihrem Projekt besser funktioniert, sind zwei Schritte erforderlich:
- Führen Sie den folgenden Befehl im Terminal aus:
dotnet tool update --global upgrade-assistant
. - Führen Sie den .NET MAUI Upgrade-Assistenten mit dem folgenden Befehl aus:
upgrade-assistant upgrade <Pfad zu sln oder csproj> --non-interactive --entry-point *
.
Fazit
Wie Sie sehen, ist die Migration einer Xamarin.Forms-App zu .NET MAUI in wenigen Schritten erledigt, wenn Sie die genannten Punkte beachten. Vielleicht wird der .NET Upgrade Assistant in naher Zukunft in der Lage sein, alles automatisiert zu migrieren und wir müssen nur noch sehr wenig manuelle Arbeit leisten. Bis dahin versucht dieser Leitfaden, Ihnen einen guten Start zu ermöglichen. Lassen Sie mich wissen, wie Ihre Migration verlaufen ist und wo es Probleme gab. Ich bin sicher, wir können Ihnen helfen. Sie finden den Quellcode in unserem öffentlichen Bitbucket Repository: MAUI-Migration.