.NET MAUI w 2026: Kompletny Przewodnik po Programowaniu Cross-Platform i Pytania Rekrutacyjne

Poznaj .NET MAUI 10 w 2026 roku - od konfiguracji projektu, przez architekturę handlerów, MVVM z CommunityToolkit, HybridWebView, po migrację z Xamarin i kluczowe pytania rekrutacyjne.

.NET MAUI cross-platform development tutorial 2026

.NET MAUI (Multi-platform App UI) osiągnął pełną dojrzałość produkcyjną wraz z wydaniem .NET 10. Jako wersja z długoterminowym wsparciem (LTS, obsługiwana do listopada 2028 roku), .NET MAUI 10 koncentruje się na jakości i wydajności, dostarczając nowe API takie jak HybridWebView oraz SafeAreaEdges. Ten artykuł przedstawia praktyczny przewodnik po tworzeniu aplikacji cross-platform, omawia architekturę frameworka oraz kluczowe pytania pojawiające się na rozmowach kwalifikacyjnych w 2026 roku.

.NET MAUI 10 LTS

.NET 10 to wydanie z długoterminowym wsparciem (do listopada 2028). MAUI 10 kładzie nacisk na stabilność i wydajność — jest to najbardziej dojrzałe wydanie MAUI dotychczas. Framework jest teraz dystrybuowany jako workload .NET oraz pakiety NuGet, co umożliwia przypinanie wersji per projekt.

Konfiguracja projektu .NET MAUI 10 od podstaw

Najszybszą drogą do uruchomienia aplikacji MAUI jest wykorzystanie .NET CLI. .NET 10 wprowadza zaktualizowany szablon projektu, który zawiera wsparcie dla .NET Aspire, zapewniając telemetrię i odkrywanie usług.

bash
# 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-android

Struktura pojedynczego projektu konsoliduje kod specyficzny dla platform w katalogu Platforms/, współdzieląc resztę. Plik MauiProgram.cs pełni rolę composition root — to tutaj rejestruje się serwisy, czcionki i handlery.

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

Wstrzykiwanie zależności w MAUI stosuje ten sam wzorzec co ASP.NET Core. Serwisy Singleton utrzymują się przez cały czas życia aplikacji, serwisy Transient są tworzone przy każdym żądaniu, natomiast serwisy Scoped — choć dostępne — wymagają ostrożności, ponieważ MAUI nie posiada wbudowanej koncepcji zakresu jak żądania HTTP.

Handlery: architektura renderowania cross-platform

MAUI zastąpiło renderery Xamarin.Forms architekturą handlerów. Handlery mapują każdy kontroler cross-platform na jego natywny odpowiednik poprzez cienką warstwę abstrakcji. Kluczowa różnica polega na tym, że handlery są bezstanowe i oddzielone od widoku wirtualnego, co czyni je szybszymi i łatwiejszymi do dostosowania.

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

W .NET 10 kontrolki Entry i Editor na Androidzie przeszły z AppCompatEditText na MauiAppCompatEditText, dodając natywne wsparcie dla zdarzenia SelectionChanged. Ulepszone handlery CollectionView i CarouselView wprowadzone w .NET 9 są teraz domyślne na iOS i Mac Catalyst.

MVVM z CommunityToolkit.Mvvm: eliminacja kodu boilerplate

Generator kodu źródłowego CommunityToolkit.Mvvm eliminuje około 80% ceremonii MVVM. Koniec z ręczną implementacją INotifyPropertyChanged, koniec z wrapperami komend — atrybuty sterują generowaniem kodu.

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;
        }
    }
}

XAML wiąże się bezpośrednio z wygenerowanymi właściwościami i komendami:

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>

Atrybut x:DataType włącza kompilowane bindowania, które są szybsze od bindowań opartych na refleksji i generują błędy kompilacji, gdy ścieżka bindowania jest nieprawidłowa.

Gotowy na rozmowy o .NET?

Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.

HybridWebView w .NET 10: łączenie natywnego z webowym

HybridWebView umożliwia osadzanie treści webowych wewnątrz aplikacji MAUI przy zachowaniu dwukierunkowej komunikacji między C# a JavaScript. .NET 10 dodaje trzy możliwości: wywołania JavaScript typu fire-and-forget, zdarzenia inicjalizacji dla konfiguracji specyficznej dla platformy oraz przechwytywanie żądań webowych.

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");
    }
}

Odpowiadający JavaScript odbiera wywołania i może wysyłać wiadomości z powrotem do 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 = '';
}

Wyjątki JavaScript rzucane podczas InvokeJavaScriptAsync są teraz automatycznie przekazywane do .NET jako wyjątki, eliminując ciche awarie.

SafeAreaEdges: perfekcyjne układy na każdym urządzeniu

.NET MAUI 10 wprowadza właściwość SafeAreaEdges dla Layout, ContentView, ContentPage, Border i ScrollView. Nowy enum (None, SoftInput, Container, Default, All) zastępuje starsze podejście Page.UseSafeArea specyficzne dla iOS rozwiązaniem 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 dostosowuje zawartość, gdy pojawia się klawiatura ekranowa. Container unika wcięć, obudów sensorów i wskaźnika home. Wartości te można łączyć per kontrolka.

Migracja z Xamarin.Forms do .NET MAUI

Wsparcie dla Xamarin.Forms zakończyło się w maju 2024 roku. Migracja do MAUI wymaga zmian strukturalnych wykraczających poza prostą zamianę przestrzeni nazw.

Koniec wsparcia Xamarin

Xamarin.Forms nie jest wspierany od maja 2024 roku. Aplikacje nadal działające na Xamarin niosą ze sobą ryzyko bezpieczeństwa i kompatybilności. .NET MAUI 10 (LTS, wsparcie do listopada 2028) jest wyznaczonym celem migracji.

  1. Struktura projektu — konwersja z projektów specyficznych dla platform do modelu pojedynczego projektu MAUI
  2. Przestrzenie nazw — zamiana Xamarin.Forms na Microsoft.Maui.Controls i Xamarin.Essentials na Microsoft.Maui.Essentials
  3. Renderery na handlery — niestandardowe renderery muszą zostać przepisane jako handlery
  4. Inicjalizacja — zastąpienie inicjalizacji App.xaml.cs wzorcem builder w MauiProgram.cs
  5. Pakiety NuGet — wiele pakietów z ery Xamarin ma odpowiedniki MAUI
  6. Wstrzykiwanie zależności — MAUI natywnie używa Microsoft.Extensions.DependencyInjection

Najważniejsze pytania rekrutacyjne .NET MAUI na 2026 rok

Poniższe pytania odzwierciedlają to, o co pytają zespoły rekrutacyjne w 2026 roku.

Czym architektura handlerów MAUI różni się od rendererów Xamarin.Forms?

Renderery w Xamarin.Forms były ściśle powiązane zarówno z kontrolką cross-platform, jak i widokiem natywnym, tworząc dwukierunkową zależność. Handlery w MAUI to bezstanowe mappery: otrzymują powiadomienia o zmianach właściwości i stosują je do widoku natywnego poprzez słownik mapperów. Słowniki PropertyMapper i CommandMapper zastępują wzorzec nadpisywania OnElementPropertyChanged, czyniąc dostosowywanie jawnym.

Jakie są pułapki związane z czasem życia DI specyficzne dla MAUI?

MAUI obsługuje czasy życia Singleton, Transient i Scoped, ale Scoped zachowuje się inaczej niż w ASP.NET Core. Nie ma naturalnej granicy zakresu (jak żądanie HTTP). Typowe błędy: rejestrowanie ViewModelu jako Singleton, gdy przechowuje stan specyficzny dla strony (nieaktualne dane przy nawigacji), lub rejestrowanie połączenia z bazą danych jako Transient (wyczerpanie puli połączeń).

Wskazówka rekrutacyjna

Odpowiadając na pytania o DI, należy wykazać zrozumienie, czym cykl życia MAUI różni się od modelu request-scoped ASP.NET Core. Rekruterzy szukają świadomości wycieków pamięci i problemów z przestarzałym stanem specyficznych dla długo działających aplikacji mobilnych.

Czym kompilowane bindowanie różni się od bindowania opartego na refleksji?

Bindowania oparte na refleksji rozwiązują ścieżki właściwości w runtime przy użyciu System.Reflection, co jest wolne i generuje błędy runtime przy literówkach. Kompilowane bindowania, włączane za pomocą x:DataType, rozwiązują ścieżki bindowań w czasie kompilacji. Kompilator generuje bezpośredni kod dostępu do właściwości, pomijając refleksję. Poprawia to czas uruchomienia, redukuje alokacje pamięci i wychwytuje błędy bindowań podczas budowania.

Jakie strategie istnieją do współdzielenia kodu między aplikacją MAUI a backendem ASP.NET Core?

Zalecane podejście wykorzystuje współdzieloną bibliotekę klas zawierającą DTO, logikę walidacji i reguły biznesowe. Zarówno aplikacja MAUI, jak i backend ASP.NET Core referencjonują tę bibliotekę. .NET 10 wzmacnia ten wzorzec integracją .NET Aspire dla MAUI, zapewniającą odkrywanie usług i telemetrię między projektami mobilnymi i backendowymi.

Czym HybridWebView różni się od BlazorWebView w MAUI?

BlazorWebView hostuje pełną aplikację Blazor wewnątrz aplikacji MAUI. Komponenty Razor renderują się w osadzonym WebView, ale runtime .NET wykonuje się natywnie (nie przez WebAssembly). HybridWebView jest lżejszy: ładuje statyczną zawartość HTML/CSS/JS i zapewnia interop C#-JavaScript bez narzutu frameworka Blazor. BlazorWebView pasuje do zespołów z istniejącymi komponentami Blazor, które chcą ponownego użycia kodu. HybridWebView pasuje do scenariuszy, w których istniejąca zawartość webowa wymaga natywnej integracji bez pełnego frameworka.

Zacznij ćwiczyć!

Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Podsumowanie

  • .NET MAUI 10 to wydanie LTS (wsparcie do listopada 2028) skoncentrowane na stabilności i wydajności — niezawodny wybór do produkcyjnych aplikacji cross-platform
  • Architektura handlerów zastępuje renderery Xamarin bezstanowymi mapperami, poprawiając testowalność i dostosowywanie poprzez PropertyMapper i CommandMapper
  • Generatory kodu źródłowego CommunityToolkit.Mvvm usuwają większość kodu boilerplate MVVM — atrybuty [ObservableProperty] i [RelayCommand] zastępują ręczne implementacje
  • HybridWebView w .NET 10 dodaje wywołania JavaScript fire-and-forget, zdarzenia inicjalizacji i przechwytywanie żądań dla integracji natywno-webowej
  • SafeAreaEdges zapewnia granularną, cross-platformową kontrolę nad wycięciami urządzeń, klawiaturami i paskami systemowymi
  • Migracja z Xamarin.Forms wymaga przepisania handlerów i refaktoryzacji inicjalizacji
  • Przygotowanie do rozmów kwalifikacyjnych powinno koncentrować się na architekturze handler vs. renderer, pułapkach DI, kompilowanych bindowaniach oraz kompromisach HybridWebView vs. BlazorWebView

Zacznij ćwiczyć!

Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Tagi

#dotnet
#maui
#cross-platform
#xamarin
#mobile

Udostępnij

Powiązane artykuły