.NET MAUI en 2026 : Développement Cross-Platform et Questions d'Entretien

Tutoriel .NET MAUI pour 2026 : créer des applications cross-platform avec .NET 10, handlers, MVVM, HybridWebView. Questions d'entretien avec réponses détaillées.

Développement cross-platform .NET MAUI avec C# ciblant Android, iOS et desktop depuis une base de code unique

.NET MAUI (Multi-platform App UI) s'est imposé comme un framework cross-platform de qualité production avec .NET 10. Publié en tant que version Long-Term Support maintenue jusqu'en novembre 2028, .NET MAUI 10 est distribué sous forme de workload et de packages NuGet, offrant une qualité, des performances et de nouvelles API améliorées telles que les évolutions de HybridWebView et SafeAreaEdges. Ce tutoriel couvre la création d'une application cross-platform, l'architecture qui fait fonctionner MAUI, et les questions d'entretien que les recruteurs posent en 2026.

.NET MAUI 10 LTS

.NET 10 est une version Long-Term Support (maintenue jusqu'en novembre 2028). MAUI 10 privilégie la qualité et les performances plutôt que l'ajout de nouveaux contrôles UI — ce qui en fait la version la plus stable de MAUI à ce jour. Le framework est désormais distribué en tant que workload .NET et packages NuGet, permettant le verrouillage de version par projet.

Mise en Place d'un Projet .NET MAUI 10 de Zéro

Le chemin le plus rapide vers une application MAUI fonctionnelle commence avec la CLI .NET. .NET 10 introduit un template de projet mis à jour qui inclut les configurations par défaut d'Aspire, connectant la télémétrie et la découverte de services nativement.

bash
# Installer le workload MAUI (si pas déjà présent)
dotnet workload install maui

# Créer une nouvelle application MAUI
dotnet new maui -n CrossPlatformDemo
cd CrossPlatformDemo

# Exécuter sur un émulateur Android
dotnet build -t:Run -f net10.0-android

La structure mono-projet consolide le code spécifique à chaque plateforme dans un dossier Platforms/ tout en partageant le reste. Le fichier MauiProgram.cs sert de racine de composition — c'est là que les services, polices et handlers sont enregistrés.

MauiProgram.cscsharp
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();
    }
}

L'injection de dépendances dans MAUI suit le même modèle qu'ASP.NET Core. Les services Singleton persistent pendant toute la durée de vie de l'application, les services Transient sont créés à chaque demande, et les services Scoped — bien que disponibles — nécessitent de la prudence car MAUI ne dispose pas d'un concept de scope intégré comme les requêtes HTTP.

Handlers : L'Architecture Derrière le Rendu Cross-Platform

MAUI a remplacé les renderers de Xamarin.Forms par une architecture de handlers. Les handlers associent chaque contrôle cross-platform à son équivalent natif via une fine couche d'abstraction. La différence clé : les handlers sont sans état et découplés de la vue virtuelle, ce qui les rend plus rapides et plus faciles à personnaliser.

CustomEntryHandler.cs — Customizing the Entry control on Androidcsharp
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>();
});

Dans .NET 10, les contrôles Android Entry et Editor sont passés de AppCompatEditText à MauiAppCompatEditText, ajoutant la prise en charge native de l'événement SelectionChanged. Les handlers améliorés pour CollectionView et CarouselView introduits dans .NET 9 sont désormais les handlers par défaut sur iOS et Mac Catalyst, résolvant des problèmes de stabilité de longue date.

MVVM avec CommunityToolkit.Mvvm : Éliminer le Code Répétitif

Le générateur de code source CommunityToolkit.Mvvm élimine environ 80 % de la cérémonie MVVM. Plus besoin d'implémentation manuelle de INotifyPropertyChanged, plus de wrappers de commandes — les attributs pilotent la génération de code.

MainViewModel.cscsharp
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;
        }
    }
}

Le XAML se lie directement aux propriétés et commandes générées :

xml
<!-- 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'attribut x:DataType active les bindings compilés, qui sont plus rapides que les bindings par réflexion et produisent des erreurs à la compilation lorsqu'un chemin de binding est incorrect.

Prêt à réussir tes entretiens .NET ?

Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.

HybridWebView dans .NET 10 : Le Pont entre Natif et Web

HybridWebView permet d'intégrer du contenu web dans une application MAUI tout en maintenant une communication bidirectionnelle entre C# et JavaScript. .NET 10 ajoute trois fonctionnalités : l'invocation JavaScript de type fire-and-forget, les événements d'initialisation pour la configuration spécifique à la plateforme, et l'interception des requêtes web.

MainPage.xaml.cs — HybridWebView interactioncsharp
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        // Initialization event for platform-specific tweaks
        hybridWebView.WebViewInitialized += (sender, args) =>
        {
            // Access the native platform view after initialization
            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",  // JS function name
            HybridSampleContext.Default.String  // JSON serialization context
        );
        await DisplayAlert("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 JavaScript correspondant reçoit les appels et peut envoyer des messages en retour vers C# :

wwwroot/index.html (HybridWebView content)javascript
function getFormData() {
    return JSON.stringify({
        name: document.getElementById('name').value,
        email: document.getElementById('email').value
    });
}

function resetForm() {
    document.getElementById('name').value = '';
    document.getElementById('email').value = '';
}

Les exceptions JavaScript levées pendant InvokeJavaScriptAsync sont désormais automatiquement transmises vers .NET sous forme d'exceptions, éliminant les échecs silencieux.

SafeAreaEdges : Des Mises en Page Pixel-Perfect sur Chaque Appareil

.NET MAUI 10 introduit la propriété SafeAreaEdges sur Layout, ContentView, ContentPage, Border et ScrollView. La nouvelle énumération (None, SoftInput, Container, Default, All) remplace l'ancien Page.UseSafeArea spécifique à iOS par une approche cross-platform.

xml
<!-- Granular safe area control per section -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             SafeAreaEdges="All">
    <Grid RowDefinitions="Auto,*,Auto">
        <!-- Header respects all safe areas -->
        <Border Grid.Row="0" SafeAreaEdges="Container">
            <Label Text="Header" />
        </Border>

        <!-- Content scrolls under safe areas -->
        <ScrollView Grid.Row="1" SafeAreaEdges="SoftInput">
            <VerticalStackLayout Padding="16">
                <Entry Placeholder="Type here..." />
            </VerticalStackLayout>
        </ScrollView>

        <!-- Footer avoids home indicator -->
        <Border Grid.Row="2" SafeAreaEdges="Container">
            <Label Text="Footer" />
        </Border>
    </Grid>
</ContentPage>

SoftInput ajuste le contenu lorsque le clavier virtuel apparaît. Container évite les encoches, les boîtiers de capteurs et l'indicateur d'accueil. Ces valeurs peuvent être combinées par contrôle, permettant à un en-tête de se placer sous la barre de statut tandis que la zone de contenu reste dégagée.

Migration de Xamarin.Forms vers .NET MAUI

Xamarin.Forms a atteint sa fin de support en mai 2024. La migration vers MAUI implique des changements structurels au-delà d'un simple remplacement de namespaces. Voici une checklist de migration basée sur des conversions de projets réels :

Fin de vie Xamarin

Xamarin.Forms n'est plus supporté depuis mai 2024. Les applications tournant encore sur Xamarin présentent des risques de sécurité et de compatibilité. .NET MAUI 10 (LTS, supporté jusqu'en novembre 2028) est la cible de migration désignée.

  1. Structure du projet — Convertir les projets spécifiques à chaque plateforme vers le modèle mono-projet MAUI. Déplacer le code partagé vers la racine, le code plateforme sous Platforms/.
  2. Namespaces — Remplacer Xamarin.Forms par Microsoft.Maui.Controls et Xamarin.Essentials par Microsoft.Maui.Essentials (désormais intégré à MAUI).
  3. Renderers vers Handlers — Les renderers personnalisés doivent être réécrits en handlers. L'API des handlers est plus simple mais la logique de mapping diffère.
  4. Démarrage — Remplacer l'initialisation dans App.xaml.cs par MauiProgram.cs utilisant le pattern builder.
  5. Packages NuGet — De nombreux packages de l'ère Xamarin ont des équivalents MAUI. Vérifier la compatibilité avant la mise à niveau.
  6. Injection de dépendances — MAUI utilise Microsoft.Extensions.DependencyInjection nativement. Remplacer tout conteneur DI tiers ou les appels à DependencyService.

Le .NET Upgrade Assistant automatise une partie des étapes 1-2, mais les handlers (étape 3) et les ajustements de logique métier nécessitent un travail manuel.

Questions d'Entretien .NET MAUI Incontournables en 2026

Ces questions reflètent ce que les équipes de recrutement demandent en 2026, en se basant sur l'écosystème .NET 10 actuel.

En quoi l'architecture de handlers de MAUI diffère-t-elle des renderers de Xamarin.Forms ?

Les renderers dans Xamarin.Forms étaient étroitement couplés à la fois au contrôle cross-platform et à la vue native, créant une dépendance bidirectionnelle. Les handlers dans MAUI sont des mappers sans état : ils reçoivent des notifications de changement de propriétés et les appliquent à la vue native via un dictionnaire de mappers. Ce découplage signifie que les handlers sont plus faciles à tester, étendre et réutiliser. Les dictionnaires PropertyMapper et CommandMapper remplacent le pattern d'override OnElementPropertyChanged, rendant la personnalisation explicite plutôt qu'enfouie dans des instructions switch.

Quels sont les pièges des durées de vie DI spécifiques à MAUI ?

