.NET MAUI in 2026: Cross-Platform Development Tutorial and Interview Questions
.NET MAUI tutorial covering cross-platform development with .NET 10, handlers, MVVM, HybridWebView, and essential interview questions for 2026.

.NET MAUI (Multi-platform App UI) has matured into a production-grade cross-platform framework with .NET 10. Released as a Long-Term Support version supported through November 2028, .NET MAUI 10 ships as a workload plus NuGet packages, delivering improved quality, performance, and new APIs like HybridWebView enhancements and SafeAreaEdges. This tutorial walks through building a cross-platform app, covers the architecture that makes MAUI work, and addresses the interview questions that hiring managers ask in 2026.
.NET 10 is a Long-Term Support release (supported through November 2028). MAUI 10 focuses on quality and performance over new UI controls — making it the most stable MAUI release to date. It now ships as a .NET workload and NuGet packages, enabling version pinning per project.
Setting Up a .NET MAUI 10 Project from Scratch
The fastest path to a running MAUI app starts with the .NET CLI. .NET 10 introduces an updated project template that includes .NET Aspire service defaults, connecting telemetry and 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-androidThe single-project structure consolidates platform-specific code under a Platforms/ folder while sharing the rest. The MauiProgram.cs file serves as the composition root — this is where services, fonts, and handlers are registered.
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();
}
}Dependency injection in MAUI follows the same pattern as ASP.NET Core. Singleton services persist for the app lifetime, Transient services are created per request, and Scoped services — while available — require caution because MAUI has no built-in scope concept like HTTP requests.
Handlers: The Architecture Behind Cross-Platform Rendering
MAUI replaced Xamarin.Forms renderers with a handler architecture. Handlers map each cross-platform control to its native counterpart through a thin abstraction layer. The key difference: handlers are stateless and decoupled from the virtual view, which makes them faster and easier to customize.
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, the Android Entry and Editor controls switched from AppCompatEditText to MauiAppCompatEditText, adding native support for the SelectionChanged event. The improved CollectionView and CarouselView handlers introduced in .NET 9 are now the default on iOS and Mac Catalyst, resolving long-standing stability issues.
MVVM with CommunityToolkit.Mvvm: Eliminating Boilerplate
The CommunityToolkit.Mvvm source generator eliminates roughly 80% of MVVM ceremony. No manual INotifyPropertyChanged implementation, no command wrappers — attributes drive the code generation.
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;
}
}
}The XAML binds directly to the generated properties and commands:
<!-- 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>The x:DataType attribute enables compiled bindings, which are faster than reflection-based bindings and produce compile-time errors when a binding path is wrong.
Ready to ace your .NET interviews?
Practice with our interactive simulators, flashcards, and technical tests.
HybridWebView in .NET 10: Bridging Native and Web
HybridWebView enables embedding web content inside a MAUI app while maintaining bidirectional communication between C# and JavaScript. .NET 10 adds three capabilities: fire-and-forget JavaScript invocation, initialization events for platform-specific configuration, and web request interception.
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");
}
}The corresponding JavaScript receives calls and can send messages back to C#:
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 = '';
}JavaScript exceptions thrown during InvokeJavaScriptAsync are now automatically forwarded to .NET as exceptions, eliminating silent failures.
SafeAreaEdges: Pixel-Perfect Layouts on Every Device
.NET MAUI 10 introduces the SafeAreaEdges property across Layout, ContentView, ContentPage, Border, and ScrollView. The new enum (None, SoftInput, Container, Default, All) replaces the legacy iOS-specific Page.UseSafeArea with a cross-platform approach.
<!-- 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 adjusts content when the on-screen keyboard appears. Container avoids notches, sensor housings, and the home indicator. These can be combined per control, allowing a header to sit under the status bar while the content area stays clear.
Migrating from Xamarin.Forms to .NET MAUI
Xamarin.Forms reached end of support in May 2024. Migrating to MAUI involves structural changes beyond a namespace swap. Here is a migration checklist based on real-world project conversions:
Xamarin.Forms has been unsupported since May 2024. Applications still running on Xamarin carry security and compatibility risks. .NET MAUI 10 (LTS, supported through November 2028) is the designated migration target.
- Project structure — Convert from platform-specific projects to the MAUI single-project model. Move shared code to the root, platform code under
Platforms/. - Namespaces — Replace
Xamarin.FormswithMicrosoft.Maui.ControlsandXamarin.EssentialswithMicrosoft.Maui.Essentials(now built into MAUI). - Renderers to Handlers — Custom renderers must be rewritten as handlers. The handler API is simpler but the mapping logic differs.
- Startup — Replace
App.xaml.csinitialization withMauiProgram.csusing the builder pattern. - NuGet packages — Many Xamarin-era packages have MAUI equivalents. Verify compatibility before upgrading.
- Dependency injection — MAUI uses
Microsoft.Extensions.DependencyInjectionnatively. Replace any third-party DI containers orDependencyServicecalls.
The .NET Upgrade Assistant automates parts of steps 1-2, but handlers (step 3) and business logic adjustments require manual work.
Top .NET MAUI Interview Questions for 2026
These questions reflect what hiring teams ask in 2026, based on the current .NET 10 ecosystem.
How does the MAUI handler architecture differ from Xamarin.Forms renderers?
Renderers in Xamarin.Forms were tightly coupled to both the cross-platform control and the native view, creating a bidirectional dependency. Handlers in MAUI are stateless mappers: they receive property change notifications and apply them to the native view through a mapper dictionary. This decoupling means handlers are easier to test, extend, and reuse. The PropertyMapper and CommandMapper dictionaries replace the OnElementPropertyChanged override pattern, making customization explicit rather than buried in switch statements.
What are the DI lifetime pitfalls specific to MAUI?
MAUI supports Singleton, Transient, and Scoped lifetimes, but Scoped behaves differently than in ASP.NET Core. There is no natural scope boundary (like an HTTP request). A Scoped service registered in MAUI acts like a Singleton unless custom scopes are created manually. Common mistakes: registering a ViewModel as Singleton when it holds page-specific state (stale data across navigation), or registering a database connection as Transient (connection pool exhaustion). The rule of thumb: ViewModels are Transient, services are Singleton, and Scoped is avoided unless the scope lifecycle is managed explicitly.
When answering DI questions, demonstrate understanding of how MAUI's lifecycle differs from ASP.NET Core's request-scoped model. Interviewers look for awareness of memory leaks and stale state issues specific to long-running mobile apps.
How does compiled binding differ from reflection-based binding in MAUI?
Reflection-based bindings resolve property paths at runtime using System.Reflection, which is slow and produces runtime errors for typos. Compiled bindings, enabled with x:DataType, resolve binding paths at compile time. The compiler generates direct property access code, skipping reflection entirely. This improves startup time, reduces memory allocations, and catches binding errors during build. In .NET 10, the new XAML source generator further optimizes this by compiling XAML at build time rather than parsing it at runtime.
What strategies exist for sharing code between a MAUI app and an ASP.NET Core backend?
The recommended approach uses a shared class library containing DTOs, validation logic, and business rules. Both the MAUI app and the ASP.NET Core backend reference this library. .NET 10 reinforces this pattern with the new .NET Aspire integration for MAUI, which provides service discovery and telemetry across mobile and backend projects. Shared contracts using System.Text.Json source generators ensure serialization consistency. The key constraint: the shared library must target net10.0 (not platform-specific TFMs) to remain portable.
How does HybridWebView differ from BlazorWebView in MAUI?
BlazorWebView hosts a full Blazor application inside the MAUI app. Razor components render into an embedded WebView, but the .NET runtime executes natively (not via WebAssembly). HybridWebView is lighter: it loads static HTML/CSS/JS content and provides C#-to-JavaScript interop without the Blazor framework overhead. The choice depends on the use case. BlazorWebView suits teams with existing Blazor components who want code reuse. HybridWebView suits scenarios where existing web content (dashboards, maps, editors) needs native integration without a full framework.
Practice more .NET interview questions on SharpSkill to solidify these concepts with interactive exercises.
Start practicing!
Test your knowledge with our interview simulators and technical tests.
Conclusion
- .NET MAUI 10 is an LTS release (November 2028 support) focused on stability and performance, not feature churn — making it a reliable choice for production cross-platform apps
- The handler architecture replaces Xamarin renderers with stateless mappers, improving testability and customization through
PropertyMapperandCommandMapper - CommunityToolkit.Mvvm source generators remove most MVVM boilerplate —
[ObservableProperty]and[RelayCommand]attributes replace manualINotifyPropertyChangedand command implementations - HybridWebView in .NET 10 adds fire-and-forget JavaScript calls, initialization events, and request interception for native-web integration
- SafeAreaEdges provides granular, cross-platform control over device cutouts, keyboards, and system bars, replacing the legacy iOS-only
UseSafeArea - Xamarin.Forms migration requires handler rewrites and startup refactoring — the .NET Upgrade Assistant handles namespace changes but manual work remains for custom renderers
- Interview preparation should focus on handler vs. renderer architecture, DI lifetime pitfalls in long-running apps, compiled bindings, and HybridWebView vs. BlazorWebView trade-offs
Start practicing!
Test your knowledge with our interview simulators and technical tests.
Tags
Share
Related articles

C# and .NET Interview Questions: Complete Guide 2026
The 25 most common C# and .NET interview questions. LINQ, async/await, dependency injection, Entity Framework and best practices with detailed answers.

Top 25 ASP.NET Core Interview Questions: Middleware, DI and Minimal APIs
Master the most common ASP.NET Core interview questions on middleware pipelines, dependency injection lifetimes, and minimal APIs. Covers .NET 9 and .NET 10 features with code examples.

.NET 9 Blazor: Full-Stack Development with Blazor United in 2026
.NET 9 Blazor United combines static SSR, Server, and WebAssembly render modes into one full-stack framework. A practical tutorial covering render modes, streaming rendering, constructor injection, and production-ready patterns.