Migrace z Xamarin.Forms na .NET MAUI v roce 2026: Kompletní průvodce krok za krokem

Migrace z Xamarin.Forms na .NET MAUI v roce 2026 krok za krokem: inventura, upgrade-assistant, Custom Renderery na Handlery, DependencyService na DI a CI/CD.

Migrace Xamarin na .NET MAUI 2026: Návod

Aktualizováno: 29. května 2026

Migrace z Xamarin.Forms na .NET MAUI je v roce 2026 nutnost, ne volba. Oficiální podpora Xamarinu skončila 1. května 2024 a od té doby aplikace neobdržely žádné bezpečnostní záplaty ani opravy. V tomhle průvodci projdeme reálný postup, který jsem použil ve třech produkčních aplikacích: od inventury závislostí, přes nástroj dotnet upgrade-assistant, přepis Custom Rendererů na Handlery, až po aktualizaci CI/CD a App Store metadat. Klíčové slovo "migrace na .NET MAUI" znamená v praxi dvě věci najednou: upgrade frameworku a refaktoring architektury.

  • Xamarin.Forms i klasický Xamarin (iOS/Android) přestaly být podporované 1. května 2024. Aplikace publikované po tomto datu nesplňují bezpečnostní požadavky App Store ani Google Play Protect.
  • Nástroj dotnet upgrade-assistant automatizuje 60–80 % mechanických úprav (SDK-style csproj, namespace přejmenování, NuGet balíčky), zbytek je manuální refaktoring.
  • Custom Renderery jsou v .NET MAUI nahrazeny Handlery. Jde o architektonicky odlišný model, který nelze 1:1 portovat, ale Microsoft poskytuje kompatibilní vrstvu Microsoft.Maui.Controls.Compatibility pro postupnou migraci.
  • Reálná doba migrace středně velké aplikace (50–80 obrazovek, 15–25 vlastních kontrol) je 4–8 týdnů jednoho seniora. Nepodceňujte testování na fyzických zařízeních.
  • Cílový framework musí být minimálně net9.0-android35.0 a net9.0-ios18.0 pro splnění požadavků obchodů v 2026.
  • Doporučuji postupovat iterativně s kompatibilní vrstvou, ne velkým "big bang" přepisem.

Proč migrovat právě teď: stav podpory v roce 2026

Pokud jste migraci odkládali, máte v roce 2026 už jen málo manévrovacího prostoru. Microsoft ukončil oficiální podporu Xamarinu k 1. květnu 2024. To znamená žádné opravy bezpečnostních zranitelností, žádnou kompatibilitu s novými verzemi iOS a Androidu, a žádné aktualizace SDK pro nové cílové úrovně API.

Google Play od srpna 2025 vyžaduje target SDK 35 (Android 15) pro všechny aktualizace existujících aplikací. Xamarin.Android dokáže oficiálně cílit nanejvýš na API 34, a každý pokus o vyšší úroveň běží na komunitních fork-ech, které nejsou v produkci udržitelné. Apple od dubna 2025 vyžaduje sestavení s iOS 18 SDK, což klasický Xamarin.iOS nepodporuje. Aplikace, které jste publikovali před touto změnou, zatím přežívají, ale jakákoliv aktualizace selže při review.

Druhý důvod je ekonomický. NuGet balíčky pro Xamarin přestaly dostávat aktualizace. Polly, Refit, MediatR a další běžné knihovny dnes vydávají jen .NET Standard 2.0 nebo přímo net8.0+ verze, které se kompilují s MAUI, ale ne s Xamarin.Forms. Časem každá závislost zamrzne na verzi, která má známé CVE. V mé poslední migraci jsme našli 14 závislostí s aktivními bezpečnostními záplatami, které byly v Xamarin verzích nedostupné. (Bezpečnostní tým si toho samozřejmě všiml jako první.)

Jaký je rozdíl mezi Xamarin.Forms a .NET MAUI?

.NET MAUI je evoluce, ne revoluce. Sdílí kořeny s Xamarin.Forms, ale jádro architektury je přepsané. Nejdůležitější rozdíly shrnuje následující tabulka:

