.NET MAUI — Cross-Platform UI Development Explained
.NET MAUI (Multi-platform App UI) is Microsoft’s framework for building native mobile and desktop apps from a single C# codebase. It targets Android, iOS, macOS, Windows, and Tizen — all from one project with shared UI and logic.
What You’ll Learn
You’ll master MAUI’s page and layout system, MVVM architecture with CommunityToolkit, data binding, and native API access. You’ll build a MAUI app with real data binding.
Why .NET MAUI Matters
MAUI replaces Xamarin.Forms with a modern, performance-optimized framework. It lets .NET developers target every major platform without learning platform-specific UI frameworks. At DodaTech, we use MAUI for mobile companion apps that integrate with Durga Antivirus Pro.
.NET MAUI Learning Path
flowchart LR
A[Blazor] --> B[.NET MAUI]
B --> C{You Are Here}
C --> D[Entity Framework]
C --> E[WPF & WinForms]
style C fill:#f90,color:#fff
Pages and Layouts
MAUI apps are built from pages (screens) that contain layouts (containers) with views (controls):
| Element | Examples | Purpose |
|---|---|---|
| Page | ContentPage, Shell, TabbedPage | A full screen |
| Layout | StackLayout, Grid, FlexLayout | Arranges children |
| View | Label, Button, Entry, CollectionView | UI controls |
<?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="Contacts">
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*" Padding="20">
<!-- Search Bar -->
<SearchBar Placeholder="Search contacts..."
Grid.Row="0"
Text="{Binding SearchText}" />
<!-- Contact List -->
<CollectionView Grid.Row="1"
ItemsSource="{Binding FilteredContacts}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" Orientation="Horizontal">
<Label Text="{Binding Name}" FontSize="18" />
<Label Text="{Binding Phone}" FontSize="14" TextColor="Gray" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>MVVM with CommunityToolkit
MVVM (Model-View-ViewModel) separates UI from logic. CommunityToolkit.Mvvm provides source generators for clean code:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class ContactViewModel : ObservableObject
{
[ObservableProperty]
private string name;
[ObservableProperty]
private string phone;
[ObservableProperty]
private string searchText;
public ObservableCollection<Contact> Contacts { get; } = new();
public List<Contact> FilteredContacts => Contacts
.Where(c => c.Name.Contains(SearchText ?? "", StringComparison.OrdinalIgnoreCase))
.ToList();
[RelayCommand]
async Task AddContact()
{
var contact = new Contact { Name = Name, Phone = Phone };
Contacts.Add(contact);
Name = string.Empty;
Phone = string.Empty;
OnPropertyChanged(nameof(FilteredContacts));
}
partial void OnSearchTextChanged(string value)
{
OnPropertyChanged(nameof(FilteredContacts));
}
}Data binding connects the View (XAML) to the ViewModel (C#):
// In code-behind or DI registration
public MainPage()
{
InitializeComponent();
BindingContext = new ContactViewModel();
}Native API Access
MAUI provides a cross-platform API layer for native features:
// Geolocation
var location = await Geolocation.Default.GetLastKnownLocationAsync();
if (location == null)
{
location = await Geolocation.Default.GetLocationAsync();
}
Console.WriteLine($"Lat: {location.Latitude}, Lon: {location.Longitude}");
// Device info
var deviceInfo = DeviceInfo.Current;
Console.WriteLine($"Model: {deviceInfo.Model}, Platform: {deviceInfo.Platform}");
// File system access
string appData = FileSystem.AppDataDirectory;
string cacheDir = FileSystem.CacheDirectory;For platform-specific code, use conditional compilation or partial classes:
#if ANDROID
// Android-specific code
#elif IOS
// iOS-specific code
#elif WINDOWS
// Windows-specific code
#endifCommon Mistakes Beginners Make
1. Blocking the UI Thread with Network Calls
Never make HTTP calls or database queries synchronously. Always use async/await or the UI thread freezes and the OS shows “App Not Responding.”
2. Not Implementing INotifyPropertyChanged
Without property change notification, the UI never updates when data changes. CommunityToolkit’s [ObservableProperty] handles this automatically.
3. Ignoring Hot Reload
MAUI’s Hot Reload applies XAML and C# changes without rebuilding. Use it. It saves hours of rebuild time during UI iteration.
4. Forgetting to Register Services in DI
builder.Services.AddSingleton<IContactService, ContactService>();
builder.Services.AddTransient<MainPage>();Register pages and ViewModels in MauiProgram.cs or DI fails with “Unable to resolve service.”
5. Using Absolute Layout Paths
MAUI’s AbsoluteLayout is position-dependent and breaks on different screen sizes. Use Grid and StackLayout with HorizontalOptions / VerticalOptions instead.
6. Not Testing on Physical Devices
The emulator is faster, but real devices reveal touch response, performance, and camera issues. Always deploy to a physical device before release.
7. Overlooking Platform-Specific Styling
What looks great on Android may need different margins on iOS. Use OnPlatform and OnIdiom in XAML for platform-specific adjustments.
Practice Questions
1. What is the MVVM pattern?
MVVM separates View (XAML UI), ViewModel (logic/state), and Model (data). ViewModel exposes properties and commands that the View binds to.
2. What does [ObservableProperty] do?
It generates a property with INotifyPropertyChanged support, eliminating boilerplate code.
3. How does MAUI provide native API access?
Through cross-platform APIs (Geolocation, DeviceInfo, FileSystem) and conditional compilation for platform-specific code.
4. What’s the difference between ContentPage and Shell?
ContentPage is a single screen. Shell provides navigation chrome (flyout menu, tabs) and URI-based navigation.
5. Challenge: Add photo capture.
Add a button that opens the camera, captures a photo, and displays it. Use MediaPicker.Default.CapturePhotoAsync().
Mini Project: Note-Taking App
Build a MAUI note app:
MainPagewithCollectionViewlisting notesAddNotePagewithEntryfor title andEditorfor content- ViewModel with
[ObservableProperty]and[RelayCommand] - Save notes to a JSON file in
FileSystem.AppDataDirectory - Add swipe-to-delete on note items
FAQ
What’s Next
Congratulations on completing this .NET MAUI tutorial! Here’s where to go from here:
- Practice daily — Build one small screen per day
- Build a project — Create a cross-platform CRUD app
- Explore related topics — MAUI Shell navigation, custom handlers
- Join the community — Share your MAUI apps and get feedback
Remember: every expert was once a beginner. Keep building!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro