Simplify Cross-Platform UIs with XAML and MVVM in .NET MAUI

Building UI with XAML and MVVM in .NET MAUI

Master MVVM to build maintainable, modern UIs. Covers data binding, layouts, commands, and theming in .NET MAUI.

.NET Development·By amarozka · March 23, 2025

Building UI with XAML and MVVM in .NET MAUI

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 *