xamarin-forms-migration

Xamarin.Forms → .NET MAUI Migration

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "xamarin-forms-migration" with this command: npx skills add davidortinau/maui-skills/davidortinau-maui-skills-xamarin-forms-migration

Xamarin.Forms → .NET MAUI Migration

Use this skill when migrating a Xamarin.Forms app to .NET MAUI. This covers the full migration path from project file conversion through UI and API changes.

Field-tested advice: Do not use the .NET Upgrade Assistant. Apply namespace renames, project file updates, and package replacements directly. Build after each batch of changes and use compiler errors to guide the next round of fixes.

Migration Workflow Overview

  • Choose project structure (single-project recommended)

  • Create a new .NET MAUI project

  • Copy code and resources

  • Update namespaces (XAML + C# + Essentials)

  • Fix layout behavior changes

  • Migrate renderers → handlers

  • Migrate effects → behaviors

  • Remove Compatibility package

  • Update NuGet dependencies

  • Migrate app data stores

  • Bootstrap, build, and test iteratively

  • Verify against .NET 10 deprecated API list

Step 1 — Choose Project Structure

Option Recommendation

Single-project (recommended) One .csproj with <TargetFrameworks>net8.0-android;net8.0-ios;...</TargetFrameworks> . Platform code lives in Platforms/ folders. Avoids AOT/build errors that multi-project can cause.

Multi-project Separate head projects per platform. Only use if you have a strong reason (shared solution with non-MAUI projects).

Field advice: Use single-project. Multi-project causes AOT/build errors and you'll lose git history.

Step 2 — Create a New .NET MAUI Project

Create a new .NET MAUI project with the same name as your Xamarin.Forms app, then copy code into it. This is simpler and less error-prone than editing the existing project file in place.

<!-- .NET MAUI single-project csproj --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))"> $(TargetFrameworks);net8.0-windows10.0.19041.0 </TargetFrameworks> <OutputType>Exe</OutputType> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>

Replace net8.0 with net9.0 or net10.0 as appropriate for your target version. The migration steps are identical across .NET 8, 9, and 10.

Step 3 — Copy Code and Resources

  • Copy all cross-platform code from your Xamarin.Forms library project into the new MAUI project (same folder structure).

  • Copy platform-specific code from each head project into Platforms/<platform>/ .

  • Copy custom code from MainActivity /MainApplication (Android) and AppDelegate (iOS) into the MAUI equivalents.

  • Copy resources (images, fonts, raw assets) into Resources/ .

Step 4 — Update Namespaces

XAML Namespace Changes

Xamarin.Forms .NET MAUI

xmlns="http://xamarin.com/schemas/2014/forms"

xmlns="http://schemas.microsoft.com/dotnet/2021/maui"

xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

(unchanged)

C# Namespace Changes

Xamarin.Forms Namespace .NET MAUI Namespace

Xamarin.Forms

Microsoft.Maui.Controls

Xamarin.Forms.Xaml

Microsoft.Maui.Controls.Xaml

Xamarin.Forms.PlatformConfiguration

Microsoft.Maui.Controls.PlatformConfiguration

Xamarin.Forms.PlatformConfiguration.iOSSpecific

Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific

Xamarin.Forms.PlatformConfiguration.AndroidSpecific

Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific

Xamarin.Forms.Shapes

Microsoft.Maui.Controls.Shapes

Xamarin.Forms.StyleSheets

(removed — use MAUI styles)

Xamarin.Essentials → .NET MAUI Namespaces

In .NET MAUI, Xamarin.Essentials functionality is built in. Remove the Xamarin.Essentials

NuGet package and update using directives:

Xamarin.Essentials .NET MAUI Namespace

Xamarin.Essentials (general) Split across multiple namespaces below

App actions, permissions, version tracking Microsoft.Maui.ApplicationModel

Contacts, email, networking Microsoft.Maui.ApplicationModel.Communication

Battery, sensors, flashlight, haptics Microsoft.Maui.Devices

Media picking, text-to-speech Microsoft.Maui.Media

Clipboard, file sharing Microsoft.Maui.ApplicationModel.DataTransfer

File picking, secure storage, preferences Microsoft.Maui.Storage

Step 5 — Fix Layout Behavior Changes

Default Value Changes

.NET MAUI zeroes out default spacing/padding that Xamarin.Forms set to non-zero values. Add explicit values or use implicit styles to preserve old behavior:

Property Xamarin.Forms Default .NET MAUI Default

Grid.ColumnSpacing

6 0

Grid.RowSpacing

6 0

StackLayout.Spacing

6 0

<!-- Implicit styles to restore Xamarin.Forms defaults (add to App.xaml) --> <Style TargetType="Grid"> <Setter Property="ColumnSpacing" Value="6"/> <Setter Property="RowSpacing" Value="6"/> </Style> <Style TargetType="StackLayout"> <Setter Property="Spacing" Value="6"/> </Style>