MAUI supporte les durées de vie Singleton, Transient et Scoped, mais Scoped se comporte différemment d'ASP.NET Core. Il n'y a pas de limite de scope naturelle (comme une requête HTTP). Un service Scoped enregistré dans MAUI se comporte comme un Singleton à moins que des scopes personnalisés ne soient créés manuellement. Erreurs courantes : enregistrer un ViewModel en Singleton alors qu'il contient un état spécifique à la page (données périmées lors de la navigation), ou enregistrer une connexion de base de données en Transient (épuisement du pool de connexions). La règle générale : les ViewModels sont Transient, les services sont Singleton, et Scoped est évité sauf si le cycle de vie du scope est géré explicitement.

Conseil d'entretien

Lors de la réponse aux questions sur l'injection de dépendances, il est important de démontrer une compréhension de la façon dont le cycle de vie de MAUI diffère du modèle de scope par requête d'ASP.NET Core. Les recruteurs recherchent une conscience des fuites mémoire et des problèmes d'état périmé spécifiques aux applications mobiles de longue durée.

Quelle est la différence entre le binding compilé et le binding par réflexion dans MAUI ?

Les bindings par réflexion résolvent les chemins de propriétés au runtime en utilisant System.Reflection, ce qui est lent et produit des erreurs au runtime pour les fautes de frappe. Les bindings compilés, activés avec x:DataType, résolvent les chemins de binding à la compilation. Le compilateur génère du code d'accès direct aux propriétés, contournant entièrement la réflexion. Cela améliore le temps de démarrage, réduit les allocations mémoire et détecte les erreurs de binding pendant le build. Dans .NET 10, le nouveau générateur de source XAML optimise encore davantage en compilant le XAML au moment du build plutôt qu'en le parsant au runtime.

Quelles stratégies existent pour partager du code entre une application MAUI et un backend ASP.NET Core ?

L'approche recommandée utilise une bibliothèque de classes partagée contenant les DTOs, la logique de validation et les règles métier. L'application MAUI et le backend ASP.NET Core référencent tous deux cette bibliothèque. .NET 10 renforce ce pattern avec la nouvelle intégration .NET Aspire pour MAUI, qui fournit la découverte de services et la télémétrie entre projets mobiles et backend. Les contrats partagés utilisant les générateurs de source System.Text.Json assurent la cohérence de la sérialisation. La contrainte clé : la bibliothèque partagée doit cibler net10.0 (pas de TFMs spécifiques à une plateforme) pour rester portable.

Quelle est la différence entre HybridWebView et BlazorWebView dans MAUI ?

BlazorWebView héberge une application Blazor complète à l'intérieur de l'application MAUI. Les composants Razor sont rendus dans une WebView intégrée, mais le runtime .NET s'exécute nativement (pas via WebAssembly). HybridWebView est plus léger : il charge du contenu HTML/CSS/JS statique et fournit une interopérabilité C#-vers-JavaScript sans la surcharge du framework Blazor. Le choix dépend du cas d'usage. BlazorWebView convient aux équipes ayant des composants Blazor existants souhaitant la réutilisation de code. HybridWebView convient aux scénarios où du contenu web existant (tableaux de bord, cartes, éditeurs) nécessite une intégration native sans framework complet.

Pour approfondir ces concepts, il est possible de pratiquer davantage de questions d'entretien .NET sur SharpSkill avec des exercices interactifs.

Passe à la pratique !

Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.

Conclusion

  • .NET MAUI 10 est une version LTS (support jusqu'en novembre 2028) axée sur la stabilité et les performances, pas sur l'ajout constant de fonctionnalités — ce qui en fait un choix fiable pour les applications cross-platform en production
  • L'architecture de handlers remplace les renderers Xamarin par des mappers sans état, améliorant la testabilité et la personnalisation via PropertyMapper et CommandMapper
  • Les générateurs de source CommunityToolkit.Mvvm suppriment la majeure partie du code répétitif MVVM — les attributs [ObservableProperty] et [RelayCommand] remplacent les implémentations manuelles de INotifyPropertyChanged et de commandes
  • HybridWebView dans .NET 10 ajoute les appels JavaScript fire-and-forget, les événements d'initialisation et l'interception de requêtes pour l'intégration native-web
  • SafeAreaEdges offre un contrôle granulaire et cross-platform sur les encoches, claviers et barres système, remplaçant l'ancien UseSafeArea limité à iOS
  • La migration depuis Xamarin.Forms nécessite la réécriture des handlers et la refactorisation du démarrage — le .NET Upgrade Assistant gère les changements de namespaces mais un travail manuel reste nécessaire pour les renderers personnalisés
  • La préparation aux entretiens devrait se concentrer sur l'architecture handlers vs renderers, les pièges de durée de vie DI dans les applications longue durée, les bindings compilés et les compromis HybridWebView vs BlazorWebView

Passe à la pratique !

Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.

Tags

#.net maui
#cross-platform
#tutoriel
#entretien
#migration xamarin
#.net 10
#développement mobile

Partager

Articles similaires