Wednesday, 13 August 2025

Best Practices for XAML in .NET MAUI

Here's a complete guide to writing clean, maintainable XAML in .NET MAUI following best practices:

1. Basic Structure

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="MyApp.MainPage"
             Title="Main Page">
    
    <!-- Page content goes here -->
    
</ContentPage>

2. Layout Best Practices

Use Appropriate Layout Controls

xml
<Grid RowDefinitions="Auto, *, Auto"
     ColumnDefinitions="*, *"
     RowSpacing="10"
     ColumnSpacing="10">
    
    <Label Grid.Row="0" Grid.ColumnSpan="2"
           Text="Welcome to MyApp"
           HorizontalOptions="Center"
           FontSize="Title"/>
           
    <CollectionView Grid.Row="1" Grid.ColumnSpan="2"
                   ItemsSource="{Binding Items}">
        <!-- Item template -->
    </CollectionView>
    
    <Button Grid.Row="2" Grid.Column="0"
            Text="Cancel"
            Command="{Binding CancelCommand}"/>
            
    <Button Grid.Row="2" Grid.Column="1"
            Text="Confirm"
            Command="{Binding ConfirmCommand}"/>
</Grid>

Use StackLayout for Simple Vertical/Horizontal Stacks

xml
<StackLayout Spacing="15" Padding="20">
    <Label Text="Username"
           FontAttributes="Bold"/>
    <Entry Placeholder="Enter username"
           Text="{Binding Username}"/>
    <Label Text="Password"
           FontAttributes="Bold"/>
    <Entry Placeholder="Enter password"
           IsPassword="True"
           Text="{Binding Password}"/>
    <Button Text="Login"
            Command="{Binding LoginCommand}"/>
</StackLayout>

3. Resource Management

Define Resources at Appropriate Levels

xml
<ContentPage.Resources>
    <ResourceDictionary>
        <Color x:Key="PrimaryColor">#512BD4</Color>
        <Color x:Key="SecondaryColor">#DFD8F7</Color>
        
        <Style x:Key="BaseLabelStyle" TargetType="Label">
            <Setter Property="FontSize" Value="14"/>
            <Setter Property="TextColor" Value="{StaticResource PrimaryColor}"/>
        </Style>
        
        <Style x:Key="HeaderLabelStyle" TargetType="Label" BasedOn="{StaticResource BaseLabelStyle}">
            <Setter Property="FontSize" Value="20"/>
            <Setter Property="FontAttributes" Value="Bold"/>
        </Style>
    </ResourceDictionary>
</ContentPage.Resources>

4. Data Binding Best Practices

xml
<StackLayout>
    <!-- Use compiled bindings for better performance -->
    <Label Text="{Binding WelcomeMessage, Mode=OneWay}"
           Style="{StaticResource HeaderLabelStyle}"/>
           
    <!-- Use x:DataType for compile-time validation -->
    <CollectionView x:DataType="viewmodels:ItemsViewModel"
                    ItemsSource="{Binding Items}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType="models:Item">
                <Grid Padding="10">
                    <Label Text="{Binding Name}"
                           FontSize="16"/>
                    <Label Text="{Binding Description}"
                           FontSize="14"
                           TextColor="Gray"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</StackLayout>

5. Visual State Manager

xml
<StackLayout>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal"/>
            <VisualState x:Name="Selected">
                <VisualState.Setters>
                    <Setter Property="BackgroundColor" Value="{StaticResource SecondaryColor}"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    
    <!-- Content that will respond to visual states -->
</StackLayout>

6. Template Best Practices

ControlTemplate Example

xml
<ContentPage.Resources>
    <ControlTemplate x:Key="CardViewTemplate">
        <Frame BorderColor="{StaticResource PrimaryColor}"
               CornerRadius="10"
               Padding="15"
               HasShadow="True">
            <StackLayout>
                <ContentPresenter/>
                <Button Text="Action"
                        Command="{TemplateBinding BindingContext.ActionCommand}"
                        IsVisible="{TemplateBinding BindingContext.HasAction}"/>
            </StackLayout>
        </Frame>
    </ControlTemplate>
</ContentPage.Resources>

<!-- Usage -->
<ContentView ControlTemplate="{StaticResource CardViewTemplate}">
    <Label Text="This is a card component"
           FontSize="16"/>
</ContentView>

7. Accessibility

xml
<StackLayout>
    <Label Text="Welcome message"
           SemanticProperties.HeadingLevel="Level1"
           SemanticProperties.Description="Welcome text for the application"/>
           
    <Image Source="logo.png"
           SemanticProperties.Description="Company logo"
           HeightRequest="100"/>
           
    <Button Text="Continue"
            SemanticProperties.Hint="Navigates to the next page"/>
