MAUI Cross-Platform Apps
Build cross-platform applications for Android, iOS, Windows, and macOS.
A Simple Analogy
MAUI is like building one house that works in different countries. One codebase adjusts to platform requirements automatically (iOS layout vs Android, etc.).
Why MAUI?
- One codebase: Build for iOS, Android, Windows, macOS
- C# everywhere: Use same language across platforms
- Xaml: Declarative UI like WPF
- Native performance: Direct API access per platform
- Hot reload: Instant feedback during development
Project Setup
# Create MAUI app
dotnet new maui -n MyApp
cd MyApp
# Run on platform
dotnet build -t run -f net8.0-android
dotnet build -t run -f net8.0-ios
dotnet build -t run -f net8.0-windows
XAML UI Definition
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage"
Title="Order List">
<VerticalStackLayout Padding="20" Spacing="10">
<Label Text="My Orders" FontSize="24" FontAttributes="Bold" />
<SearchBar x:Name="SearchBar" Placeholder="Search orders..." />
<CollectionView ItemsSource="{Binding Orders}" SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" Spacing="5">
<Label Text="{Binding Id, StringFormat='Order {0}'}" FontAttributes="Bold" />
<Label Text="{Binding Total, StringFormat='${0:F2}'}" FontSize="14" />
<Label Text="{Binding CreatedAt, StringFormat='{0:MMM d, yyyy}'}"
FontSize="12" TextColor="Gray" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="Create Order" Command="{Binding CreateOrderCommand}" />
</VerticalStackLayout>
</ContentPage>
ViewModel and Binding
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new OrderViewModel();
}
}
public partial class OrderViewModel : BaseViewModel
{
private readonly IOrderService _orderService;
[ObservableProperty]
ObservableCollection<OrderDto> orders;
public OrderViewModel()
{
_orderService = ServiceHelper.GetService<IOrderService>();
}
[RelayCommand]
public async Task LoadOrders()
{
if (IsBusy) return;
try
{
IsBusy = true;
var orders = await _orderService.GetAllAsync();
Orders = new ObservableCollection<OrderDto>(orders);
}
catch (Exception ex)
{
await Shell.Current.DisplayAlert("Error", ex.Message, "OK");
}
finally
{
IsBusy = false;
}
}
[RelayCommand]
public async Task CreateOrder()
{
await Shell.Current.GoToAsync("create-order");
}
}
Platform-Specific Code
// Conditional compilation
#if ANDROID
var platformSpecific = new Android.SpecificFeature();
#elif IOS
var platformSpecific = new iOS.SpecificFeature();
#elif WINDOWS
var platformSpecific = new Windows.SpecificFeature();
#endif
// Or using if statements with IsAndroid, IsIOS, etc.
if (DeviceInfo.Platform == DevicePlatform.Android)
{
// Android-specific code
}
else if (DeviceInfo.Platform == DevicePlatform.iOS)
{
// iOS-specific code
}
Navigation
// AppShell.xaml
<Shell FlyoutBehavior="Flyout">
<TabBar>
<Tab Title="Orders" Icon="list_icon">
<ShellContent Title="All Orders" ContentTemplate="{DataTemplate local:OrdersPage}" Route="orders" />
</Tab>
<Tab Title="Create" Icon="plus_icon">
<ShellContent ContentTemplate="{DataTemplate local:CreateOrderPage}" Route="create-order" />
</Tab>
<Tab Title="Settings" Icon="settings_icon">
<ShellContent ContentTemplate="{DataTemplate local:SettingsPage}" Route="settings" />
</Tab>
</TabBar>
</Shell>
// Navigate programmatically
await Shell.Current.GoToAsync($"order-detail/{orderId}");
Dependency Injection
// MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
return builder
.UseMauiApp<App>()
.ConfigureServices(services =>
{
services.AddSingleton<IOrderService, OrderService>();
services.AddSingleton<OrderViewModel>();
services.AddSingleton<MainPage>();
})
.Build();
}
}
Best Practices
- Use MVVM: Separate logic from UI
- Responsive layouts: Handle different screen sizes
- Async/await: Keep UI responsive
- Platform abstractions: Hide platform differences
- Test on devices: Emulator ≠ real device
Related Concepts
- Xamarin.Forms (predecessor)
- React Native
- Flutter
- Blazor for web
Summary
MAUI enables building native cross-platform applications with C# and XAML. Share business logic across platforms while maintaining native look and feel.
Related Articles
AWS Lambda with .NET Functions
Learn how to build and deploy serverless .NET functions using AWS Lambda.
Read More serverlessAzure Functions with .NET
Build serverless applications with Azure Functions.
Read More webBlazor Server Applications
Build interactive web apps with C# using Blazor Server.
Read More