| name | xamarin-forms-migration |
| description | Plan Xamarin.Forms to .NET MAUI migrations. USE FOR: audits, fresh `dotnet new maui`, `Xamarin.Forms`/`Xamarin.Essentials` namespace updates, `DependencyService` to DI, `MessagingCenter` to WeakReferenceMessenger/events, renderer triage into mapper/custom handler/platform service/slim binding, `MauiProgram`, permissions, parity. DO NOT USE FOR: brand-new MAUI apps, native SDK bindings, backend. |
Xamarin.Forms Migration
Use this skill to move a Xamarin.Forms app to .NET MAUI without blindly copying
obsolete patterns. Treat migration as an audit and phased rebuild on a fresh
MAUI project unless the user explicitly needs a small tactical port.
Response Checklist
- Call out the migration audit first (
DependencyService, MessagingCenter,
custom renderers/effects, permissions, and platform capabilities).
- Prefer a fresh MAUI project workflow and
MauiProgram.cs DI setup.
- Explicitly classify renderer replacements into mapper customization, custom
handler, platform service, or slim binding.
Migration Tooling
Before migrating manually, check whether the .NET Upgrade Assistant can cover
the mechanical parts of the app:
dotnet tool install -g upgrade-assistant
upgrade-assistant upgrade <your-solution>.sln
Upgrade Assistant can help with project conversion and namespace/API rewrites.
Use this skill for decisions tooling cannot safely automate: renderer
classification, DependencyService lifetimes, MessagingCenter replacement,
platform capability parity, and validation planning.
Migration Workflow
- Inventory the current app:
- Xamarin.Forms version, target platforms, platform projects, NuGet packages,
renderers, effects,
DependencyService, MessagingCenter, and native SDKs.
- App startup, navigation, resource dictionaries, images/fonts, and platform
entitlements/permissions.
- Create a new .NET MAUI project or solution structure that matches the target
app shape. Prefer this over editing the Xamarin.Forms project in place.
- Move shared code first: models, services, view models, converters, resources,
and XAML. Keep platform code out until shared code builds.
- Update namespaces and APIs using
maui-current-apis; do not introduce new
Xamarin.Forms or Xamarin.Essentials references.
- Migrate app startup to
MauiProgram.cs, CreateMauiApp, DI registration,
fonts, handlers, lifecycle events, and platform services.
- Migrate UI and navigation incrementally. Keep Shell route names, modal flows,
and deep-link behavior explicit.
- Plan custom renderer/effect replacements:
- simple native property tweak -> handler mapper customization;
- reusable custom control -> custom handler;
- non-visual platform API -> platform service via DI;
- third-party native SDK surface -> slim binding.
- Validate each migrated slice with build, platform launch, and accessibility or
performance checks for changed UI.
Common API Replacements
| Xamarin.Forms-era pattern | MAUI direction |
|---|
using Xamarin.Forms | using Microsoft.Maui.Controls |
using Xamarin.Essentials | Microsoft.Maui.ApplicationModel, Microsoft.Maui.Devices, Microsoft.Maui.Storage, or the specific MAUI namespace |
Device.BeginInvokeOnMainThread | MainThread.BeginInvokeOnMainThread or Dispatcher.Dispatch |
Device.StartTimer | Dispatcher.StartTimer or IDispatcherTimer |
Device.RuntimePlatform | DeviceInfo.Platform, OnPlatform, partial classes, or DI services |
Color.Red, Color.FromHex | Colors.Red, Color.FromArgb, or resource colors |
Application.Current.MainPage = ... | Window.Page for intentional resets, or Shell/navigation abstractions for routine navigation |
DependencyService.Get<T>() | Constructor-injected services registered in MauiProgram.cs |
MessagingCenter | WeakReferenceMessenger, events, observable state, or explicit domain services |
ExportRenderer / CustomRenderer | Handler mapper customization or ViewHandler<TVirtualView,TPlatformView> |
DependencyService to DI
-
Move the cross-platform contract to shared code:
public interface IClipboardAuditService
{
Task TrackCopyAsync(string source, CancellationToken cancellationToken = default);
}
-
Implement each platform in Platforms/<Platform>/ or target-specific files.
-
Register the implementation in MauiProgram.cs with AddSingleton,
AddScoped, or AddTransient based on lifetime needs.
-
Inject the service into view models or services. Avoid service locator calls
from pages unless the app already uses that pattern and you are containing
migration risk.
MessagingCenter Replacement
Choose the smallest explicit communication pattern:
| Existing use | Replacement |
|---|
| View model updates a bound page | Observable properties and binding |
| Domain event across features | WeakReferenceMessenger or an app event aggregator |
| One service asks another to work | Inject the target service and call a method |
| Navigation trigger | Navigation service or Shell route call |
| Platform callback | Platform service event or IObservable<T> exposed through DI |
Do not migrate MessagingCenter by adding global static events everywhere.
Document message names, payload types, sender/receiver lifetimes, and threading
before replacing them.
Renderer to Handler Planning
Audit each renderer and classify it before writing code:
| Renderer shape | MAUI migration |
|---|
| Changes one native property on an existing MAUI control | Handler.Mapper.AppendToMapping scoped to a subclass or named mapping |
| Needs a cross-platform custom control with bindable properties | Custom handler with PropertyMapper and optional CommandMapper |
| Subscribes to native events | Handler ConnectHandler/DisconnectHandler with explicit unsubscribe cleanup |
| Calls camera, health, maps, payment, or other SDK APIs | Platform service or slim binding; do not hide SDK workflow in a visual handler |
| Uses Xamarin.Forms effects only for styling | Prefer styles, visual states, or a handler mapper |
Platform Capability Parity
For each target platform, record:
- required permissions, entitlements, manifests, Info.plist keys, and app
capabilities;
- Essentials API coverage and behavioral differences;
- native SDK availability and version requirements;
- background tasks, push/deep link, secure storage, file picker, and biometric
differences;
- UI parity risks such as safe areas, keyboard/soft input, gestures, and desktop
pointer behavior.
Cross-Skill Routing
- Use
maui-current-apis for version-specific MAUI API replacements.
- Use
maui-custom-handlers for handler mapper/custom handler implementation.
- Use
maui-platform-invoke for non-visual platform services, partial classes,
permissions, and lifecycle hooks.
- Use
android-slim-bindings or ios-slim-bindings when a native SDK needs a
maintainable binding surface.
- Use
maui-accessibility and maui-performance for migrated UI risk areas.
Validation Checklist
- The migration plan starts from an audited Xamarin.Forms solution, not guesses.
- New code targets MAUI namespaces and current APIs.
- Platform capabilities and permissions are mapped for every retained platform.
- Renderers/effects are classified before migration.
DependencyService and MessagingCenter replacements have explicit lifetimes.
- Each migrated slice builds and runs on at least one intended platform.