Field advice: Specify all layout values explicitly — don't rely on platform defaults. Define them in styles.

Key Layout Behavior Differences

Issue Xamarin.Forms .NET MAUI Fix

Grid columns/rows Inferred from XAML Must be explicitly declared Add ColumnDefinitions and RowDefinitions

*AndExpand options Supported on StackLayout Obsolete — no effect on HorizontalStackLayout /VerticalStackLayout

Convert to Grid with * row/column sizes

StackLayout fill Children could fill stacking direction Children stack beyond available space Use Grid when children need to fill space

RelativeLayout

Built-in Compatibility namespace only Replace with Grid

Frame

Built-in Replaced by Border (Frame still works but measures differently) Migrate to Border

ScrollView in StackLayout Compressed to fit Expands to full content height (no scroll) Place ScrollView in Grid with constrained row

BoxView default size 40×40 0×0 Set explicit WidthRequest /HeightRequest

Converting *AndExpand to Grid

<!-- BEFORE (Xamarin.Forms) --> <StackLayout> <Label Text="Hello world!"/> <Image VerticalOptions="FillAndExpand" Source="dotnetbot.png"/> </StackLayout>

<!-- AFTER (.NET MAUI) --> <Grid RowDefinitions="Auto, *"> <Label Text="Hello world!"/> <Image Grid.Row="1" Source="dotnetbot.png"/> </Grid>

Field advice: Flatten layout trees. Replace nested hierarchies with single Grid layouts. Avoid deep nesting.

Step 6 — Migrate Renderers to Handlers

Field advice: Migrate all renderers to handlers — don't use shimmed renderers. Extend existing mappers when possible.

Option A — Customize Existing Handlers (Preferred)

Use mapper methods to modify existing control behavior without a full handler:

// In MauiProgram.cs Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("NoBorder", (handler, view) => { #if ANDROID handler.PlatformView.Background = null; #elif IOS || MACCATALYST handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None; #endif });

Mapper Method When it runs

PrependToMapping

Before default mapper

ModifyMapping

Replaces default mapper

AppendToMapping

After default mapper

Option B — Full Handler Migration

For renderers that require a completely new native view, migrate to a full handler:

  • Create a cross-platform control class (extends View )

  • Create a partial handler class with PropertyMapper

  • Create platform-specific partial classes with CreatePlatformView()

  • Register with ConfigureMauiHandlers in MauiProgram.cs

For detailed handler creation guidance, use the maui-custom-handlers skill.

Shimmed Renderers (Fallback Only)

If you must keep a renderer temporarily, .NET MAUI provides shims for renderers deriving from FrameRenderer , ListViewRenderer , ShellRenderer , TableViewRenderer , and VisualElementRenderer :

  • Move code to Platforms/<platform>/ folders

  • Change Xamarin.Forms.* namespaces to Microsoft.Maui.*

  • Remove [assembly: ExportRenderer(...)] attributes

  • Register with ConfigureMauiHandlers / AddHandler

Warning: Shimmed renderers are a migration convenience, not a long-term solution. They create parent wrapper views that hurt performance.

Step 7 — Migrate Effects to Behaviors

Field advice: Effects are now Behaviors — this requires redesign, not just renaming.

Effects can be migrated to .NET MAUI but require changes:

  • Remove ResolutionGroupNameAttribute and ExportEffectAttribute

  • Remove Xamarin.Forms and Xamarin.Forms.Platform.* using directives

  • Combine RoutingEffect

  • PlatformEffect implementations into a single file with conditional compilation
  • Register with ConfigureEffects in MauiProgram.cs

// MauiProgram.cs builder.ConfigureEffects(effects => { effects.Add<FocusRoutingEffect, FocusPlatformEffect>(); });

For new development, prefer behaviors or handler mapper customizations over effects.

Step 8 — Do NOT Use the Compatibility Package

Field advice: Microsoft.Maui.Controls.Compatibility causes cascading incompatibilities. Remove it and rebuild layouts natively.

Step 9 — Update NuGet Dependencies

Compatible Frameworks Incompatible Frameworks

net8.0-android , monoandroid , monoandroidXX.X

net8.0-ios

monotouch , xamarinios , xamarinios10

net8.0-macos

monomac , xamarinmac , xamarinmac20

net8.0-tvos

xamarintvos

.NET Standard libraries without incompatible framework dependencies remain compatible.

If no .NET-compatible version exists:

  • Recompile the package with .NET TFMs (if you own it)

  • Look for a preview .NET version

  • Replace with a .NET-compatible alternative

Retired Dependencies

  • App Center is retired → Replace with Sentry, Azure Monitor, or similar

  • Visual Studio for Mac is retired → Use VS Code or Rider