AspektXamarin.Forms.NET MAUI
Cílový runtimeMono + .NET Framework.NET 8 / .NET 9 (jednotný runtime)
Projektová struktura3–4 projekty (sdílený + per-platform)Jeden multi-target projekt (SDK-style)
Rozšiřitelnost UICustom Renderers (per-platform třídy)Handlers (mappery vlastností)
Dependency InjectionDependencyService (statický locator)Microsoft.Extensions.DependencyInjection
Hot ReloadXAML Hot Reload (omezeně)XAML + C# Hot Reload
Podpora platforemiOS, Android, UWP, TizeniOS, Android, macOS (Catalyst), Windows
Maximální target SDK (2026)Android 34, iOS 17Android 35, iOS 18
Stav podporyUkončena 1. 5. 2024LTS do listopadu 2026 (.NET 8) / 2027 (.NET 9)

Pokud vás zajímá hloubková analýza výkonu po migraci, podívejte se na náš průvodce optimalizace výkonu v .NET MAUI, který vysvětluje, proč jsou některé scénáře (zejména startup a virtualizace seznamů) výrazně rychlejší než v Xamarinu.

Příprava projektu před migrací: inventura a audit

Než spustíte jakýkoliv automatický nástroj, udělejte inventuru. Honestly, v mé praxi se 70 % nepříjemných překvapení odhalí v této fázi, ne při kompilaci. Vytvořte si tabulku, do které vyplníte:

  1. Seznam NuGet balíčků a jejich MAUI-kompatibilních verzí. Použijte dotnet list package a každý balíček ověřte na nuget.org. Některé byly přejmenované (např. Xamarin.Essentials je v MAUI součástí Microsoft.Maui.Essentials).
  2. Custom Renderery a Effects. Vyhledejte všechny třídy s atributem [assembly: ExportRenderer] a [assembly: ExportEffect]. Každý z nich budete muset přepsat na Handler nebo Behavior.
  3. Volání DependencyService. Grep přes DependencyService.Get a DependencyService.Register. Všechna místa potřebují přepis na konstruktor DI.
  4. Platformně specifické projekty. Soubory v YourApp.Android a YourApp.iOS projektech se sloučí do jediného projektu s Platforms/ podadresářem.
  5. Build pipeline. Pokud používáte Azure Pipelines nebo GitHub Actions, poznamenejte si UseDotNet, NuGetToolInstaller a podpisové kroky. Všechny se změní.

Ve velkém projektu jsem se naučil dělat ještě jeden krok: vytvořit větev migration/baseline a v ní spustit kompletní sadu UI testů, aby se zachoval referenční stav chování před migrací. Bez baseline se těžko rozhoduje, jestli nová chybka v dialogu je regrese, nebo původně skrytý bug (přesně tohle mě jednou stálo dva dny ladění).

Spuštění dotnet upgrade-assistant krok za krokem

Microsoft poskytuje nástroj .NET Upgrade Assistant, který provede většinu mechanických úprav. V roce 2026 instalujete verzi 0.5+ takto:

dotnet tool install -g upgrade-assistant
upgrade-assistant upgrade ./MyApp.sln

Nástroj se vás interaktivně zeptá, který projekt je startovní (vyberte sdílený Xamarin.Forms projekt), a poté provede sérii kroků. Co konkrétně udělá:

  • Konvertuje packages.config na PackageReference v csproj.
  • Přepíše projektový soubor do SDK-style formátu s <TargetFrameworks>net9.0-android;net9.0-ios</TargetFrameworks>.
  • Aktualizuje namespace Xamarin.Forms na Microsoft.Maui.Controls ve všech C# i XAML souborech.
  • Sloučí App.xaml, MainActivity.cs (Android) a AppDelegate.cs (iOS) do nové struktury MauiProgram.cs + Platforms/Android/ + Platforms/iOS/.
  • Aktualizuje nebo nahradí známé NuGet balíčky jejich MAUI verzemi.

