Desktop & Mobile: WPF, WinUI & .NET MAUI
C# is not only for web APIs and background services. Billing software in shops, hospital front-desk systems, school ERPs and many internal tools in Indian companies are Windows desktop apps written in C#. With .NET MAUI the same language also builds Android and iOS apps.
There are several UI frameworks, and job adverts mention them by name, so this lesson gives you a map: what each one is for, the MVVM pattern they share, and a first .NET MAUI app built step by step. It is an overview; each framework deserves its own course.
The UI frameworks at a glance
| Framework | Runs on | UI written in | Typical use today |
|---|---|---|---|
| Windows Forms | Windows | C# with a visual designer | Quick internal tools, maintaining older business apps |
| WPF | Windows | XAML + C# | Rich line-of-business desktop apps |
| WinUI 3 | Windows 10 and 11 | XAML + C# | New Windows apps with the modern Windows look |
| .NET MAUI | Android, iOS, macOS, Windows | XAML or C# | One code base for mobile and desktop |
| Blazor Hybrid | Inside MAUI, WPF or Windows Forms | Razor components (HTML + C#) | Reusing web UI skills and components in a native app |
Some facts to remember:
- Windows Forms and WPF run on modern .NET 10, not only on .NET Framework. They stay Windows-only; their projects target
net10.0-windows. Create them withdotnet new winformsordotnet new wpf. - WinUI 3 is part of the Windows App SDK, Microsoft's current platform for native Windows apps.
- .NET MAUI (Multi-platform App UI) is the successor of Xamarin.Forms. Microsoft ended support for Xamarin in May 2024, so Xamarin apps are being moved to MAUI.
- XAML (eXtensible Application Markup Language) is an XML language that describes the screen: buttons, text boxes, layouts. C# code supplies the behaviour.
- Community frameworks such as Avalonia and Uno Platform also run C# XAML apps on Linux and the web. They are not made by Microsoft but are widely used.
MVVM: the pattern behind XAML apps
WPF, WinUI and MAUI all encourage MVVM (Model, View, ViewModel):
- The Model is your data and business rules (an
Invoice, a GST calculator). - The View is the XAML screen. It contains almost no code.
- The ViewModel is a C# class that exposes properties for the View to show and commands for buttons to run.
The View connects to the ViewModel with data binding: Text="{Binding Amount}" keeps a text box and a property in sync. For that to work, the ViewModel must announce changes by implementing INotifyPropertyChanged. The field keyword from C# 14 keeps this short, and because a ViewModel is plain C#, you can run and test it in a console app with no UI at all:
using System.ComponentModel;
var vm = new FeeViewModel();
vm.PropertyChanged += (_, e) => Console.WriteLine($"{e.PropertyName} changed");
vm.Amount = 1000m;
Console.WriteLine($"GST: {vm.Gst}");
vm.Amount = 1000m; // same value: no notification
public class FeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public decimal Amount
{
get;
set
{
if (field == value) return;
field = value;
OnChanged(nameof(Amount));
OnChanged(nameof(Gst)); // Gst depends on Amount
}
}
public decimal Gst => Math.Round(Amount * 0.18m, 2); // 18% is an example rate
private void OnChanged(string name) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}Amount changed Gst changed GST: 180.00
When a bound control hears "Gst changed", it reads Gst again and redraws itself. Setting the same value twice raises nothing, which avoids needless redraws. In real projects many teams use the CommunityToolkit.Mvvm package, whose source generators write this notification code for you.
Walkthrough: your first .NET MAUI app
You can build MAUI apps on Windows (for Windows and Android), on a Mac (for Android, iOS and macOS) and, for Android only, on Linux. Building for iOS always needs a Mac with Xcode.
Step 1: install the MAUI workload
dotnet workload install maui
dotnet workload listA workload is an optional part of the SDK. On Linux the command is dotnet workload install maui-android. In Visual Studio, tick the ".NET Multi-platform App UI development" workload in the installer instead. In VS Code, install the .NET MAUI extension, which also brings C# Dev Kit. For Android you also need the Java JDK and the Android SDK; the MAUI extension and the Visual Studio installer can set them up for you.
Step 2: create the project
dotnet new maui -n FeeCalc
cd FeeCalcMAUI uses a single project: one .csproj that targets several platforms at once (its TargetFrameworks lists entries such as net10.0-android and net10.0-ios), with a Platforms folder for the rare platform-specific code and a Resources folder for shared images, fonts and the app icon.
Step 3: add the ViewModel
Copy the FeeViewModel class from the previous section into a new file FeeViewModel.cs, inside namespace FeeCalc;.
Step 4: describe the screen in XAML
Replace the contents of MainPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FeeCalc"
x:Class="FeeCalc.MainPage"
x:DataType="local:FeeViewModel">
<VerticalStackLayout Padding="20" Spacing="12">
<Label Text="Course fee (Rs)" FontSize="18" />
<Entry Text="{Binding Amount}" Keyboard="Numeric" />
<Label Text="{Binding Gst, StringFormat='GST: Rs {0:F2}'}" FontSize="18" />
</VerticalStackLayout>
</ContentPage>x:DataType tells the XAML compiler which type the bindings use, so it can check property names at build time and generate faster compiled bindings. In MainPage.xaml.cs, keep the generated InitializeComponent() call and set the binding source after it, then delete the template's counter button handler, which no longer has a button:
namespace FeeCalc;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new FeeViewModel();
}
}Step 5: run it
dotnet build -t:Run -f net10.0-androidThis builds the Android version and starts it on a running emulator or connected phone. On Windows you can instead pick the Windows target in Visual Studio or VS Code and press F5. Type 2500 in the box and the label shows GST: Rs 450.00 immediately, with no button and no event handler: binding did the work.
Choosing a framework
- An internal Windows tool that must be ready this week: Windows Forms or WPF.
- A new Windows-only product with a modern look: WinUI 3 (or WPF if your team already knows it).
- One app for Android and iOS, perhaps also desktop: .NET MAUI.
- A team that already has Blazor web components: Blazor Hybrid inside MAUI or WPF.
- Desktop apps that must also run on Linux: consider Avalonia or Uno Platform.
Whatever you choose, keep business rules in a separate class library (see Solutions, Projects & NuGet Packages) so the same code can serve a desktop app, a mobile app and a web API.
Common mistakes
- Expecting WPF or Windows Forms to run on Linux or macOS. They are Windows-only, even on .NET 10.
- Putting business logic in click handlers. Move it into ViewModels and services you can test.
- Forgetting
INotifyPropertyChanged. The screen shows the first value and never updates. - Blocking the UI thread. A slow
.ResultorThread.Sleepin a handler freezes the window; useasync/await. - Starting a new mobile app on Xamarin. It is out of support; use .NET MAUI.
Key points
- Windows Forms and WPF run on modern .NET but only on Windows; WinUI 3 is the newest Windows UI platform.
- .NET MAUI builds Android, iOS, macOS and Windows apps from a single project and replaces Xamarin.Forms.
- XAML describes the screen; data binding connects it to C# properties.
- MVVM separates Model, View and ViewModel; ViewModels implement
INotifyPropertyChangedand can be tested without UI. - Install MAUI with
dotnet workload install maui, create withdotnet new maui, and run withdotnet build -t:Run -f <target>.
Exercise
Extend FeeViewModel with a DiscountPercent property (default 0). Gst should now be calculated on the discounted amount, and a new read-only Total property should return the discounted amount plus GST. Raise change notifications correctly for every property that depends on the one that changed. Test it in a console app: set Amount to 2000 and DiscountPercent to 10, and print the names of changed properties and the final total.
Show solution
using System.ComponentModel;
var vm = new FeeViewModel();
vm.PropertyChanged += (_, e) => Console.WriteLine($"{e.PropertyName} changed");
vm.Amount = 2000m;
vm.DiscountPercent = 10m;
Console.WriteLine($"Total: {vm.Total}");
public class FeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
public decimal Amount
{
get;
set { if (field != value) { field = value; RaiseAll(nameof(Amount)); } }
}
public decimal DiscountPercent
{
get;
set { if (field != value) { field = value; RaiseAll(nameof(DiscountPercent)); } }
}
private decimal Discounted => Amount - Amount * DiscountPercent / 100;
public decimal Gst => Math.Round(Discounted * 0.18m, 2);
public decimal Total => Discounted + Gst;
private void RaiseAll(string changed)
{
foreach (string name in new[] { changed, nameof(Gst), nameof(Total) })
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}Amount changed Gst changed Total changed DiscountPercent changed Gst changed Total changed Total: 2124.00
The discounted fee is 2000 - 200 = 1800, GST on it is 1800 x 0.18 = 324.00, so the total is 2124.00 (a decimal keeps the two decimal places that came from multiplying by 0.18m). Changing either input property raises notifications for itself and for both properties that depend on it, so every bound label on the screen stays correct.
Quick Quiz
1. Which UI framework builds Android and iOS apps from one C# project?
.NET MAUI targets Android, iOS, macOS and Windows from a single project.
2. What must a ViewModel implement so that bound controls update when a property changes?
Bindings listen for the PropertyChanged event to know when to refresh.
3. Which statement about WPF on .NET 10 is true?
WPF was ported to modern .NET but still depends on Windows.
4. What is the role of the View in MVVM?
The View is the XAML UI; logic lives in the ViewModel and Model.
Learn C# with a mentor
Free lessons get you started. Our Programming & Software Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
