
Skill
xamarin-forms-migration
migrate Xamarin.Forms apps to .NET MAUI
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.
SKILL.md
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.csDI 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.
- Xamarin.Forms version, target platforms, platform projects, NuGet packages,
renderers, effects,
- 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 newXamarin.FormsorXamarin.Essentialsreferences. - 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.cswithAddSingleton,AddScoped, orAddTransientbased 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-apisfor version-specific MAUI API replacements. - Use
maui-custom-handlersfor handler mapper/custom handler implementation. - Use
maui-platform-invokefor non-visual platform services, partial classes, permissions, and lifecycle hooks. - Use
android-slim-bindingsorios-slim-bindingswhen a native SDK needs a maintainable binding surface. - Use
maui-accessibilityandmaui-performancefor 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.
DependencyServiceandMessagingCenterreplacements have explicit lifetimes.- Each migrated slice builds and runs on at least one intended platform.
More skills from the maui-labs repository
View all 32 skillsandroid-slim-bindings
create Android slim bindings for .NET
Jul 12.NETAndroidJavaKotlin +1devflow-automation
automate .NET MAUI app state
Jul 12.NETAutomationMAUIMobiledevflow-connect
diagnose DevFlow agent connectivity issues
Jul 12DebuggingMAUINetworkingdotnet-workload-info
discover MAUI workload metadata
Jul 12C#CLIEngineeringMAUIios-slim-bindings
create iOS slim bindings for MAUI
Jul 12.NETiOSMAUISwift +1maui-accessibility
implement accessibility in .NET MAUI apps
Jul 12.NETAccessibilityMAUIMobile +1
More from .NET (Microsoft)
View publishermultithreaded-task-migration
migrate MSBuild tasks to multithreaded mode
msbuild
Jul 12.NETEngineeringPerformanceanalyzing-dotnet-performance
analyze .NET code for performance anti-patterns
skills
Jul 12.NETCode AnalysisDebuggingPerformanceandroid-tombstone-symbolication
symbolicate .NET runtime frames in Android tombstones
skills
Jul 12.NETAndroidDebuggingMicrosoftapple-crash-symbolication
symbolicate .NET runtime frames in crash logs
skills
Jul 12.NETDebuggingiOSmacOS +1assertion-quality
evaluate assertion quality in test suites
skills
Jul 12Code AnalysisQATestingauthor-component
create and review Blazor components
skills
Jul 15.NETBlazorC#UI Components +1