</StackLayout>

8. Complete Example Page

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"
             xmlns:viewmodels="clr-namespace:MyApp.ViewModels"
             xmlns:models="clr-namespace:MyApp.Models"
             x:Class="MyApp.Views.MainPage"
             Title="My App"
             x:DataType="viewmodels:MainViewModel">
    
    <ContentPage.Resources>
        <ResourceDictionary>
            <!-- Colors -->
            <Color x:Key="PrimaryColor">#512BD4</Color>
            <Color x:Key="SecondaryColor">#DFD8F7</Color>
            <Color x:Key="ErrorColor">#FF0000</Color>
            
            <!-- Styles -->
            <Style x:Key="BaseLabelStyle" TargetType="Label">
                <Setter Property="FontSize" Value="14"/>
                <Setter Property="TextColor" Value="{StaticResource PrimaryColor}"/>
            </Style>
            
            <Style x:Key="HeaderLabelStyle" TargetType="Label" BasedOn="{StaticResource BaseLabelStyle}">
                <Setter Property="FontSize" Value="20"/>
                <Setter Property="FontAttributes" Value="Bold"/>
                <Setter Property="Margin" Value="0,0,0,10"/>
            </Style>
            
            <Style x:Key="PrimaryButtonStyle" TargetType="Button">
                <Setter Property="BackgroundColor" Value="{StaticResource PrimaryColor}"/>
                <Setter Property="TextColor" Value="White"/>
                <Setter Property="CornerRadius" Value="5"/>
                <Setter Property="Padding" Value="20,10"/>
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ScrollView>
        <Grid RowDefinitions="Auto, Auto, *, Auto"
              ColumnDefinitions="*"
              RowSpacing="20"
              Padding="20">
            
            <!-- Header -->
            <Label Grid.Row="0"
                   Text="Welcome to MyApp"
                   Style="{StaticResource HeaderLabelStyle}"
                   HorizontalOptions="Center"/>
            
            <!-- User Info -->
            <StackLayout Grid.Row="1" Spacing="10">
                <Label Text="Username"
                       Style="{StaticResource BaseLabelStyle}"/>
                <Entry Placeholder="Enter username"
                       Text="{Binding Username}"/>
                
                <Label Text="Password"
                       Style="{StaticResource BaseLabelStyle}"/>
                <Entry Placeholder="Enter password"
                       IsPassword="True"
                       Text="{Binding Password}"/>
                
                <Label Text="{Binding ErrorMessage}"
                       TextColor="{StaticResource ErrorColor}"
                       IsVisible="{Binding HasError}"/>
            </StackLayout>
            
            <!-- Content Area -->
            <CollectionView Grid.Row="2"
                           ItemsSource="{Binding Items}"
                           SelectionMode="Single"
                           SelectedItem="{Binding SelectedItem}">
                <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="models:Item">
                        <Grid Padding="10">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="Selected">
                                        <VisualState.Setters>
                                            <Setter Property="BackgroundColor" Value="{StaticResource SecondaryColor}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            
                            <Label Text="{Binding Name}"
                                   FontSize="16"/>
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
            
            <!-- Buttons -->
            <Grid Grid.Row="3" ColumnDefinitions="*,*" ColumnSpacing="10">
                <Button Grid.Column="0"
                        Text="Cancel"
                        Command="{Binding CancelCommand}"/>
                
                <Button Grid.Column="1"
                        Text="Login"
                        Style="{StaticResource PrimaryButtonStyle}"
                        Command="{Binding LoginCommand}"/>
            </Grid>
        </Grid>
    </ScrollView>
</ContentPage>

Best Practices Summary

  1. Use appropriate layout controls - Choose Grid for complex layouts, StackLayout for simple stacks

  2. Organize resources - Define styles, colors, and templates in resource dictionaries

  3. Use compiled bindings (x:DataType) for better performance and compile-time validation

  4. Implement Visual State Manager for responsive UI states

  5. Create reusable templates with ControlTemplate and DataTemplate

  6. Prioritize accessibility with semantic properties

  7. Keep XAML clean by separating complex logic into view models

  8. Use proper naming conventions for resources and elements

  9. Optimize performance by minimizing nested layouts

  10. Consider light/dark mode by using AppThemeBinding where needed

Remember to complement your XAML with a well-structured ViewModel and Model layer to follow the MVVM pattern properly.

No comments:

Post a Comment

Complete Guide: Building a Live Cricket Streaming App for 100M Users

Comprehensive guide to building a scalable live cricket streaming platform for 100M users, covering backend infrastructure, streaming techno...