Step 10 — Migrate App Data

Data Store Migration Guide

Application.Properties

Migrate to Preferences (Microsoft.Maui.Storage )

Secure Storage Migrate from Xamarin.Essentials.SecureStorage to Microsoft.Maui.Storage.SecureStorage

Version Tracking Migrate from Xamarin.Essentials.VersionTracking to Microsoft.Maui.ApplicationModel.VersionTracking

SkiaSharp Update to SkiaSharp 2.88+ with SkiaSharp.Views.Maui

Step 11 — Bootstrap and Test

Entry Point Changes

Replace the Xamarin.Forms App class initialization with MAUI's MauiProgram :

// MauiProgram.cs public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); }); return builder.Build(); } }

Build and Fix

  • Delete all bin/ and obj/ folders

  • Delete Resource.designer.cs (Android)

  • Build and fix compiler errors iteratively

  • Profile early — do not assume MAUI is automatically faster

Field advice: Build after each batch of changes and use compiler errors to guide fixes.

.NET 10 API Currency Warning

When migrating to .NET MAUI targeting .NET 10, avoid these MAUI APIs that are themselves deprecated or obsolete. Use the maui-current-apis skill for the full list.

Avoid in .NET 10 Use Instead

ListView , TableView

CollectionView

Frame

Border with StrokeShape

Device.RuntimePlatform

DeviceInfo.Platform

Device.BeginInvokeOnMainThread()

MainThread.BeginInvokeOnMainThread()

Device.OpenUri()

Launcher.OpenAsync()

DependencyService

Constructor injection via builder.Services

MessagingCenter

WeakReferenceMessenger (CommunityToolkit.Mvvm)

DisplayAlert() / DisplayActionSheet()

DisplayAlertAsync() / DisplayActionSheetAsync()

FadeTo() , RotateTo() , etc. FadeToAsync() , RotateToAsync() , etc.

Color.FromHex()

Color.FromArgb()

Page.IsBusy

ActivityIndicator

Migration is the perfect time to skip deprecated APIs entirely. Don't migrate Xamarin.Forms code to a MAUI API that's already on its way out.

Common Troubleshooting

Issue Fix

Xamarin.* namespace doesn't exist Update to Microsoft.Maui.* equivalent

CollectionView doesn't scroll Place in Grid (not StackLayout) to constrain size

Pop-up under page on iOS Use DisplayAlert /DisplayActionSheet from the ContentPage

BoxView not visible Set WidthRequest and HeightRequest (default is 0×0 in MAUI)

Missing padding/margin/spacing Add explicit values or implicit styles for old defaults

Custom layout broken Rewrite using MAUI layout APIs

Custom renderer broken Migrate to handler (see Step 6)

Effect broken Migrate to MAUI effect registration (see Step 7)

SkiaSharp broken Update to SkiaSharp.Views.Maui package

Can't access App.Properties data Migrate to Preferences

Android-Specific Warnings

  • Android migration is significantly harder than iOS. Expect more UI bugs.

  • Android has OEM-specific rendering differences not reproducible on emulators. Test on physical devices.

  • Shadow rendering varies across Android OEMs and API levels. Implement shadows in platform-specific handler code.

  • Handler-level property changes (e.g., colors) do not auto-update on theme switch. Manually handle theme changes inside custom handlers.

Quick Checklist

  • ☐ Created new .NET MAUI project (single-project preferred)

  • ☐ Copied cross-platform and platform code

  • ☐ Updated XAML namespace to http://schemas.microsoft.com/dotnet/2021/maui

  • ☐ Replaced Xamarin.Forms.* → Microsoft.Maui.* namespaces

  • ☐ Replaced Xamarin.Essentials → split MAUI namespaces

  • ☐ Added explicit Grid ColumnDefinitions /RowDefinitions

  • ☐ Replaced *AndExpand with Grid layouts

  • ☐ Migrated renderers to handlers (not shimmed renderers)

  • ☐ Migrated effects to behaviors or MAUI effects

  • ☐ Removed Microsoft.Maui.Controls.Compatibility package

  • ☐ Updated NuGet dependencies for .NET compatibility

  • ☐ Migrated App.Properties, SecureStorage, VersionTracking data

  • ☐ Added explicit spacing/padding values (MAUI defaults to 0)

  • ☐ Deleted bin/ , obj/ , and Resource.designer.cs

  • ☐ Tested on physical Android device

  • ☐ Profiled performance

  • ☐ Verified no .NET 10 deprecated APIs (run maui-current-apis skill)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

maui-performance

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-data-binding

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-rest-api

No summary provided by upstream source.

Repository SourceNeeds Review
General

maui-permissions

No summary provided by upstream source.

Repository SourceNeeds Review