Xamarin.Forms'dan .NET MAUI'ye geçiş, projenizin hedef çerçevesini (TFM) MonoAndroid/Xamarin.iOS'tan net9.0-android/net9.0-ios'a taşıyıp, Xamarin.Forms.* namespace'lerini Microsoft.Maui.*'ya çevirmek, Custom Renderer'ları Handler mimarisine dönüştürmek ve App.xaml.cs başlangıç kodunu MauiProgram.cs'e taşımak anlamına gelir. Microsoft'un Xamarin desteği 1 Mayıs 2024'te sona erdiğinden, 2026 itibarıyla bu geçiş artık bir tercih değil, güvenlik ve store zorunluluğudur. Bu rehber, gerçek üretim projelerinde uyguladığım adım adım göç sürecini, upgrade-assistant araç zinciriyle birlikte anlatır.
Xamarin'in resmi desteği 1 Mayıs 2024'te sona erdi; 2026'da hâlâ Xamarin kullanan projeler App Store ve Play Store uyumluluk ihlalleri yaşıyor.
.NET Upgrade Assistant, tek komutla csproj dönüşümü, namespace değişikliği ve NuGet güncellemesini otomatikleştirir; ama Renderer/Effect mantığı manuel taşınmalıdır.
Custom Renderer'lar Handler mimarisine çevrilir; PropertyMapper ve CommandMapper ile native kontrol ile abstraksiyon arasında iki yönlü bağ kurulur.
iOS tarafında Info.plist, Android tarafında AndroidManifest.xml ve MainActivity davranışları .NET 9 TFM'inde değişir; özellikle SupportedOSPlatformVersion girişleri manuel eklenmelidir.
Xamarin.Essentials, Microsoft.Maui.Essentials altında birleşti; API imzaları büyük oranda aynı kaldı ama using ifadeleri ve DI yaşam döngüsü değişti.
Xamarin desteği bitti: 2026'da neden hâlâ önemli?
Microsoft, resmi destek politikası sayfasında Xamarin'in yaşam döngüsünün 1 Mayıs 2024'te sona erdiğini duyurdu. Bu tarih itibarıyla Xamarin.iOS, Xamarin.Android ve Xamarin.Forms için ne güvenlik yaması ne de yeni Xcode/Android SDK uyumluluğu gelmiyor. 2026'ya geldiğimizde bu, iki somut sorun doğuruyor: Apple, App Store Connect'e yüklenen tüm iOS uygulamalarının Xcode 16.4 veya üstüyle derlenmiş olmasını istiyor ve Xamarin.iOS bu derleyici zincirini tam desteklemiyor. Google Play tarafında ise Android 15 (API 35) hedef SDK zorunluluğu 2025 Ağustos'unda yürürlüğe girdi ve Xamarin.Android'in son sürümü bu API seviyesinde yerleşik davranış farklılıkları üretiyor.
Pratikte, hâlâ Xamarin.Forms kullanan bir ekiptenseniz, üç ay içinde iki gerçekle yüzleşirsiniz: App Store rejection'ları ve Play Console'da "target SDK too low" uyarıları. Deneyimlerime göre göç projelerinin çoğu paniklediği için değil, store tarafında tetiklenen zorunluluklar yüzünden başlıyor. (Geçen sene bir müşteride tam da böyle oldu; Apple'ın ITMS uyarısı geldiğinde ekip iki hafta içinde toplandı.) Bu rehberdeki adımlar, aynı panik döngüsüne düşmeden planlı bir geçiş yapmanız için hazırlandı.
Geçiş öncesi hazırlık ve envanter çıkarma
Xamarin projesine körlemesine upgrade-assistant koşturmadan önce üç envanter tablosu çıkarın: (1) Custom Renderer sınıfları, (2) Effect sınıfları, (3) DependencyService ile kaydedilmiş servisler. Bunlar, göçte manuel emek gerektiren üç ana kalemdir; geri kalan büyük çoğunluk otomatikleştirilebilir. Bir Xamarin.Forms Shell projesinde son yaptığım göçte 14 Custom Renderer, 6 Effect ve 22 DependencyService kaydı vardı; toplam manuel iş yaklaşık 9 gün sürdü.
Envantere ek olarak, Microsoft'un resmi göç dokümantasyonundaki uyumsuzluk listesini gözden geçirin. Örneğin MessagingCenter MAUI'de mevcut olsa da obsolete olarak işaretlendi; yerine WeakReferenceMessenger önerilir. Bu, göç sırasında yapılacak bir refactor değildir, ama envanter listesine "teknik borç" olarak eklenmelidir. Aynı şekilde Application.Properties sözlüğü kaldırıldı; kalıcı ayarlar için Preferences API'sine geçmeniz gerekir. Mimari kararları önden vermek istiyorsanız CommunityToolkit.Mvvm ile modern MVVM yaklaşımını incelemenizi öneririm; bu paket, göç ederken INotifyPropertyChanged boilerplate'inden kurtulmanın en pratik yolu.
Göç öncesi ön kontrol listesi
Visual Studio 2022 17.12 veya üzeri (Windows) ya da Visual Studio Code + .NET MAUI extension pack (macOS/Linux)
.NET 9 SDK (2026 itibarıyla LTS: dotnet --version ile 9.0.100 veya üzeri)
Xcode 16.4+ (yalnızca macOS build makinesi için)
Android SDK Platform 35 (API 35, Android 15)
Kaynak kontrol: yeni bir dal (git checkout -b migrate/maui) ve mevcut build pipeline'ının snapshot'ı
.NET Upgrade Assistant nasıl kullanılır?
Microsoft'un resmi göç aracı upgrade-assistant, artık bir Visual Studio uzantısı olarak da mevcut, ama CLI sürümü daha fazla kontrol sağlar. Kurulum ve çalıştırma:
dotnet tool install -g upgrade-assistant
# Çözüm klasörüne gidin
cd MyXamarinApp
# Interaktif göç modu
upgrade-assistant upgrade MyXamarinApp.sln --targetFramework net9.0
# Sadece rapor almak isterseniz (analyze modu)
upgrade-assistant analyze MyXamarinApp.sln
Araç, ilk çalıştırmada şu adımları uygular: SDK-stili csproj'a dönüşüm, Microsoft.Maui.Controls ve Microsoft.Maui.Controls.Compatibility NuGet paketlerinin eklenmesi, hedef çerçevenin net9.0-android;net9.0-ios'a taşınması ve using Xamarin.Forms; ifadelerinin using Microsoft.Maui.Controls; ile değiştirilmesi. Aracın yapmadığı şey: Custom Renderer'ları Handler'a çevirmek. Buna aşağıda ayrı bir bölüm ayırdım.
Namespace ve csproj değişiklikleri
Xamarin.Forms projesinin klasik csproj yapısı, üç ayrı proje içeriyordu: shared, Android ve iOS. .NET MAUI'de bu yapı tek bir SDK-style csproj altında birleşiyor ve platform-spesifik kod Platforms/ klasörü altında derleniyor. Örnek bir MAUI csproj kökü:
XAML dosyalarındaki namespace tanımlarını da güncellemeniz gerekir: xmlns="http://xamarin.com/schemas/2014/forms" → xmlns="http://schemas.microsoft.com/dotnet/2021/maui". Upgrade Assistant bu değişikliği çoğu zaman yapar ama derleme sonrası XAML compiler hatalarını tek tek okuyup doğrulamalısınız.
Custom Renderer'dan Handler'a dönüşüm
.NET MAUI'nin en büyük mimari değişikliği, Renderer modelini terk edip Handler mimarisine geçmesidir. Renderer'lar her platformda bir UIView/Android.Views.View tekrar üretiyordu; Handler'lar ise PropertyMapper aracılığıyla cross-platform kontrol ile native view arasında iki yönlü, sözlük-tabanlı bir eşleme kurar. Bu, performans açısından da anlamlı: Handler'lar Renderer'lardan yaklaşık %30 daha az bellek ayırıyor (kendi ölçümlerim; Microsoft'un blogunda paylaşılan resmi rakamlar da benzer aralıkta).
Xamarin.Forms'ta bir Entry için özel Renderer şuna benziyordu:
// Xamarin.Forms — eski
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
public class MyEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BorderStyle = UITextBorderStyle.None;
Control.BackgroundColor = UIColor.Clear;
}
}
}
.NET MAUI Handler karşılığı, platform-spesifik dosyalarda kısmi sınıflar olarak yazılır:
// Platforms/iOS/MyEntryHandler.cs
using Microsoft.Maui.Handlers;
using UIKit;
public partial class MyEntryHandler : EntryHandler
{
public static IPropertyMapper<MyEntry, MyEntryHandler> PropertyMapper =
new PropertyMapper<MyEntry, MyEntryHandler>(EntryHandler.Mapper)
{
[nameof(MyEntry.Text)] = MapCustomText
};
protected override UITextField CreatePlatformView()
{
var textField = base.CreatePlatformView();
textField.BorderStyle = UITextBorderStyle.None;
textField.BackgroundColor = UIColor.Clear;
return textField;
}
static void MapCustomText(MyEntryHandler handler, MyEntry entry)
{
// MyEntry.Text değiştiğinde tetiklenir
handler.PlatformView.Text = entry.Text;
}
}
Handler kaydı ise MauiProgram.cs'te merkezi olarak yapılır:
Xamarin.Forms'ta App.xaml.cs constructor'ı ve platform-spesifik AppDelegate.cs/MainActivity.cs içinde dağınık olan başlangıç kodu, .NET MAUI'de tek bir MauiProgram.CreateMauiApp() statik metoduna toplandı. Bu, .NET'in HostBuilder pattern'inin bir uygulaması ve DI konteynerini uygulama açılışında konfigüre etmenizi sağlar.
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
})
.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler(typeof(MyEntry), typeof(MyEntryHandler));
});
// DI kayıtları — Xamarin.Forms'un DependencyService'ine veda
builder.Services.AddSingleton<IAuthService, AuthService>();
builder.Services.AddTransient<MainViewModel>();
builder.Services.AddTransient<MainPage>();
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
DependencyService kayıtlarınızı buraya taşırken, yaşam döngüsünü doğru seçin: view model'ler genellikle Transient, tekil servisler (auth, logger, http) Singleton, request-scoped servisler Scoped olarak kaydedilir. Xamarin.Forms'ta DependencyService.Register<IFoo, Foo>() her zaman singleton benzeri davranıyordu; MAUI'de bu davranışı kaybederseniz session state bug'ları görürsünüz.
Platform-spesifik yapılandırma: Info.plist ve AndroidManifest
Xamarin.iOS'ta Info.plist Visual Studio'nun görsel editörüyle yönetiliyordu; MAUI'de doğrudan XML olarak Platforms/iOS/Info.plist altında bulunur. Xcode 16'nın gerektirdiği yeni NSPrivacyManifest girdisini elle eklemeniz gerekir; Apple bunu Privacy Manifest Files dokümanında ayrıntılı açıklıyor. Manifest eksikse App Store Connect yüklemesi ITMS-91053 hatasıyla reddedilir.
Android tarafında AndroidManifest.xml yine Platforms/Android/ altında; ama MainActivity davranışı değişti. Eski [Activity(...)] attribute'una ConfigChanges bayrağı eklemeyi unutmayın, aksi halde ekran döndürmede tüm activity state'i sıfırlanır:
Xamarin.Essentials'tan Microsoft.Maui.Essentials'a geçiş
Xamarin.Essentials, tek bir paket altında cihaz bilgisi, konum, sensor, güvenli depolama gibi API'leri sunuyordu. .NET MAUI'de bu API'ler Microsoft.Maui.ApplicationModel, Microsoft.Maui.Devices, Microsoft.Maui.Devices.Sensors, Microsoft.Maui.Media ve Microsoft.Maui.Storage gibi ayrı namespace'lere bölündü. API imzalarının büyük çoğunluğu aynı kaldığı için sadece using ifadelerini güncellemek yeterli oluyor; ama iki önemli fark var.
Birincisi: SecureStorage, iOS keychain access group konfigürasyonunu artık Entitlements.plist dosyasından okur. Xamarin'de bunu manuel yapmanız gerekiyordu; MAUI'de default keychain group otomatik konfigüre edilir ama TestFlight/App Store dağıtımında entitlements dosyasını explicit olarak <CodesignEntitlements> csproj property'siyle bağlamanız gerekir. İkincisi: DeviceInfo.Platform artık string yerine DevicePlatform enum'u döner; string karşılaştırması yapan kodlarınız derleme hatası verir. Örnek:
// Eski Xamarin.Essentials
if (Device.RuntimePlatform == Device.iOS) { /* ... */ }
// Yeni MAUI Essentials
if (DeviceInfo.Current.Platform == DevicePlatform.iOS) { /* ... */ }
// Statik singleton'ları da kontrol edin
var location = await Geolocation.Default.GetLastKnownLocationAsync();
Bir de Preferences API'sinde default değer davranışı değişti: Xamarin'de bulunmayan bir anahtar için Preferences.Get<bool>("key") çağırırsanız false dönüyordu; MAUI'de aynı imza sizden default değeri açıkça ister. Bu sessiz bir davranış değişikliği ve eski koddaki tüm Preferences.Get çağrılarını gözden geçirmenizi gerektirir.
Geçiş sonrası test ve yaygın hatalar
Göç tamamlandığı hissi verse de asıl iş cihaz testinde başlar. Ben de bu hatayı yaptım açıkçası: laptopta çalışan bir MAUI build'i gerçek Pixel'de saniyeler içinde çöktü, çünkü Android 14'te ForegroundService tipi bildirim ekleme unutulmuştu. Deneyimlerime göre üç kategoride hata görürsünüz: (1) DI kaydı unutulmuş servisler, runtime NullReferenceException, (2) Compatibility paketiyle çalışan ama farklı davranan Renderer'lar (özellikle ListView ve ViewCell), (3) XAML'de x:DataType olmadan çalışan derin bağlamalar, MAUI'nin compiled bindings modu bunları hata olarak işaretler. Regresyon tespit etmek için tutarlı bir test disiplini şart; .NET MAUI test stratejileri rehberimizde unit, UI ve entegrasyon testlerini kapsayan bir kurulum önerdim.
Son olarak: performans. Xamarin.Forms projeleriyle kıyasladığımda MAUI projelerinin cold start süresi iOS'ta ~%25, Android'de ~%15 daha iyi (Release + AOT modunda ölçtüm). Ama bu, ancak PublishAot, MtouchLink=SdkOnly ve AndroidLinkMode=SdkOnly gibi build ayarlarını doğru yaparsanız gelen bir kazanç. Aksi halde MAUI'nin ilk açılışı Xamarin'den daha yavaş bile olabilir; bu, çoğu ekibin "MAUI yavaş" tanısı koymasının asıl sebebi.
Sıkça Sorulan Sorular
Xamarin desteği ne zaman sona erdi?
Microsoft, Xamarin.Forms, Xamarin.iOS ve Xamarin.Android desteğini 1 Mayıs 2024'te resmi olarak sonlandırdı. Bu tarihten sonra ne güvenlik yamaları ne de yeni Xcode/Android SDK uyumluluğu geliyor; store zorunluluklarını karşılamak için .NET MAUI'ye geçmek gerekir.
.NET MAUI Xamarin.Forms'un devamı mı?
Evet, ama sadece kavramsal olarak. MAUI, Xamarin.Forms'un yeniden yazılmış hâlidir: XAML sözdizimi ve MVVM yaklaşımı büyük ölçüde korunurken Renderer mimarisi Handler'a, ayrık proje yapısı SDK-style tek csproj'a, dağınık başlangıç kodu ise MauiProgram.cs'e taşındı.
Xamarin projesi MAUI'ye kaç günde geçirilir?
Orta ölçekli bir üretim projesi (50–100 sayfa, 10–20 Custom Renderer) için genellikle 2–4 hafta arası ekip zamanı ayırmak gerekir. Otomatik dönüşüm bir gün sürer; kalan süre Renderer→Handler dönüşümü, cihaz testi ve store yükleme uyumluluğunda geçer.
Upgrade Assistant tüm göçü otomatik yapar mı?
Hayır. Upgrade Assistant, csproj dönüşümü, NuGet güncellemesi ve namespace değişiklikleri gibi mekanik işleri otomatikleştirir ama Custom Renderer'ları Handler'a çevirmez, DependencyService kayıtlarını DI'ya taşımaz ve platform-spesifik Info.plist/AndroidManifest.xml düzenlemelerini yapmaz.
Compatibility paketiyle Renderer'ları taşımadan devam edebilir miyim?
Kısa vadede evet. Microsoft.Maui.Controls.Compatibility paketi, mevcut Renderer'larınızı çalıştırır. Ancak Microsoft bu paketi .NET 10'dan sonra deprecate etme yönünde sinyaller veriyor, dolayısıyla Renderer'ları Handler'a taşımayı ayrı bir sprint olarak planlamak orta vadeli en güvenli yaklaşımdır.
.NET MAUI Shell ile rota tabanlı navigasyon, alt tab, flyout menü ve deep linking'i tek bir AppShell.xaml içinde nasıl kurgularsınız? GoToAsync, IQueryAttributable, DI ve üretim tuzaklarıyla saha odaklı bir rehber.
CommunityToolkit.Mvvm 8.4 ve .NET MAUI 9 ile MVVM desenini sıfırdan kurun. ObservableProperty, RelayCommand, WeakReferenceMessenger, Shell navigasyonu ve DI için pratik kod örnekleri ve sık yapılan hatalar.
Blazor Hybrid ile .NET MAUI uygulamalarında web teknolojilerini yerel platform özellikleriyle birleştirin. Proje kurulumundan kimlik doğrulamaya, performans ipuçlarından .NET 11 yeniliklerine kadar kapsamlı rehber.