The previous four lessons took BiblioTech to the desktop (Windows Forms, WPF) and to the web (ASP.NET Core, Blazor). One platform remains: mobile devices. This last lesson of Module 7 introduces Xamarin.Forms, the framework that for years let you write cross-platform mobile applications in C#, and its official successor, .NET MAUI (Multi-platform App UI), to which Microsoft has migrated the entire ecosystem. You'll see why that change happened, what a project gains by adopting MAUI, and you'll build a simple mobile screen showing BiblioTech's catalog, with XAML that will feel very familiar after the WPF lesson. This closes out Module 7's tour of the main ways to give a C# application an interface.
Contents
- Xamarin.Forms: its historical role in mobile development with C#
- Why Microsoft replaced Xamarin.Forms with .NET MAUI
- What a project gains with .NET MAUI: a single cross-platform project
- Basic structure of a MAUI project
ContentPageand XAML: similarities with WPF- Complete example: a BiblioTech catalog screen with
CollectionView - Closing out Module 7 and the link to Module 8
- Xamarin.Forms: its historical role in mobile development with C#
Before Xamarin, developing an Android application required Java or Kotlin, and iOS required Objective-C or Swift: two completely separate codebases, needing two teams or twice the effort for the same application. Xamarin, acquired by Microsoft in 2016, made it possible to write that logic in C# and compile it natively for both platforms; Xamarin.Forms, specifically, further added a shared interface layer in XAML, so that not even the visual interface had to be written twice.
For several years, Xamarin.Forms was Microsoft's main route to cross-platform mobile development
in C#, and a great many applications in production still run on it. It's important to recognize
this if you come across existing Xamarin.Forms code: the XAML syntax and ContentPage concepts
you'll see in this lesson are, to a large extent, the very same ones Xamarin.Forms introduced back
then.
- Why Microsoft replaced Xamarin.Forms with .NET MAUI
Microsoft announced the end of support for Xamarin.Forms and its evolution into .NET MAUI as its official successor, integrated directly into .NET (starting with .NET 6), instead of being kept as a separate framework with its own lifecycle. The main reasons behind this change:
| Xamarin.Forms limitation | How .NET MAUI solves it |
|---|---|
| A project separate from the rest of the .NET ecosystem, with its own tools and release cycle | Integrated into .NET from the ground up: same SDK, same dotnet new, same versions as the rest of the course |
| One project per platform (Android, iOS) with duplicated configuration | A single cross-platform project (section 3) |
| No native support for desktop applications (Windows, macOS) | Desktop support included from the initial design |
| An older rendering architecture, with more intermediate layers | A more direct, better-performing handlers architecture |
.NET MAUI, then, isn't a brand-new framework unrelated to Xamarin.Forms: it's its official evolution/successor, designed precisely to solve those architectural limitations and unify mobile development within the same .NET already used throughout the rest of this course. An existing Xamarin.Forms project can be migrated to .NET MAUI (Microsoft documents that path), but for a new project in 2026, the natural choice is MAUI from the start.
- What a project gains with .NET MAUI: a single cross-platform project
The most visible gain of MAUI over the original Xamarin.Forms is unification: a single
.csproj project compiles for several target platforms, with no separate projects to maintain:
flowchart TD
P["A single .NET MAUI project<br/>(BiblioTech.Mobile)"] --> A["Android"]
P --> I["iOS"]
P --> W["Windows"]
P --> M["macOS (Mac Catalyst)"]
That same project can also share its XAML interface with a desktop WPF project — the basic control
and binding syntax is very similar between WPF and MAUI, as you'll see in section 5 — and, of
course, it can directly reference BiblioTech's existing domain classes (Library, Book,
Member...), with no adaptation needed.
- Basic structure of a MAUI project
BiblioTech.Mobile/
├── MauiProgram.cs
├── App.xaml
├── App.xaml.cs
├── MainPage.xaml
├── MainPage.xaml.cs
└── Platforms/
├── Android/
├── iOS/
├── Windows/
└── MacCatalyst/MauiProgram.cs: the application's startup point, where the services container is configured — the same dependency injection mechanism seen in ASP.NET Core and Blazor.App.xaml/App.xaml.cs: the application itself, which decides which page to show on startup.MainPage.xaml/.xaml.cs: the first screen, with the same XAML + code-behind pattern already known from WPF.Platforms/: platform-specific code (native icons, permissions...), rarely needed for a simple application like this lesson's.
// MauiProgram.cs (fragment)
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>();
builder.Services.AddSingleton<Library>(); // same services container as ASP.NET Core/Blazor
return builder.Build();
}
}
ContentPage and XAML: similarities with WPF
ContentPage and XAML: similarities with WPFA MAUI screen is a ContentPage, the mobile equivalent of a WPF Window, and its XAML uses an
almost identical syntax:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BiblioTech.Mobile.MainPage">
<StackLayout Padding="20">
<Label Text="BiblioTech Catalog" FontSize="20" FontAttributes="Bold" />
<CollectionView x:Name="catalogCollectionView" />
</StackLayout>
</ContentPage>| WPF | .NET MAUI | Equivalence |
|---|---|---|
Window |
ContentPage |
The screen's root container |
StackPanel |
StackLayout |
Stacks children vertically or horizontally |
TextBlock |
Label |
Non-editable text |
ListBox/ListView |
CollectionView |
List of items, with ItemsSource data binding |
{Binding ...} |
{Binding ...} |
Same data binding syntax |
x:Class, x:Name |
x:Class, x:Name |
Same attributes from XAML's x: namespace |
Anyone who already knows WPF recognizes the structure immediately: a layout container, child
controls, and bindings with the same {Binding PropertyName} syntax. The MVVM pattern
(ViewModel, INotifyPropertyChanged) introduced in the WPF lesson applies to MAUI in exactly the
same way, with no new concept to learn on that front.
- Complete example: a BiblioTech catalog screen with
CollectionView
CollectionViewReusing the CatalogViewModel from the WPF lesson almost unchanged (same properties, same
ICommand), the MAUI screen:
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BiblioTech.Mobile.MainPage">
<StackLayout Padding="20">
<Label Text="BiblioTech Catalog" FontSize="20" FontAttributes="Bold" />
<CollectionView ItemsSource="{Binding Catalog}"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" Padding="0,5">
<Label Text="{Binding Title}" FontAttributes="Bold" WidthRequest="200" />
<Label Text="{Binding Author}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Button Text="Lend" Command="{Binding LendCommand}" Margin="0,10,0,0" />
<Label Text="{Binding StatusMessage}" Margin="0,10,0,0" />
</StackLayout>
</ContentPage>// MainPage.xaml.cs (code-behind, just as minimal as in WPF)
public partial class MainPage : ContentPage
{
public MainPage(Library library)
{
InitializeComponent();
BindingContext = new CatalogViewModel(library); // equivalent to DataContext in WPF
}
}CollectionView.ItemTemplate/DataTemplate defines how each item of the list is drawn — here,
a row with the title in bold and the author next to it — something that in WPF would be solved
equivalently with ItemTemplate on a ListBox or ListView. BindingContext is, in MAUI, the
name of the property equivalent to DataContext in WPF: both indicate which object the view's
{Binding ...} refer to. CatalogViewModel itself — with Catalog, SelectedItem,
LendCommand, and StatusMessage — is exactly the same class written in the WPF lesson, with no
modification at all: the very same C# class works, unchanged, in both a desktop window and a
mobile screen.
- Closing out Module 7 and the link to Module 8
This lesson closes out Module 7's tour of the main ways to give BiblioTech an interface: desktop
with Windows Forms and WPF, web with ASP.NET Core and Blazor, and cross-platform (mobile and
desktop) with Xamarin.Forms/.NET MAUI. Across the five lessons, the domain built in the previous
modules — LibraryItem, Book, Magazine, Member, Loan, Library — hasn't changed by a
single line: each technology has simply added a different presentation layer on top of the same
core logic.
Module 8 (Best Practices and Design Patterns) now takes all that code built throughout the course — the domain, the persistence, and this module's five interfaces — and puts it under review: coding standards, classic design patterns, dependency injection in depth (the mechanism only mentioned in passing here, in ASP.NET Core, Blazor, and MAUI), unit testing, and refactoring. It's the module where BiblioTech stops growing in functionality and starts being polished in quality.
Common Mistakes and Tips
- Treating Xamarin.Forms as if it were interchangeable with .NET MAUI with no changes at all: even though they share a philosophy and a very similar XAML syntax, MAUI reorganizes the project's structure (a single cross-platform project, instead of several) and changes internal namespaces and APIs; migrating a real Xamarin.Forms project requires following the official migration guide, it isn't a simple template swap.
- Starting a new mobile project in Xamarin.Forms in 2026: since it's the predecessor already officially replaced, any new project should start directly from .NET MAUI, which is where active development and support are.
- Forgetting that MAUI also covers desktop (Windows, macOS), not just mobile: it's common to think of MAUI purely as "Xamarin for mobile," when in reality its range of target platforms is broader, including the same desktop platforms that WPF or Windows Forms cover separately.
- Tip: if you already know WPF (previous lesson), build on that foundation when learning MAUI:
most concepts (XAML, data binding, MVVM,
ICommand) transfer almost directly, only the specific names of some controls change (StackPanel→StackLayout,TextBlock→Label).
Exercises
-
Complete the equivalence table from section 5 by adding a row for
Button(identical in both frameworks) and another forGrid(also available in both, with the same row/column syntax). -
Explain, in a short paragraph, why the same
CatalogViewModelfrom the WPF lesson can be reused unchanged in this lesson's MAUI screen, and which design principle (already seen in the WPF lesson) makes that possible.
Solutions
| WPF | .NET MAUI | Equivalence |
|---|---|---|
Button |
Button |
Same name and main properties (Content/Text, Command) in both |
Grid |
Grid |
Same name; rows/columns defined with RowDefinitions/ColumnDefinitions in both |
CatalogViewModel doesn't know or depend on any specific visual control: it only exposes
properties (Catalog, SelectedItem, StatusMessage) and a command (LendCommand),
communicating with the view exclusively through INotifyPropertyChanged and ICommand. That is
precisely the separation the MVVM pattern enforces: the view (whether a WPF Window or a
MAUI ContentPage) is the only part that changes between platforms; the ViewModel, knowing
nothing about specific controls, is independent of the interface technology and can be reused
as is.
Conclusion
In this lesson you've seen Xamarin.Forms's historical role in cross-platform mobile development
with C#, why .NET MAUI replaces it as its official evolution — unifying mobile and desktop into a
single project integrated into .NET — and you've built a MAUI screen that reuses, unchanged, the
very same CatalogViewModel from the WPF lesson thanks to the separation MVVM enforces. With
ContentPage, CollectionView, and XAML almost identical to WPF's, BiblioTech now has a presence
on desktop, web, and mobile devices, always on top of the same domain built since Module 2.
This closes out Module 7 (Building Applications) in full. Module 8 (Best Practices and Design Patterns) now picks up all the accumulated code — the domain, the persistence, and this module's five interfaces — to polish it: coding standards, design patterns, dependency injection in depth, unit testing, and review and refactoring, closing the cycle before the Final Project in Module 9.
C# Programming Course
Module 1: Introduction to C#
- Introduction to C#
- Setting Up the Development Environment
- Hello World Program
- Basic Syntax and Structure
- Variables and Data Types
- Arrays and Strings
Module 2: Control Structures
Module 3: Object-Oriented Programming
- Classes and Objects
- Methods
- Constructors and Destructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
- Structs and Records: Value Types and Reference Types
Module 4: Advanced C# Concepts
- Interfaces
- Delegates and Events
- Pattern Matching and Modern C# Features
- Generics
- Collections
- LINQ (Language Integrated Query)
- Asynchronous Programming
Module 5: Working with Data
- File I/O
- Serialization
- Database Connectivity
- Entity Framework
- Working with JSON and Consuming REST APIs
Module 6: Advanced Topics
- Reflection
- Attributes
- Dynamic Programming
- Memory Management and Garbage Collection
- Multithreading and Parallel Programming
Module 7: Building Applications
Module 8: Best Practices and Design Patterns
- Coding Standards and Best Practices
- Design Patterns
- Dependency Injection and Inversion of Control
- Unit Testing
- Code Review and Refactoring