Po doběhnutí nečekejte úspěšný build. Realisticky budete mít stovky chyb v jedné středně velké aplikaci. Pracujte iterativně: opravte první namespace chybu, znovu spusťte build, opravte další třídu chyb. Důležité je nezačít s rozsáhlým refaktoringem dříve, než se projekt vůbec zkompiluje, třeba s pomocí Microsoft.Maui.Controls.Compatibility balíčku, který drží Xamarin-era API naživu jako lešení.

Přepis Custom Rendererů na Handlery

Tohle je architektonicky nejnáročnější část migrace a důvod, proč nelze celý přechod plně zautomatizovat. Handler není 1:1 ekvivalent Rendereru. Handler nedědí z nativní třídy, ale obsahuje slovník mapperů, které definují, jak se každá vlastnost MAUI kontroly promítne do nativního widgetu.

Krátké srovnání. Klasický Xamarin Renderer pro vlastní vstupní pole vypadal takto:

// Xamarin.Forms (Android)
[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
public class BorderlessEntryRenderer : EntryRenderer
{
    public BorderlessEntryRenderer(Context context) : base(context) { }

    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
        if (Control != null)
        {
            Control.Background = null;
            Control.SetPadding(0, 0, 0, 0);
        }
    }
}

Stejnou funkci v .NET MAUI implementujete jako mapper na sdíleném Handleru:

// .NET MAUI (sdílený kód v MauiProgram.cs)
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping("BorderlessEntry", (handler, view) =>
{
    if (view is BorderlessEntry)
    {
#if ANDROID
        handler.PlatformView.Background = null;
        handler.PlatformView.SetPadding(0, 0, 0, 0);
#elif IOS
        handler.PlatformView.BorderStyle = UIKit.UITextBorderStyle.None;
#endif
    }
});

Všimněte si tří věcí. Za prvé, kód pro všechny platformy je v jednom souboru s direktivami #if, namísto čtyř per-platform tříd. Za druhé, mapper se nevolá při změně elementu, ale při změně konkrétní vlastnosti, což je efektivnější. Za třetí, máte přístup k handler.PlatformView, který je typovaný na nativní view (na Androidu AppCompatEditText, na iOS UITextField).

V průměrné aplikaci s 15 Custom Renderery zabere tato fáze 5–10 dní. Doporučuji začít od nejjednodušších (změna barvy, padding) a postupovat k těm, které pracují s gesture recognizery nebo nativními event handlery. Ty mají v Handler modelu novou syntaxi přes handler.PlatformView.LayoutChange += ….

Náhrada DependencyService za vestavěnou DI

Xamarin používal DependencyService, statický service locator, který se pro testovatelnost ukázal jako bolavé místo. .NET MAUI místo něj integruje Microsoft.Extensions.DependencyInjection, stejný kontejner, jaký znáte z ASP.NET Core.

Změna je systémová. Místo registrace přes atribut:

// Xamarin.Forms (registrace)
[assembly: Dependency(typeof(FileService))]
public class FileService : IFileService { }

// použití
var service = DependencyService.Get<IFileService>();

Registrujete služby v MauiProgram.cs a injektujete je přes konstruktor:

// .NET MAUI
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder.UseMauiApp<App>();

    builder.Services.AddSingleton<IFileService, FileService>();
    builder.Services.AddTransient<MainPageViewModel>();
    builder.Services.AddTransient<MainPage>();

    return builder.Build();
}

// ViewModel s konstruktorovou injekcí
public class MainPageViewModel
{
    private readonly IFileService _fileService;
    public MainPageViewModel(IFileService fileService) => _fileService = fileService;
}

Výhodou je testovatelnost. ViewModely se nyní dají v jednotkových testech vytvořit s mock závislostmi bez globálního stavu. Pokud používáte CommunityToolkit.Mvvm, doporučuji projít náš návod na MVVM v .NET MAUI s CommunityToolkit.Mvvm, který ukazuje, jak propojit DI s [ObservableProperty] a [RelayCommand] generátory.

XAML, namespace a zlomové změny v ovládacích prvcích

