Migrar de Xamarin.Forms a .NET MAUI 10: guía completa 2026
Guía práctica para migrar Xamarin.Forms a .NET MAUI 10 en 2026: Upgrade Assistant, Custom Renderers a Handlers, dependencias NuGet, XAML y los errores que te vas a encontrar.
Migrar de Xamarin.Forms a .NET MAUI 10 consiste en actualizar el proyecto al SDK de .NET unificado, reemplazar Xamarin.Forms.Renderer por Handlers, consolidar los proyectos por plataforma en un único proyecto multi-target y validar dependencias NuGet contra los paquetes Microsoft.Maui.*. El soporte oficial de Xamarin finalizó el 1 de mayo de 2024, así que cualquier app Xamarin en producción en 2026 ya no recibe parches de seguridad y debe migrarse cuanto antes para seguir publicando en App Store y Google Play.
Lo cuento desde la trinchera: el año pasado migré una app de unas 60k líneas con doce CustomRenderer repartidos por toda la UI, y aprendí (a base de tropezones) qué partes del proceso son mecánicas y cuáles te van a robar fines de semana. Esta guía recoge esa experiencia.
Xamarin.Forms quedó fuera de soporte el 1 de mayo de 2024; .NET MAUI 10 (LTS, noviembre 2025) es su sucesor oficial con soporte hasta noviembre 2028.
La herramienta .NET Upgrade Assistant automatiza alrededor del 70% del trabajo, pero los CustomRenderer y los Effect requieren intervención manual.
El nuevo modelo de proyecto único multi-target (net10.0-android, net10.0-ios) sustituye los antiguos proyectos por plataforma de Xamarin.
Los Renderers de Xamarin siguen funcionando vía Microsoft.Maui.Controls.Compatibility, pero conviene migrar a Handlers por rendimiento (hasta 2x más rápido en arranque).
Una app Xamarin.Forms media de 50k líneas tarda entre 2 y 6 semanas en migrarse con un equipo de 1 a 2 desarrolladores.
Xamarin.Forms vs .NET MAUI 10: diferencias clave
La diferencia fundamental entre Xamarin.Forms y .NET MAUI es que MAUI unifica en un único proyecto lo que antes eran tres (PCL/.NET Standard + Android + iOS), apoyándose en el SDK .NET unificado. Mientras Xamarin.Forms se construyó sobre Mono y Xamarin.Android/iOS como capas independientes, .NET MAUI corre directamente sobre el runtime .NET 10. ¿La consecuencia práctica? Arranques más rápidos, APKs más pequeños y acceso directo a las APIs nativas sin bindings intermedios.
Otra diferencia crítica está en el modelo de renderizado. Xamarin.Forms usaba la jerarquía VisualElement → Renderer, donde cada control instanciaba un renderizador pesado vinculado al ciclo de vida del control. .NET MAUI introduce Handlers: clases ligeras separadas del control, que se conectan vía IElementHandler y permiten personalizar el comportamiento nativo sin heredar de la jerarquía visual. Esto reduce las asignaciones de memoria entre un 30% y un 40% según las mediciones publicadas por Microsoft en los .NET Blog benchmarks de .NET 10.
Característica
Xamarin.Forms 5
.NET MAUI 10
Estado del soporte
Finalizado (1 mayo 2024)
LTS hasta noviembre 2028
Estructura del proyecto
3 proyectos (Forms + Android + iOS)
Único proyecto multi-target
Modelo de renderizado
Renderers
Handlers (ligeros)
Hot Reload
XAML básico
XAML + C# Hot Reload completo
Plataformas soportadas
Android, iOS, UWP, macOS (preview)
Android, iOS, macOS (Catalyst), Windows (WinUI 3), Tizen
Runtime
Mono
.NET 10 unificado
Tamaño APK base
~25 MB
~12 MB (con linker)
Tiempo arranque (cold)
~1.8 s
~0.9 s
Requisitos previos antes de migrar
Antes de ejecutar cualquier herramienta de migración, necesitas un entorno preparado. Instala el SDK oficial de .NET 10.0 (incluye las cargas de trabajo maui-android, maui-ios y maui-maccatalyst). En Windows, Visual Studio 2026 17.13 o superior; en macOS, JetBrains Rider 2025.3 o VS Code con la extensión .NET MAUI Dev Kit, ya que Visual Studio para Mac fue descontinuado.
Comprueba que tu solución Xamarin.Forms está en la versión 5.0.0.2622 o superior. Las versiones anteriores tienen incompatibilidades con el Upgrade Assistant, y créeme, no quieres descubrirlo a mitad de proceso. Ejecuta este comando para verificar las cargas de trabajo:
dotnet workload install maui
dotnet workload list
dotnet --version # debe ser 10.0.x
Crea una rama de migración en Git (git checkout -b migration/maui) y, fundamentalmente, asegúrate de tener tests automatizados o al menos un plan de smoke testing manual. Sin red de seguridad, las regresiones visuales pasan desapercibidas hasta que un usuario las reporta. Si tu proyecto consume APIs REST, te conviene revisar nuestra guía de consumo de API REST en .NET MAUI 10 para alinear la capa de red durante la migración.
Migrar con .NET Upgrade Assistant paso a paso
Microsoft proporciona el .NET Upgrade Assistant, una CLI que reescribe el archivo .csproj, actualiza los namespaces de Xamarin.Forms a Microsoft.Maui.Controls, fusiona los proyectos de plataforma y migra los recursos básicos. Cubre alrededor del 70% del trabajo mecánico, según las cifras publicadas en la documentación oficial de migración a .NET MAUI.
Instálalo como herramienta global y ejecútalo sobre la solución:
dotnet tool install -g upgrade-assistant
cd MiAppXamarin
upgrade-assistant upgrade MiAppXamarin.sln
El asistente te guiará por pasos interactivos:
Seleccionar el proyecto principal: elige el proyecto compartido Xamarin.Forms (el .NET Standard, no los nativos).
Backup automático: el asistente crea una copia .backup de cada archivo modificado.
Conversión del .csproj: reescribe a formato SDK-style con <TargetFrameworks>net10.0-android;net10.0-ios</TargetFrameworks>.
Actualización de namespaces: reemplaza using Xamarin.Forms; por using Microsoft.Maui; y using Microsoft.Maui.Controls;.
Migración del bootstrap: convierte App.xaml.cs y crea MauiProgram.cs con el MauiAppBuilder.
El archivo MauiProgram.cs resultante debería parecerse a esto:
using Microsoft.Extensions.Logging;
using CommunityToolkit.Maui;
namespace MiAppMaui;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
Reemplazar Custom Renderers por Handlers
Los Custom Renderers son, casi siempre, la parte más costosa de la migración. Honestamente, fue donde se me fueron dos de las tres semanas que tardé en mi proyecto. .NET MAUI 10 mantiene compatibilidad mediante el paquete Microsoft.Maui.Controls.Compatibility, lo que permite que tus renderers existentes sigan funcionando durante la transición. Esta capa de compatibilidad, eso sí, será deprecada en .NET 12 (noviembre 2027), así que conviene migrar a Handlers antes.
Un renderer típico de Xamarin para personalizar un Entry en Android se vería así:
// Xamarin.Forms (antiguo)
[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
public class BorderlessEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
Control.Background = null;
}
}
El equivalente en .NET MAUI usa el mapper del handler, sin herencia:
// .NET MAUI 10 (Handler customization)
using Microsoft.Maui.Handlers;
public static class EntryHandlerCustomization
{
public static void Customize()
{
EntryHandler.Mapper.AppendToMapping("NoUnderline", (handler, view) =>
{
#if ANDROID
handler.PlatformView.BackgroundTintList =
Android.Content.Res.ColorStateList.ValueOf(
Android.Graphics.Color.Transparent);
#elif IOS
handler.PlatformView.BorderStyle =
UIKit.UITextBorderStyle.None;
#endif
});
}
}
Invoca EntryHandlerCustomization.Customize() dentro de MauiProgram.CreateMauiApp(). Este patrón elimina la necesidad de subclases por plataforma y reduce el código entre un 40% y un 50% en proyectos con muchos renderers. Si tu app usa Effects (la otra extensión visual de Xamarin), conviene migrarlos también a la API de Handler mappers, ya que los RoutingEffect son ahora considerados legacy.
Actualizar dependencias NuGet y CommunityToolkit
Las dependencias son la segunda fuente principal de fricción. Muchos paquetes populares de Xamarin tienen un equivalente directo en .NET MAUI:
¿Y si dependes de algún paquete sin equivalente MAUI? Por ejemplo, un wrapper antiguo de un SDK propietario. Busca su fork mantenido por la comunidad o, en última instancia, invoca la API nativa directamente con [DllImport] en Android o ObjCRuntime en iOS. Para gestión de estado complejo y patrones MVVM, te recomiendo revisar también nuestra guía de patrones MVVM con HttpClient y Refit.
Ajustar XAML, estilos y recursos
La sintaxis XAML es mayoritariamente compatible, pero hay cambios concretos que debes corregir manualmente tras pasar el Upgrade Assistant. El namespace raíz cambia de http://xamarin.com/schemas/2014/forms a http://schemas.microsoft.com/dotnet/2021/maui. Cualquier referencia x:Class que apunte a un control compilado debe actualizar su assembly.
Recursos de imagen: mueve los PNG/SVG desde Resources/drawable y Resources/Images.xcassets a Resources/Images/ en el proyecto único. MAUI los procesa con el sistema MAUI Images en compilación.
Fuentes: deben registrarse en MauiProgram.cs con fonts.AddFont(...), ya no se referencian con OnPlatform.
Splash screen: define <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> en el .csproj.
Icono de la app: similar, vía <MauiIcon Include="Resources\AppIcon\appicon.svg" />.
Errores comunes y cómo resolverlos
Estos son los problemas que más reportan los equipos durante la migración, basado en los issues recientes del repositorio dotnet/maui en GitHub:
1. Java.Lang.NoSuchMethodError al arrancar en Android
Casi siempre indica una versión incompatible de AndroidX. Verifica que <SupportedOSPlatformVersion> en el .csproj sea al menos 24 (Android 7.0) y borra las carpetas obj/ y bin/ antes de reconstruir.
2. System.MissingMethodException en iOS al cargar una página XAML
Causa típica: un BindableProperty definido en Xamarin con la firma antigua. Reemplaza BindableProperty.Create(nameof(Prop), typeof(string), typeof(MyControl)) manteniendo todos los parámetros nombrados; el type inference en MAUI es bastante más estricto.
3. El OnPlatform markup extension no resuelve valores
El parser de MAUI requiere especificar el tipo genérico explícitamente: <OnPlatform x:TypeArguments="x:Double"> en lugar de la inferencia que Xamarin permitía.
4. DependencyService deja de inyectar instancias
MAUI todavía soporta DependencyService, pero la práctica recomendada es migrar al contenedor DI integrado:
MAUI convierte SVG a PNG en compilación. Si el SVG usa filtros complejos (feGaussianBlur, gradientes con spreadMethod), simplifícalo o conviértelo previamente, ya que el conversor falla silenciosamente. Me pasó con un logotipo que parecía no aparecer, y resultó que era un filtro Gaussian Blur el culpable.
¿Cuánto tiempo lleva migrar Xamarin a MAUI?
Una migración real de una app Xamarin.Forms de tamaño medio (40k a 80k líneas, ~30 vistas XAML, entre 5 y 10 custom renderers, 15 dependencias NuGet) suele tomar entre 2 y 6 semanas con un equipo de 1 o 2 desarrolladores. La distribución habitual del esfuerzo es: 15% para el Upgrade Assistant y la configuración inicial, 35% para los renderers/handlers, 25% para ajustes XAML y dependencias, y 25% para regresión visual y QA.
Las apps con uso intensivo de EmbeddedResource, generadores de código por reflexión o controles propietarios pueden duplicar ese tiempo. Para acelerar el proceso, divide la migración por features verticales en lugar de por capas: migra primero la pantalla de login completa (XAML + ViewModel + servicios), valida que funciona en Android e iOS, y solo entonces avanza al siguiente flujo. Este enfoque, te lo digo por experiencia, reduce el riesgo de regresiones acumuladas y mantiene la app ejecutable en todo momento.
Preguntas frecuentes
¿Es obligatorio migrar de Xamarin a .NET MAUI en 2026?
Sí, en la práctica. Xamarin perdió el soporte de Microsoft el 1 de mayo de 2024, por lo que no recibe parches de seguridad ni actualizaciones para nuevas versiones de Android o iOS. Google y Apple exigen targetear versiones recientes del SDK para publicar en sus tiendas, y Xamarin.Forms 5 ya no puede compilar contra Android 15 o iOS 19 sin parches de la comunidad.
¿.NET MAUI reemplaza completamente a Xamarin?
Sí. .NET MAUI es el sucesor oficial designado por Microsoft. Engloba lo que antes eran Xamarin.Forms, Xamarin.Android, Xamarin.iOS y Xamarin.Mac, y los reemplaza con un único modelo de proyecto unificado sobre .NET 10.
¿Puedo migrar gradualmente o tiene que ser de golpe?
La migración debe completarse antes de publicar en MAUI, pero internamente puedes avanzar por módulos. Mantén la app Xamarin en una rama, crea otra para la migración y valida feature por feature usando el paquete de compatibilidad Microsoft.Maui.Controls.Compatibility, que permite reutilizar renderers existentes durante la transición.
¿Qué pasa con Visual Studio para Mac al migrar?
Visual Studio para Mac fue retirado en agosto de 2024. En macOS hoy se usa JetBrains Rider 2025.3 o VS Code con la extensión oficial .NET MAUI Dev Kit. Ambas ofrecen depuración completa para Android, iOS y Mac Catalyst.
¿Vale la pena migrar a .NET MAUI o conviene reescribir en Flutter o React Native?
Si tu equipo ya domina C# y XAML, .NET MAUI es la opción más rentable: reaprovechas entre el 80% y el 95% del código existente. Reescribir en Flutter o React Native implica tirar todo el conocimiento de dominio, las pruebas y los bindings nativos personalizados, lo que rara vez se justifica salvo que ya tuvieras planeado un rediseño completo.
Sofia is a mobile platform engineer with eleven years across native iOS, Xamarin, and now .NET MAUI. She spent three years at Spotify in Stockholm working on internal tooling for the mobile build infrastructure, then joined a fintech in Milan where she leads the mobile foundations team responsible for a MAUI app that handles around 2 million monthly active users across iOS and Android.
Most of what she writes about lives in the build and release layer: deterministic builds, fastlane integration for MAUI, code signing on macOS runners, MAUI .NET 9 upgrade postmortems, and benchmarking startup time on cheap Android hardware. She co-organizes the Milano .NET meetup and gave a talk at NDC Oslo 2025 on shrinking a MAUI Android APK from 84 MB to 31 MB without losing features.