.NET MAUI nel 2026: Sviluppo Cross-Platform e Domande di Colloquio
Tutorial .NET MAUI per il 2026: sviluppare app cross-platform con .NET 10, handlers, MVVM, HybridWebView. Include le domande di colloquio.

.NET MAUI (Multi-platform App UI) si è affermato come framework cross-platform maturo e pronto per la produzione con .NET 10. Rilasciato come versione Long-Term Support con supporto fino a novembre 2028, .NET MAUI 10 viene distribuito come workload e pacchetti NuGet, offrendo miglioramenti in qualità, performance e nuove API come i potenziamenti di HybridWebView e SafeAreaEdges. Questo tutorial guida attraverso la creazione di un'app cross-platform, spiega l'architettura alla base di MAUI e affronta le domande di colloquio che i responsabili delle assunzioni pongono nel 2026.
.NET 10 è un rilascio Long-Term Support (supportato fino a novembre 2028). MAUI 10 punta su qualità e performance piuttosto che su nuovi controlli UI, rendendolo il rilascio MAUI più stabile. Ora viene distribuito come workload .NET e pacchetti NuGet, abilitando il version pinning per progetto.
Configurare un Progetto .NET MAUI 10 da Zero
Il percorso più rapido verso un'app MAUI funzionante inizia con la .NET CLI. .NET 10 introduce un template di progetto aggiornato che include i service defaults di .NET Aspire, collegando telemetria e service discovery out of the box.
# Install the MAUI workload (if not already present)
dotnet workload install maui
# Create a new MAUI app
dotnet new maui -n CrossPlatformDemo
cd CrossPlatformDemo
# Run on Android emulator
dotnet build -t:Run -f net10.0-androidLa struttura a progetto singolo consolida il codice specifico per piattaforma sotto una cartella Platforms/, condividendo tutto il resto. Il file MauiProgram.cs funge da composition root, dove vengono registrati servizi, font e handlers.
using Microsoft.Extensions.Logging;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Register services for dependency injection
builder.Services.AddSingleton<IApiService, ApiService>();
builder.Services.AddTransient<MainViewModel>();
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}La dependency injection in MAUI segue lo stesso pattern di ASP.NET Core. I servizi Singleton persistono per l'intera durata dell'app, i servizi Transient vengono creati per ogni richiesta, e i servizi Scoped richiedono cautela perché MAUI non possiede un concetto nativo di scope come le richieste HTTP.
Handlers: L'Architettura Dietro al Rendering Cross-Platform
MAUI ha sostituito i renderer di Xamarin.Forms con un'architettura basata su handler. Gli handler mappano ogni controllo cross-platform al suo corrispettivo nativo attraverso un sottile livello di astrazione. La differenza fondamentale: gli handler sono stateless e disaccoppiati dalla virtual view, rendendoli più veloci e più facili da personalizzare.
using Microsoft.Maui.Handlers;
public class CustomEntryHandler : EntryHandler
{
protected override void ConnectHandler(MauiAppCompatEditText platformView)
{
base.ConnectHandler(platformView);
// Remove the default underline on Android
platformView.SetBackgroundColor(Android.Graphics.Color.Transparent);
}
}
// Register in MauiProgram.cs
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Entry, CustomEntryHandler>();
});In .NET 10, i controlli Entry e Editor su Android sono passati da AppCompatEditText a MauiAppCompatEditText, aggiungendo il supporto nativo per l'evento SelectionChanged. I miglioramenti ai CollectionView e CarouselView handler introdotti in .NET 9 sono ora predefiniti su iOS e Mac Catalyst, risolvendo problemi di stabilità di lunga data.
Android 16 Edge-to-Edge: Breaking Change e Correzione Richiesta
Android 16 rimuove il meccanismo di opt-out per la visualizzazione edge-to-edge. Le app che mirano all'API 36 devono gestire correttamente gli inset delle barre di sistema, altrimenti il contenuto viene renderizzato in modo errato. .NET 10 ha introdotto una breaking change silenziosa: in .NET 9, ContentPage rispettava le barre di sistema di default (comportamento Container), ma .NET 10 utilizza di default edge-to-edge (None).
Le app che migrano da .NET 9 a .NET 10 potrebbero vedere il contenuto renderizzato sotto la barra di stato o la barra di navigazione su Android 15+. La correzione richiede l'impostazione esplicita di SafeAreaEdges per ripristinare il comportamento precedente.
La correzione comporta l'aggiunta di uno stile implicito globale in App.xaml:
<!-- App.xaml -->
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CrossPlatformDemo.App">
<Application.Resources>
<ResourceDictionary>
<Style TargetType="ContentPage" ApplyToDerivedTypes="True">
<Setter Property="SafeAreaEdges" Value="Container" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>L'enum SafeAreaEdges fornisce controllo granulare:
None: contenuto edge-to-edge senza padding per safe areaSoftInput: sempre padding per la tastieraContainer: scorrere sotto la tastiera, restare fuori da barre e notchDefault: comportamento predefinito della piattaformaAll: rispettare tutti gli inset della safe area
Questo approccio utilizza la Window Insets API a runtime, rendendolo compatibile con Android 16 dove gli opt-out a livello di manifest non funzionano più.
MVVM con CommunityToolkit.Mvvm: Eliminare il Boilerplate
Il source generator di CommunityToolkit.Mvvm elimina circa l'80% del codice cerimoniale MVVM. Nessuna implementazione manuale di INotifyPropertyChanged, nessun wrapper per i command: gli attributi guidano la generazione del codice.
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
private readonly IApiService _apiService;
public MainViewModel(IApiService apiService)
{
_apiService = apiService;
}
// Source generator creates the 'Title' property with change notification
[ObservableProperty]
private string _title = string.Empty;
// Source generator creates the 'IsLoading' property
[ObservableProperty]
private bool _isLoading;
// Source generator creates an async ICommand
[RelayCommand]
private async Task LoadDataAsync()
{
IsLoading = true;
try
{
Title = await _apiService.FetchTitleAsync();
}
finally
{
IsLoading = false;
}
}
}Il XAML si lega direttamente alle proprietà e ai command generati:
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:CrossPlatformDemo.ViewModels"
x:DataType="vm:MainViewModel">
<VerticalStackLayout Padding="20" Spacing="16">
<Label Text="{Binding Title}"
FontSize="24"
HorizontalOptions="Center" />
<Button Text="Load Data"
Command="{Binding LoadDataCommand}"
IsEnabled="{Binding IsLoading, Converter={StaticResource InverseBoolConverter}}" />
<ActivityIndicator IsRunning="{Binding IsLoading}"
IsVisible="{Binding IsLoading}" />
</VerticalStackLayout>
</ContentPage>L'attributo x:DataType abilita i compiled binding, che sono più veloci dei binding basati su reflection e producono errori a compile-time quando un percorso di binding è errato.
Pronto a superare i tuoi colloqui su .NET?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
XAML Source Generator in .NET 10
.NET MAUI 10 introduce un XAML source generator che compila XAML a build-time invece di parsificarlo a runtime. Questo migliora le performance di avvio e intercetta gli errori XAML durante la compilazione.
Per abilitare la generazione del source XAML, aggiungere la proprietà al file di progetto:
<PropertyGroup>
<MauiXamlInflator>SourceGen</MauiXamlInflator>
</PropertyGroup>.NET 10 Preview 5 ha anche introdotto namespace XML impliciti che eliminano le dichiarazioni boilerplate xmlns. Un file GlobalXmlns.cs può aggregare più namespace:
[assembly: XmlnsDefinition(
"http://schemas.microsoft.com/dotnet/maui/global",
"MyApp.Views")]
[assembly: XmlnsDefinition(
"http://schemas.microsoft.com/dotnet/maui/global",
"MyApp.Controls")]Con questa configurazione, i file XAML diventano più puliti:
<!-- Prima -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyApp.Controls"
x:Class="MyApp.MainPage">
<controls:TagView />
</ContentPage>
<!-- Dopo (con xmlns globale) -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/maui/global"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage">
<TagView />
</ContentPage>HybridWebView in .NET 10: Il Ponte tra Nativo e Web
HybridWebView consente di incorporare contenuti web all'interno di un'app MAUI mantenendo la comunicazione bidirezionale tra C# e JavaScript. .NET 10 aggiunge tre funzionalità: invocazione JavaScript fire-and-forget, eventi di inizializzazione per la configurazione specifica della piattaforma e intercettazione delle richieste web.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// Initialization event for platform-specific tweaks
hybridWebView.WebViewInitialized += (sender, args) =>
{
System.Diagnostics.Debug.WriteLine("WebView ready");
};
}
// Call JavaScript from C#
private async void OnCallJsClicked(object sender, EventArgs e)
{
var result = await hybridWebView.InvokeJavaScriptAsync<string>(
"getFormData",
HybridSampleContext.Default.String
);
await DisplayAlertAsync("Result", result, "OK");
}
// Fire-and-forget: no return type needed (.NET 10)
private async void OnResetClicked(object sender, EventArgs e)
{
await hybridWebView.InvokeJavaScriptAsync("resetForm");
}
}Le eccezioni JavaScript lanciate durante InvokeJavaScriptAsync vengono ora automaticamente inoltrate a .NET come eccezioni, eliminando i fallimenti silenziosi. L'intercettazione delle richieste web consente di modificare header o fornire risposte locali:
webView.WebResourceRequested += (s, e) =>
{
if (e.Uri.ToString().Contains("api/secure"))
{
e.Handled = true;
e.SetResponse(200, "OK", "application/json", GetCustomStream());
}
};API Deprecate e Percorso di Migrazione
.NET MAUI 10 depreca diverse API. Le applicazioni che le utilizzano dovrebbero migrare alle alternative raccomandate.
ListView e celle correlate: ListView, EntryCell, ImageCell, SwitchCell, TextCell e ViewCell sono deprecate. Utilizzare CollectionView, che offre migliori performance e stabilità con i nuovi handler iOS/Mac Catalyst.
MessagingCenter: Reso interno in .NET 10. Sostituire con WeakReferenceMessenger di CommunityToolkit.Mvvm.
Metodi di animazione: FadeTo, RotateTo, ScaleTo e metodi simili sono deprecati. Utilizzare gli equivalenti async: FadeToAsync, RotateToAsync, ScaleToAsync.
TableView: Deprecato a favore di CollectionView.
DisplayAlert/DisplayActionSheet: Sostituiti con DisplayAlertAsync e DisplayActionSheetAsync.
Migrazione da Xamarin.Forms a .NET MAUI
Il supporto per Xamarin.Forms è terminato a maggio 2024. La migrazione a MAUI richiede modifiche strutturali che vanno oltre un semplice scambio di namespace. Ecco una checklist di migrazione basata su conversioni di progetti reali:
Xamarin.Forms non è più supportato da maggio 2024. Le applicazioni ancora in esecuzione su Xamarin comportano rischi di sicurezza e compatibilità. .NET MAUI 10 (LTS, supportato fino a novembre 2028) è il target di migrazione designato.
- Struttura del progetto: Conversione dai progetti specifici per piattaforma al modello single-project di MAUI. Il codice condiviso va nella root, il codice specifico per piattaforma sotto
Platforms/. - Namespace: Sostituire
Xamarin.FormsconMicrosoft.Maui.ControlseXamarin.EssentialsconMicrosoft.Maui.Essentials(ora integrato in MAUI). - Renderer a Handler: I custom renderer devono essere riscritti come handler. L'API degli handler è più semplice, ma la logica di mapping è differente.
- Startup: Sostituire l'inizializzazione
App.xaml.csconMauiProgram.csutilizzando il builder pattern. - Pacchetti NuGet: Molti pacchetti dell'era Xamarin hanno equivalenti MAUI. Verificare la compatibilità prima dell'upgrade.
- Dependency injection: MAUI utilizza
Microsoft.Extensions.DependencyInjectionnativamente. Sostituire qualsiasi container DI di terze parti o chiamate aDependencyService.
Il .NET Upgrade Assistant automatizza parti dei passaggi 1-2, ma gli handler (passaggio 3) e gli aggiustamenti della logica di business richiedono lavoro manuale.
Le Domande di Colloquio più Importanti su .NET MAUI per il 2026
Queste domande riflettono ciò che i team di sviluppo chiedono nei colloqui del 2026, basandosi sull'ecosistema attuale .NET 10. Per ulteriore preparazione ai colloqui C# e .NET, consultare la guida completa ai colloqui .NET.
Come si differenzia l'architettura handler di MAUI dai renderer di Xamarin.Forms?
I renderer in Xamarin.Forms erano strettamente accoppiati sia al controllo cross-platform che alla view nativa, creando una dipendenza bidirezionale. Gli handler in MAUI sono mapper stateless: ricevono notifiche di cambiamento delle proprietà e le applicano alla view nativa attraverso un dizionario di mapping. Questo disaccoppiamento rende gli handler più facili da testare, estendere e riutilizzare. I dizionari PropertyMapper e CommandMapper sostituiscono il pattern di override OnElementPropertyChanged, rendendo la personalizzazione esplicita invece di nasconderla in blocchi switch.
Quali sono le insidie dei lifetime DI specifiche di MAUI?
MAUI supporta i lifetime Singleton, Transient e Scoped, ma Scoped si comporta diversamente rispetto ad ASP.NET Core. Non esiste un confine di scope naturale (come una richiesta HTTP). Un servizio Scoped registrato in MAUI agisce come un Singleton a meno che non vengano creati scope personalizzati manualmente. Errori comuni: registrare un ViewModel come Singleton quando contiene stato specifico della pagina (dati obsoleti durante la navigazione), o registrare una connessione al database come Transient (esaurimento del connection pool). La regola generale: i ViewModel sono Transient, i servizi sono Singleton, e Scoped viene evitato a meno che il ciclo di vita dello scope non sia gestito esplicitamente.
Quando si risponde a domande sulla DI, è importante dimostrare di comprendere come il lifecycle di MAUI differisca dal modello request-scoped di ASP.NET Core. Gli intervistatori cercano la consapevolezza dei memory leak e dei problemi di stato obsoleto specifici delle app mobile a lunga esecuzione.
Come si differenzia il compiled binding dal binding basato su reflection in MAUI?
I binding basati su reflection risolvono i percorsi delle proprietà a runtime usando System.Reflection, il che è lento e produce errori a runtime in caso di errori di battitura. I compiled binding, abilitati con x:DataType, risolvono i percorsi di binding a compile-time. Il compilatore genera codice di accesso diretto alle proprietà, saltando completamente la reflection. Questo migliora il tempo di avvio, riduce le allocazioni di memoria e intercetta gli errori di binding durante la build. In .NET 10, il nuovo source generator XAML ottimizza ulteriormente compilando il XAML a build-time invece di parsificarlo a runtime.
Quali strategie esistono per condividere codice tra un'app MAUI e un backend ASP.NET Core?
L'approccio raccomandato utilizza una shared class library contenente DTO, logica di validazione e regole di business. Sia l'app MAUI che il backend ASP.NET Core fanno riferimento a questa libreria. .NET 10 rafforza questo pattern con la nuova integrazione .NET Aspire per MAUI, che fornisce service discovery e telemetria attraverso progetti mobile e backend. I contratti condivisi con System.Text.Json source generator assicurano la consistenza della serializzazione. Il vincolo chiave: la shared library deve targetizzare net10.0 (non TFM specifici per piattaforma) per rimanere portabile.
Come si differenzia HybridWebView da BlazorWebView in MAUI?
BlazorWebView ospita un'applicazione Blazor completa all'interno dell'app MAUI. I componenti Razor vengono renderizzati in un WebView incorporato, ma il runtime .NET viene eseguito nativamente (non tramite WebAssembly). HybridWebView è più leggero: carica contenuti HTML/CSS/JS statici e fornisce interop C#-to-JavaScript senza l'overhead del framework Blazor. La scelta dipende dal caso d'uso. BlazorWebView è adatto per team con componenti Blazor esistenti che desiderano riutilizzare il codice. HybridWebView è adatto per scenari dove contenuti web esistenti (dashboard, mappe, editor) necessitano di integrazione nativa senza un framework completo.
Altre domande di colloquio .NET su SharpSkill permettono di consolidare questi concetti con esercizi interattivi.
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Fonti
- What's new in .NET MAUI for .NET 10 - documentazione ufficiale con tutte le funzionalità di .NET 10 MAUI
- .NET MAUI GitHub Releases - note di rilascio per le versioni 10.0.x
- Edge-to-Edge Is Now Mandatory in Android 16 - guida alla migrazione per i requisiti di Android 16
- MAUI GitHub Discussion #34171 - feedback della community sulla stabilità di .NET MAUI 10
Cosa Ricordare per gli Sviluppatori .NET MAUI 10
- .NET MAUI 10 è un rilascio LTS (supporto fino a novembre 2028) focalizzato su stabilità e performance, rendendolo una scelta affidabile per app cross-platform in produzione
- Android 16 rende obbligatorio l'edge-to-edge: aggiungere
SafeAreaEdges="Container"come stile globale in App.xaml per ripristinare il comportamento di .NET 9 - Il XAML source generator (
MauiXamlInflator=SourceGen) compila XAML a build-time, migliorando le performance di avvio e intercettando gli errori prima - ListView, TableView e MessagingCenter sono deprecati: migrare a CollectionView e WeakReferenceMessenger
- L'architettura handler sostituisce i renderer Xamarin con mapper stateless, migliorando testabilità attraverso
PropertyMappereCommandMapper - I source generator di CommunityToolkit.Mvvm rimuovono la maggior parte del boilerplate MVVM: gli attributi
[ObservableProperty]e[RelayCommand]sostituiscono le implementazioni manuali - HybridWebView in .NET 10 aggiunge chiamate JavaScript fire-and-forget, eventi di inizializzazione e intercettazione delle richieste per l'integrazione nativo-web
- La preparazione ai colloqui dovrebbe concentrarsi su architettura handler vs. renderer, insidie dei lifetime DI nelle app a lunga esecuzione, compiled binding e trade-off tra HybridWebView e BlazorWebView
Sapresti trovare il bug in .NET?
Uno snippet reale, un bug nascosto, un tentativo al giorno. Senza account per provare.

Scritto da
Anthony Fillion-MailletFondatore di SharpSkill
Sviluppatore fullstack da oltre 10 anni. Guida SharpSkill e risponde di tutto ciò che vi viene pubblicato.
Aggiornato il 14 settembre 2026
Tag
Condividi
Articoli correlati

.NET 10 nel 2026: Nuove Funzionalita, Native AOT e C# 14 per la Preparazione ai Colloqui
.NET 10 viene rilasciato come versione Long-Term Support con miglioramenti Native AOT, extension members di C# 14, la keyword field e app basate su file. Una guida completa sulle nuove funzionalita, i guadagni prestazionali e le conoscenze pronte per i colloqui per sviluppatori .NET nel 2026.

Clean Architecture in .NET 2026: CQRS, MediatR e Domande per Colloqui Tecnici
Una guida completa alla Clean Architecture in .NET con CQRS e MediatR. Include best practice, esempi di codice e domande frequenti nei colloqui per architetti .NET.

Ciclo di vita del DbContext in ASP.NET Core: Performance vs Thread Safety nelle Operazioni Async
Gestione ottimale del ciclo di vita del DbContext in ASP.NET Core: Scoped vs Transient, thread safety nelle operazioni async e ottimizzazione delle performance con DbContext pooling.