Většinu XAML kódu nemusíte měnit, ale několik zlomových bodů existuje. Klíčové změny v ovládacích prvcích:

  • MasterDetailPage přejmenováno na FlyoutPage (jinak kompatibilní).
  • Frame je v MAUI 9 označen jako legacy. Microsoft doporučuje Border s StrokeShape pro zaoblené rohy.
  • ListView stále funguje, ale CollectionView je výrazně rychlejší díky virtualizaci. V mé migraci jsme přechodem na CollectionView zkrátili první render seznamu z 380 ms na 95 ms na středním Androidu.
  • XAML namespace v hlavičce stránek se mění z xmlns="http://xamarin.com/schemas/2014/forms" na xmlns="http://schemas.microsoft.com/dotnet/2021/maui".
  • OnPlatform a OnIdiom mají jinou syntaxi typového argumentu. Místo x:TypeArguments používáte vlastnost Default.

Aktualizace CI/CD a publikace do App Store

Migrace nekončí ve Visual Studiu. Pipeline pro buildy se mění výrazně. Pokud používáte GitHub Actions, starý workflow pro Xamarin.Android vypadal asi takto:

- uses: actions/setup-dotnet@v3
  with:
    dotnet-version: '6.0.x'
- run: msbuild MyApp.Android/MyApp.Android.csproj /t:SignAndroidPackage /p:Configuration=Release

V .NET MAUI je správný postup tento:

- uses: actions/setup-dotnet@v4
  with:
    dotnet-version: '9.0.x'
- run: dotnet workload install maui-android maui-ios
- run: dotnet publish -f net9.0-android -c Release /p:AndroidKeyStore=true \
       /p:AndroidSigningKeyStore=$KEYSTORE_PATH \
       /p:AndroidSigningStorePass=$KEYSTORE_PASS \
       /p:AndroidSigningKeyAlias=$KEY_ALIAS \
       /p:AndroidSigningKeyPass=$KEY_PASS

Pro iOS přibyla nutnost mít Xcode 16+ na buildovacím agentu (GitHub Actions macos-15). Klíčové změny v oficiální dokumentaci pro iOS publikaci popisují přechod z msbuild na dotnet publish a sloučení Entitlements souboru do Platforms/iOS/Entitlements.plist.

App Store metadata si zachovejte beze změny. Apple ani Google nepoznají, že se změnil framework. Co se ale změní, je velikost balíčku. V mé poslední aplikaci se IPA zmenšil z 38 MB na 22 MB díky PublishTrimmed=true a PublishAot=true pro iOS. U Androidu jsme dosáhli 30% zmenšení APK pomocí R8 fullmode optimalizací, které MAUI šablona zapíná ve výchozím nastavení.

Testování po migraci: co se nejčastěji rozbije

Nejvíce regresí, na které jsem ve svých třech migracích narazil, spadalo do těchto kategorií:

  1. Layout sub-pixel rozdíly. MAUI používá jiný výchozí Spacing v StackLayout a VerticalStackLayout. Vlastní designové systémy s pixelově přesnými mezerami potřebují audit.
  2. Životní cyklus stránek. OnAppearing se v MAUI volá v jiném pořadí vůči OnNavigatedTo než ve Xamarinu. Pokud spouštíte fetch dat v OnAppearing, ověřte, že není zavolán dvakrát při návratu z modálního dialogu. (Tohle mě dostalo v produkční appce při A/B testu, dvojí volání trefilo analytics counter dvakrát.)
  3. Image caching. Xamarin používal vestavěný cache, MAUI ne. Pokud načítáte vzdálené obrázky, doporučuji FFImageLoading.Maui nebo nastavit explicitní CachingEnabled="true" na komponentě Image.
  4. WebView platformně specifické chování. Na iOS MAUI používá WKWebView s odlišnými výchozími hodnotami pro JavaScript bridge. Pokud máte hybridní obrazovky, otestujte je důkladně.
  5. Push notifikace. Plugin.PushNotification v MAUI nefunguje. Použijte Plugin.Firebase.CloudMessaging nebo přímou integraci přes Microsoft.Maui.Essentials.Notifications.

