L13 — .NET MAUI pt.1: Introduction & Setup
We leave the console behind. Meet .NET MAUI — Microsoft's cross-platform UI framework. We install the workload, create our first project, tour the files, and run a real app on Windows and Android.
🎯Learning Objectives
- Explain what .NET MAUI is and what "cross-platform" means in practice
- Install the .NET MAUI workload via Visual Studio Installer
- Create a new MAUI project and identify its key files and folders
- Run the app on Windows and on an Android emulator
- Make a first tiny change to the UI and see it reflected when you re-run
📖Theory
1. From Console to Real Apps
For the last 12 lessons everything happened inside a black terminal window. That's fine for learning logic, but no real user will ever see a Console.WriteLine. Real software has buttons, lists, screens — a UI.
Writing a UI used to mean picking a framework per platform: one codebase for Windows, another for Android, another for iOS. Three teams, three bugs for every feature.
.NET MAUI (Multi-platform App UI) is Microsoft's answer: one C# + XAML codebase that compiles to Windows, Android, iOS, and macOS. You write the screen once; MAUI produces a native app on each platform.
One-sentence summary: MAUI lets you use the C# and OOP skills you've already learned to build apps that run on a phone, a desktop, and a tablet from a single project.
2. What "Cross-Platform" Actually Means
MAUI does not secretly ship a web view or a fake widget layer. Your Button becomes a real Android Button on Android, a UIButton on iOS, a WinUI button on Windows. MAUI maps one abstract control to the native control on each OS.
Code
Your code: <Button Text="Save" />
On Android: android.widget.Button
On iOS: UIKit.UIButton
On Windows: Microsoft.UI.Xaml.Controls.ButtonConsequences:
- Your app looks native on each platform — a button feels like a native button.
- The build output per platform is big — MAUI bundles the right native runtime for each target.
- You still sometimes need platform-specific code (e.g. reading a photo library). MAUI provides hooks for that.
3. What You Need to Install
To build MAUI apps on Windows, you need:
- Visual Studio 2022 (17.8 or later) — the Community edition is free.
- .NET MAUI workload — installable via the Visual Studio Installer. It pulls in:
- .NET 8 (or 9) SDK
- Android SDK + emulator images
- Windows App SDK (for Windows targets)
- For iOS targets: a Mac on the same network (not required in our course — we target Windows + Android only).
Warning: the MAUI workload is large (~10 GB) and the first install can take 30+ minutes. Do this at home before class, not during.
4. Creating Your First MAUI Project
In Visual Studio:
- File → New → Project
- Search for ".NET MAUI App" (not "MAUI Blazor Hybrid" — that's a different thing)
- Name it
HelloMaui, choose a folder, click Next - Pick .NET 8.0 as the framework, click Create
Visual Studio generates a working project with a sample counter page. Don't modify anything yet — just try to run it first.
5. Tour of the Project Structure
Code
HelloMaui/
├── Platforms/ ← platform-specific startup code
│ ├── Android/
│ ├── iOS/
│ ├── MacCatalyst/
│ └── Windows/
├── Resources/ ← images, fonts, styles, app icon
│ ├── AppIcon/
│ ├── Fonts/
│ ├── Images/
│ └── Styles/
├── App.xaml ← application-level resources (colors, global styles)
├── App.xaml.cs ← app entry logic
├── AppShell.xaml ← the navigation shell (tabs, flyout, routes)
├── AppShell.xaml.cs
├── MainPage.xaml ← the UI of the first page — XAML markup
├── MainPage.xaml.cs ← the code behind that page — C# class
├── MauiProgram.cs ← the startup: registers services, fonts, etc.
└── HelloMaui.csproj ← project file — target frameworks and dependenciesThe pair you'll edit most is MainPage.xaml (the look) and MainPage.xaml.cs (the logic). Together they are a partial class — two files making one C# class.
6. XAML in 60 Seconds
XAML is an XML dialect for describing UI. Instead of building controls with new Button(...) calls in C#, you declare them as tags:
XML
<VerticalStackLayout Padding="20" Spacing="10">
<Label Text="Hello, MAUI!" FontSize="24" />
<Button Text="Click me" Clicked="OnClicked" />
</VerticalStackLayout>The Clicked="OnClicked" part wires a button tap to a C# method called OnClicked in the code-behind file:
C#
// MainPage.xaml.cs
private void OnClicked(object sender, EventArgs e)
{
Console.WriteLine("Button was tapped!");
}We'll go deep on XAML in L14. For now just know: tags describe widgets, attributes set their properties, events hook into C# methods.
7. Running the App
Look at the green ▶ Run button in Visual Studio's toolbar. Next to it is a dropdown that lets you pick a target:
- Windows Machine — fastest to iterate. Runs the app as a native Windows window.
- Android Emulators → Pixel 5 (or similar) — runs on a virtual Android phone. Slower to start, but more realistic for mobile.
- Android Local Devices — if you plug in a real phone with USB debugging on, it appears here.
Click ▶. First run compiles a lot; expect 1–3 minutes. After that, changes are fast.
Tip: always start on Windows first. If your code is broken, you'll find out in seconds instead of waiting for the Android emulator to boot.
8. The Edit–Run Loop
A healthy MAUI workflow:
- Edit XAML or C#.
- Press ▶ (or Ctrl+F5 for run without debugging — faster).
- Observe the app.
- Close the app window, repeat.
MAUI has a feature called XAML Hot Reload: while the app is running under the debugger, changes you make to XAML files are applied live without restarting. Hot Reload doesn't cover everything (some C# changes still need a restart), but it speeds up UI work enormously.
💻Code Examples
Example A — The default MainPage.xaml, simplified
Open MainPage.xaml in a fresh project. Strip the sample down to this:
XML
<?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="HelloMaui.MainPage"
Title="Home">
<VerticalStackLayout Padding="20" Spacing="15" VerticalOptions="Center">
<Label Text="Hello, MAUI!"
FontSize="32"
HorizontalOptions="Center" />
<Label x:Name="StatusLabel"
Text="Tap the button below."
FontSize="16"
HorizontalOptions="Center" />
<Button Text="Tap me"
Clicked="OnTapClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ContentPage>And in MainPage.xaml.cs:
C#
namespace HelloMaui;
public partial class MainPage : ContentPage
{
private int _count = 0;
public MainPage()
{
InitializeComponent();
}
private void OnTapClicked(object sender, EventArgs e)
{
_count++;
StatusLabel.Text = $"You tapped {_count} time(s).";
}
}Notice:
InitializeComponent()is what reads the XAML and builds the UI tree.StatusLabelis reachable from C# because we gave itx:Name="StatusLabel"in XAML.- The
OnTapClickedmethod was referenced in the XAML as theClickedhandler.
Example B — MauiProgram.cs (the startup)
Every MAUI app has MauiProgram.cs at the root. This is the MAUI equivalent of Main — it configures the app before the first page shows.
C#
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
return builder.Build();
}
}You'll edit this file in L16 to register database services. For now, just know it exists.
✏️Practice Tasks
- Create a new .NET MAUI App called
HelloMaui - Without changing anything, run it on Windows Machine
- Click the "Click me" button a few times and confirm the counter goes up
- Now run it on an Android Emulator
- Take a screenshot of the app running on each target and paste both into a short document
💡 Hint
Starting from the project in Task 1:
- Open
MainPage.xaml - Replace the sample content with the simplified version from Example A
- Change the first
Labeltext from"Hello, MAUI!"to"Hello, {your name}!" - Change the
FontSizeof that Label to 40 - Add a second
Buttonlabeled"Reset"that resets the counter back to 0 and updates the status label
Run the app. Verify:
- Your name is on the screen
- "Tap me" increments the counter
- "Reset" puts it back to 0
💡 Hint
private void OnResetClicked(object sender, EventArgs e) { _count = 0; StatusLabel.Text = "Reset!"; }. Don't forget Clicked="OnResetClicked" in the XAML.Answer these questions in a short document (3–4 sentences each, in your own words):
- What does
InitializeComponent()actually do when the page is constructed? - Why does
MainPagehave two files (.xamland.xaml.cs) instead of one? - What's inside the
Platforms/folder and why is it organised that way? - What would break if you removed
x:Name="StatusLabel"from the XAML? - Describe, in your own words, the difference between XAML and C# in a MAUI project.
💡 Hint
InitializeComponent() — you'll see auto-generated code that the MAUI toolchain created from your XAML. That answers question 1 and hints at question 2.⚠️Common Mistakes
Picking the wrong project template
The New Project dialog has several MAUI-related entries: ".NET MAUI App", ".NET MAUI Blazor Hybrid App", ".NET MAUI Class Library", etc. We want .NET MAUI App (the first one). Blazor Hybrid is a different architecture.
Forgetting to install the MAUI workload
If "MAUI" doesn't appear in the project template search, the workload isn't installed. Open Visual Studio Installer → Modify → Workloads and check ".NET Multi-platform App UI development".
Running on Android before it works on Windows
If your code has a typo, Android will spend two minutes booting the emulator before showing you the error. Windows takes 5 seconds. Always debug on Windows first.
Expecting Hot Reload to cover everything
XAML Hot Reload updates layout changes live. But changes to the constructor, adding a new field, or editing certain event signatures still require a restart. If something looks wrong after a change, try stopping and re-running.
Editing the auto-generated .xaml.g.cs files
In the obj/ folder MAUI generates .xaml.g.cs files from your XAML. Never edit those — they're recreated on every build. Edit only .xaml and .xaml.cs.
🎓Instructor Notes
⚡ How to run this lesson (~80 min)
- [5 min] Context. Project a photo of a console app next to a phone app. Ask: "Which one would you actually ship?" Segue into cross-platform UI frameworks.
- [10 min] What MAUI is and isn't. Cover native vs web view distinction. Diagram on the board: one codebase → three native outputs.
- [10 min] Live: New Project. On the projector, create a fresh MAUI project and run it on Windows. Don't explain everything yet — just let them see "this works out of the box".
- [15 min] Project tour. Walk through the file tree. Open
MainPage.xamlandMainPage.xaml.csside by side. Show the partial class relationship. Make the "x:Name = variable name in C#" connection explicit. - [5 min] Android target. Switch the run target dropdown, boot the emulator (have it pre-booted!). Show the same app on both platforms.
- [30 min] Task 1 in class. Most issues are environmental: emulator missing, workload missing. Have a checklist ready: workload ✓, HAXM / WHPX ✓, at least one Android image downloaded ✓.
- [5 min] Wrap up + assign homework. Preview L14: XAML layout and navigation. Assign Tasks 2 and 3.
💬 Discussion questions
- "If MAUI compiles to native controls on each platform, why might an app still feel slightly different on Android vs Windows?"
- "What's the relationship between
.xamland.xaml.cs? Could you put everything in C# and skip XAML?" - "Why does Microsoft call it 'Multi-platform' and not 'cross-platform'?"