.NET Multi‑platform App UI (.NET MAUI) is Microsoft’s cross‑platform
framework for building native mobile and desktop apps with a single C# codebase.
It succeeds Xamarin.Forms and targets Android
, iOS/iPadOS
,
macOS
, and Windows
. .NET 8 (LTS) is the current stable
version, while .NET 9 Preview focuses on quality and new controls such as
HybridWebView
and an improved
TitleBar
API.
.csproj
, single XAML
layer → less duplication.dotnet build
, Hot‑Reload, C# 12).Note: .NET 8 is an LTS release (free patches for 3 years); .NET 9 will be an STS release (18 months).
MyMauiApp/
├─ Platforms/
│ ├─ Android/ // MainActivity, Resources, AndroidManifest.xml
│ ├─ iOS/ // AppDelegate, Info.plist, Assets.xcassets
│ ├─ MacCatalyst/ // Entitlements.plist
│ └─ Windows/ // Package.appxmanifest, *.cs
├─ Resources/ // appicon.svg, splash, fonts, raw assets
├─ App.xaml // global styles, resources
├─ MainPage.xaml // first UI page
├─ ViewModels/ // MVVM logic
├─ Services/ // DI‑registered back‑end helpers
└─ MyMauiApp.csproj // single project configuration (TargetFrameworks=net8.0‑android;…)
A single .csproj
lists several <TargetFrameworks>
.
The build system produces one bundle per platform, wiring native Gradle,
Xcode, or MSIX packaging behind the scenes.
// Create and run your first app
dotnet new maui -n HelloWorld
cd HelloWorld
dotnet run ‑‑framework net8.0‑android
ContentPage
– basic single‑view container.NavigationPage
– push/pop stack navigation.TabBar
& Shell
– high‑level app chrome.<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
x:Class="HelloWorld.MainPage">
<VerticalStackLayout Spacing="24" Padding="30">
<Label Text="Welcome to 🦀 .NET MAUI!" FontSize="32" HorizontalOptions="Center" />
<Button x:Name="CounterBtn"
Clicked="OnCounterClicked"
Text="Clicked 0 times" />
</VerticalStackLayout>
</ContentPage>
private int _count;
private void OnCounterClicked(object sender, EventArgs e)
{
_count++;
CounterBtn.Text = $"Clicked {_count} times";
}
Use Grid
, FlexLayout
,
and VerticalStackLayout
for responsive
design. Combine with the built‑in DeviceDisplay.MainDisplayInfo
API
to tweak UI for tablets vs phones.
<Grid RowDefinitions="Auto,*" ColumnDefinitions="* Auto">
<Label Grid.Row="0" Grid.Column="0" Text="Title"/>
<Button Grid.Row="0" Grid.Column="1" Text="ℹ︎" />
<CollectionView Grid.Row="1" Grid.ColumnSpan="2" />
</Grid>
public class CounterViewModel : ObservableObject
{
[ObservableProperty] private int count;
[RelayCommand]
private void Increment() => Count++;
}
The CommunityToolkit.Mvvm
package supplies
[ObservableProperty]
and
[RelayCommand]
source generators to reduce boilerplate.
<ContentPage
x:DataType="vm:CounterViewModel"
xmlns:vm="clr-namespace:HelloWorld">
<VerticalStackLayout Spacing="20">
<Label Text="{Binding Count}" FontSize="32"/>
<Button Text="Increment"
Command="{Binding IncrementCommand}" />
</VerticalStackLayout>
</ContentPage>
Microsoft.Maui.Essentials
Geolocation.GetLastKnownLocationAsync()
MediaPicker.PickPhotoAsync()
Accelerometer.ReadingChanged
Preferences.Set/Get
for secure key‑value storagevar photo = await MediaPicker.CapturePhotoAsync();
if (photo != null)
{
var stream = await photo.OpenReadAsync();
ImageView.Source = ImageSource.FromStream(() => stream);
}
MauiProgram.cs
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts => fonts.AddFont("Inter.ttf", "Inter"));
// Register interfaces
builder.Services.AddSingleton<IDataService, SqliteDataService>();
builder.Services.AddTransient<MainPage>();
return builder.Build();
}
Use dotnet maui hotreload in CLI or enable Hot Reload in Visual Studio to update UI and code‑behind on‑device instantly—no redeploy required.
The Live Visual Tree lets you drill into your running XAML hierarchy to tweak properties in real‑time, accelerating UI iteration.
#if ANDROID
Toast.MakeText(Android.App.Application.Context,
"Hi from Android", ToastLength.Short).Show();
#elif WINDOWS
await new MessageDialog("Hi from Windows").ShowAsync();
#endif
public class BorderlessEntry : Entry { }
#if ANDROID
[assembly: ExportHandler(typeof(BorderlessEntry), typeof(BorderlessEntryHandler))]
public class BorderlessEntryHandler : EntryHandler
{
protected override void ConnectHandler(global::Android.Widget.EditText platformView)
{
platformView.Background = null; // remove underline
}
}
#endif
// Android (AAB for Play Store)
dotnet publish -c Release -f net8.0-android -p:AndroidPackageFormat=aab
// iOS (IPA via Xcode)
dotnet publish -c Release -f net8.0-ios -p:BuildIpa=true
// Windows (MSIX)
dotnet publish -c Release -f net8.0-windows10.0.19041
ApplicationDisplayVersion
user‑friendly (semver).ApplicationVersion
(integer) every build for
Android & iOS store submissions.HybridWebView
(Blazor ↔ native integration).TitleBar
customization on Windows.CollectionView
& CarouselView
handlers on iOS/macOS.ProcessTerminated
event for WebView.These arrive in Preview 7 and later. Consider testing them early to prepare for GA in November 2025.