Investujte do snapshot testů. UI testy přes Appium jsou dobrý průchozí krok, ale rychlejší zpětnou vazbu dostanete z vizuálních diff testů na úrovni jednotlivých kontrol pomocí SnapshotTesting.Maui. Před migrací zachyťte baseline, po migraci porovnejte. Diff vám během 30 sekund ukáže, na kterých obrazovkách se layout změnil.

Jak dlouho migrace z Xamarinu na MAUI reálně trvá?

Otázka, kterou dostávám od stakeholderů nejčastěji. Na základě tří dokončených migrací mohu uvést tyto referenční hodnoty:

  • Malá aplikace (do 20 obrazovek, do 5 Custom Rendererů, jen Xamarin.Forms): 1–2 týdny.
  • Středně velká aplikace (40–80 obrazovek, 10–20 Custom Rendererů, závislosti na 5+ pluginech třetích stran): 4–8 týdnů.
  • Velká aplikace s rozsáhlými nativními customizacemi (100+ obrazovek, 25+ Custom Rendererů, vlastní platforma-specifický kód v každém projektu): 3–6 měsíců.

Tyto odhady počítají s jedním zkušeným .NET vývojářem na plný úvazek. Paralelizace více vývojáři přináší zisky jen do 2–3 lidí. Nad tím začínají vznikat merge konflikty v MauiProgram.cs a sdílených stylech. V mé poslední migraci jsme zjistili, že nejefektivnější je rozdělit tým podle vertikál: jeden vývojář vlastní migraci autentizace, druhý katalogu produktů, třetí onboarding flow.

Pokud chcete pochopit, jak má vypadat cílová architektura po migraci, doporučuji nastudovat navigaci v .NET MAUI Shell. Shell je v MAUI doporučený navigation pattern a často se vyplatí současně s migrací přejít z NavigationPage na Shell, protože získáte zdarma deep linking a tab management.

Často kladené otázky

Je Xamarin v roce 2026 ještě podporován?

Ne. Microsoft ukončil oficiální podporu Xamarinu (Xamarin.Forms i klasického Xamarin.iOS/Android) 1. května 2024. Aplikace stále fungují, ale neobdržíte bezpečnostní aktualizace, kompatibilitu s novými verzemi iOS/Androidu, ani podporu pro nové úrovně API.

Mohu migrovat Xamarin.Forms na .NET MAUI automaticky?

Částečně. Nástroj dotnet upgrade-assistant automatizuje přibližně 60–80 % mechanických úprav: konverzi csproj souboru, přejmenování namespace, výměnu NuGet balíčků. Custom Renderery, volání DependencyService a vlastní platformně specifický kód musíte přepsat manuálně.

Co nahrazuje Custom Renderers v .NET MAUI?

Handlery (Microsoft.Maui.Handlers). Místo dědění z platformní třídy definujete mappery, které specifikují, jak se každá vlastnost MAUI kontroly promítne do nativního widgetu. Pro postupnou migraci můžete použít balíček Microsoft.Maui.Controls.Compatibility, který dočasně podporuje staré Renderery.

Jaká je minimální verze iOS a Androidu pro .NET MAUI v roce 2026?

Cílová úroveň musí být minimálně Android 35 (API 35, Android 15) a iOS 18 SDK, aby aplikace prošla validací App Store a Google Play. Minimální podporovaná runtime verze je Android 5.0 (API 21) a iOS 12.2, ale pro nové projekty doporučuji nasadit minimum na Android 8 a iOS 15.

Vyplatí se přepsat aplikaci od nuly místo migrace?

Záleží na velikosti a kvalitě stávajícího kódu. Pro aplikace nad 50 obrazovek je migrace téměř vždy ekonomicky výhodnější, zachováte testy, lokalizace, integrace a doménovou logiku. Přepis od nuly zvažte jen tehdy, pokud máte aplikaci pod 15 obrazovek s vážnými architektonickými problémy, nebo plánujete radikální redesign UX.

Marcus Chen
O Autorovi Marcus Chen

Senior mobile architect with a decade of cross-platform experience. Spent the last five years going deep on .NET MAUI in production.