Building UI with XAML and MVVM in .NET MAUI

Simplify Cross-Platform UIs with XAML and MVVM in .NET MAUI
This post is part 3 of 5 in the series Mastering .NET MAUI: From Beginner to Pro

Are you still juggling click events and code-behind spaghetti to build your UI logic? It’s time to break free and embrace a cleaner, scalable approach with XAML and MVVM in .NET MAUI.

.NET MAUI (Multi-platform App UI) brings the power of XAML-based UI and the MVVM (Model-View-ViewModel) pattern to cross-platform development. This means you can write clean UIs and better separate concerns in your apps. Let me show you how to build a professional-grade UI using these tools.

XAML Basics

XAML (Extensible Application Markup Language) is a declarative language to define UI layouts in .NET MAUI.

Layout Containers

MAUI provides several layout containers that define how elements are arranged:

  • StackLayout: Stacks elements vertically or horizontally.
  • Grid: Places elements in rows and columns.
  • FlexLayout: Offers more control, similar to CSS flexbox.

Example: Simple StackLayout in XAML

<VerticalStackLayout Padding="20">
    <Label Text="Welcome to .NET MAUI!"
           FontSize="24"
           HorizontalOptions="Center" />
    <Button Text="Click Me" />
</VerticalStackLayout>

This defines a vertical stack with a label and a button centered horizontally.

Explanation: VerticalStackLayout stacks children vertically. Padding provides space around content, and HorizontalOptions="Center" aligns the label.

Example: Grid Layout in XAML

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="2*" />
    </Grid.ColumnDefinitions>

    <Label Text="Username:" Grid.Row="0" Grid.Column="0" />
    <Entry Placeholder="Enter name" Grid.Row="0" Grid.Column="1" />
</Grid>

Explanation: Grid splits layout into rows and columns. RowDefinitions and ColumnDefinitions define the structure. Controls are placed using Grid.Row and Grid.Column attributes.

Example: FlexLayout in XAML

<FlexLayout Direction="Row" JustifyContent="SpaceBetween" AlignItems="Center">
    <BoxView Color="Red" WidthRequest="50" HeightRequest="50" />
    <BoxView Color="Green" WidthRequest="50" HeightRequest="50" />
    <BoxView Color="Blue" WidthRequest="50" HeightRequest="50" />
</FlexLayout>

Explanation: FlexLayout is ideal for responsive layouts. Direction sets layout orientation, JustifyContent controls spacing, and AlignItems aligns children.

Data Binding and MVVM

With MVVM, you bind the View (XAML) to a ViewModel. This keeps your UI logic out of code-behind files.

Binding Data

Example: Binding a property to a label

<Label Text="{Binding Title}" FontSize="20" />

In the ViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    private string title = "Hello from ViewModel!";
    public string Title
    {
        get => title;
        set
        {
            if (title != value)
            {
                title = value;
                OnPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string name = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

Explanation: The ViewModel exposes a Title property. The UI binds to it using {Binding Title}.

Commands and Event Binding

Example: Binding a button click to a command

<Button Text="Click Me" Command="{Binding ClickCommand}" />

ViewModel:

public ICommand ClickCommand { get; }

public MainViewModel()
{
    ClickCommand = new Command(OnClicked);
}

private void OnClicked()
{
    Title = "You clicked the button!";
}

Explanation: Commands decouple UI events from business logic. The ClickCommand is triggered on button press.

Using ViewModels with Dependency Injection

Register your ViewModel in MauiProgram.cs:

builder.Services.AddSingleton<MainViewModel>();

In the code-behind of the view:

BindingContext = serviceProvider.GetService<MainViewModel>();

Styles, Resources, and Themes

Consistency matters. Instead of repeating styles, define them in resource dictionaries.

Example: App.xaml

<Application.Resources>
    <Style TargetType="Label">
        <Setter Property="FontSize" Value="18" />
        <Setter Property="TextColor" Value="DarkBlue" />
    </Style>
</Application.Resources>

Explanation: This makes all Label elements have a font size of 18 and dark blue text.

Resource Dictionaries

Define custom resources like colors and reuse them:

<Color x:Key="PrimaryColor">#3498db</Color>

Use it like:

<Label TextColor="{StaticResource PrimaryColor}" />

Themes

Create LightTheme.xaml and DarkTheme.xaml in Resources\Styles, and load based on OS settings:

App.Current.UserAppTheme = AppTheme.Dark; // or AppTheme.Light

FAQ: Common Questions About XAML and MVVM in .NET MAUI

Do I need to use MVVM in .NET MAUI?

No, but MVVM helps you maintain a clean, testable, and scalable codebase.

How do I debug data binding issues?

Use output logs and ensure the ViewModel is correctly set as the BindingContext.

Can I use CommunityToolkit.Mvvm?

Absolutely! It simplifies MVVM with source generators and attributes.

Conclusion: Build Smarter UIs with Less Effort

.NET MAUI with XAML and MVVM gives you superpowers to build robust, maintainable UIs across platforms. No more wrestling with tangled code-behind logic—embrace declarative UI and data binding for a cleaner codebase.

Try applying MVVM in your next MAUI screen and see the difference. Got questions or want to share how you’re using MVVM? Drop a comment below or explore more articles on the blog!

Leave a Reply

Your email address will not be published. Required fields are marked *