# XAML Performance / Tối Ưu XAML

Hướng dẫn chi tiết về Compiled Bindings, layout optimization và XAML best practices.

## Core Principles / Nguyên Tắc Cốt Lõi

1. **Compiled Bindings**: Luôn sử dụng `x:DataType` để binding tại compile-time
2. **Flat Layouts**: Tránh nested layouts, ưu tiên Grid
3. **Virtualization**: Sử dụng CollectionView cho danh sách lớn

---

## Compiled Bindings (BẮT BUỘC)

### Why Compiled Bindings?

| Aspect | Reflection Binding | Compiled Binding |
|--------|-------------------|------------------|
| Performance | Slow (runtime lookup) | Fast (compile-time) |
| Error Detection | Runtime exceptions | Compile-time errors |
| NativeAOT | May not work | Full support |
| Intellisense | No | Yes |

### Basic Pattern

```xml
<!-- ✅ ĐÚNG: Compiled Bindings -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MyApp.ViewModels"
             xmlns:models="clr-namespace:MyApp.Models"
             x:Class="MyApp.Views.ProductListPage"
             x:DataType="vm:ProductListViewModel">
    
    <!-- Binding được resolve tại compile-time -->
    <Label Text="{Binding Title}" />
    <Label Text="{Binding Products.Count, StringFormat='Total: {0}'}" />
    
    <CollectionView ItemsSource="{Binding Products}">
        <CollectionView.ItemTemplate>
            <!-- x:DataType thay đổi cho ItemTemplate -->
            <DataTemplate x:DataType="models:Product">
                <Grid>
                    <Label Text="{Binding Name}" />
                    <Label Text="{Binding Price, StringFormat='{0:C}'}" />
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</ContentPage>
```

```xml
<!-- ❌ SAI: Không có x:DataType -->
<ContentPage>
    <!-- Runtime reflection, chậm và không catch lỗi -->
    <Label Text="{Binding Titlee}" /> <!-- Typo không bị phát hiện! -->
</ContentPage>
```

### Nested DataType Changes

```xml
<CollectionView ItemsSource="{Binding Categories}"
                x:DataType="vm:CategoryListViewModel">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="models:Category">
            <StackLayout>
                <Label Text="{Binding Name}" />
                
                <!-- Nested collection -->
                <CollectionView ItemsSource="{Binding Products}">
                    <CollectionView.ItemTemplate>
                        <DataTemplate x:DataType="models:Product">
                            <Label Text="{Binding Name}" />
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
            </StackLayout>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
```

### Binding to Parent ViewModel from ItemTemplate

```xml
<CollectionView ItemsSource="{Binding Products}"
                x:DataType="vm:ProductListViewModel">
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="models:Product">
            <Grid>
                <Label Text="{Binding Name}" />
                
                <!-- Bind to parent ViewModel's command -->
                <Button Text="Select"
                        Command="{Binding Source={RelativeSource AncestorType={x:Type vm:ProductListViewModel}}, Path=SelectProductCommand}"
                        CommandParameter="{Binding .}" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
```

---

## Layout Optimization

### Grid vs Nested StackLayout

```xml
<!-- ❌ SAI: Nested StackLayout (deep visual tree) -->
<StackLayout>
    <StackLayout Orientation="Horizontal">
        <Image Source="{Binding ImageUrl}" />
        <StackLayout>
            <Label Text="{Binding Name}" />
            <Label Text="{Binding Description}" />
            <StackLayout Orientation="Horizontal">
                <Label Text="{Binding Price}" />
                <Button Text="Buy" />
            </StackLayout>
        </StackLayout>
    </StackLayout>
</StackLayout>
<!-- Visual tree depth: 5 levels -->

<!-- ✅ ĐÚNG: Flat Grid -->
<Grid RowDefinitions="Auto,Auto,Auto"
      ColumnDefinitions="80,*,Auto">
    
    <Image Source="{Binding ImageUrl}"
           Grid.RowSpan="3" />
    
    <Label Text="{Binding Name}"
           Grid.Column="1" />
    
    <Label Text="{Binding Description}"
           Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" />
    
    <Label Text="{Binding Price}"
           Grid.Row="2" Grid.Column="1" />
    
    <Button Text="Buy"
            Grid.Row="2" Grid.Column="2" />
</Grid>
<!-- Visual tree depth: 2 levels -->
```

### Layout Performance Tips

```xml
<!-- ✅ Fixed sizes when possible -->
<Image WidthRequest="80" HeightRequest="80" Aspect="AspectFill" />

<!-- ✅ Use Grid star sizing -->
<Grid ColumnDefinitions="*,2*,*">
    <!-- Proportional sizing, efficient -->
</Grid>

<!-- ❌ Avoid: AbsoluteLayout for complex UIs -->
<!-- ❌ Avoid: Deep nesting (>4 levels) -->
```

---

## CollectionView Best Practices

### Virtualization (Auto-enabled)

```xml
<!-- CollectionView tự động virtualize -->
<CollectionView ItemsSource="{Binding LargeList}"
                ItemsUpdatingScrollMode="KeepItemsInView">
    
    <!-- Fixed item size improves virtualization -->
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                          ItemSpacing="8" />
    </CollectionView.ItemsLayout>
    
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="models:Item">
            <!-- Keep template simple for performance -->
            <Grid HeightRequest="60" Padding="10">
                <Label Text="{Binding Name}" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
```

### EmptyView và Loading States

```xml
<CollectionView ItemsSource="{Binding Products}">
    
    <!-- Empty state -->
    <CollectionView.EmptyView>
        <ContentView>
            <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
                <Image Source="empty_box.svg" WidthRequest="100" />
                <Label Text="No products found" />
            </StackLayout>
        </ContentView>
    </CollectionView.EmptyView>
    
    <CollectionView.ItemTemplate>
        <!-- ... -->
    </CollectionView.ItemTemplate>
</CollectionView>

<!-- Loading overlay -->
<ActivityIndicator IsRunning="{Binding IsLoading}"
                   IsVisible="{Binding IsLoading}"
                   VerticalOptions="Center"
                   HorizontalOptions="Center" />
```

---

## Resource Dictionary Patterns

### App-level Resources

```xml
<!-- App.xaml -->
<Application.Resources>
    <ResourceDictionary>
        <!-- Merged dictionaries -->
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Resources/Styles/Colors.xaml" />
            <ResourceDictionary Source="Resources/Styles/Styles.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
```

### Colors.xaml

```xml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    
    <!-- Primary palette -->
    <Color x:Key="Primary">#6750A4</Color>
    <Color x:Key="PrimaryDark">#381E72</Color>
    <Color x:Key="Secondary">#625B71</Color>
    
    <!-- Semantic colors -->
    <Color x:Key="TextPrimary">#1C1B1F</Color>
    <Color x:Key="TextSecondary">#49454F</Color>
    <Color x:Key="Surface">#FFFBFE</Color>
    <Color x:Key="SurfaceVariant">#E7E0EC</Color>
    
    <!-- Status colors -->
    <Color x:Key="Success">#4CAF50</Color>
    <Color x:Key="Warning">#FF9800</Color>
    <Color x:Key="Error">#B3261E</Color>
</ResourceDictionary>
```

### Styles.xaml

```xml
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    
    <!-- Base styles -->
    <Style TargetType="Label" x:Key="TitleLabel">
        <Setter Property="FontSize" Value="24" />
        <Setter Property="FontFamily" Value="InterBold" />
        <Setter Property="TextColor" Value="{StaticResource TextPrimary}" />
    </Style>
    
    <Style TargetType="Label" x:Key="BodyLabel">
        <Setter Property="FontSize" Value="16" />
        <Setter Property="FontFamily" Value="InterRegular" />
        <Setter Property="TextColor" Value="{StaticResource TextSecondary}" />
    </Style>
    
    <Style TargetType="Button" x:Key="PrimaryButton">
        <Setter Property="BackgroundColor" Value="{StaticResource Primary}" />
        <Setter Property="TextColor" Value="White" />
        <Setter Property="FontFamily" Value="InterSemiBold" />
        <Setter Property="CornerRadius" Value="8" />
        <Setter Property="Padding" Value="16,12" />
    </Style>
    
    <!-- Apply style globally -->
    <Style TargetType="Entry" ApplyToDerivedTypes="True">
        <Setter Property="FontFamily" Value="InterRegular" />
        <Setter Property="FontSize" Value="16" />
    </Style>
</ResourceDictionary>
```

### Usage in Pages

```xml
<Label Text="Welcome" Style="{StaticResource TitleLabel}" />
<Label Text="Description" Style="{StaticResource BodyLabel}" />
<Button Text="Submit" Style="{StaticResource PrimaryButton}" />

<!-- Dynamic resource (theme switching) -->
<Label TextColor="{DynamicResource TextPrimary}" />
```

---

## Hot Reload Tips

```xml
<!-- ✅ Hot Reload friendly -->
<Label Text="Static text" />
<Label Text="{Binding DynamicText}" />

<!-- ⚠️ May require restart -->
<!-- Changes to: -->
<!-- - x:DataType -->
<!-- - Namespace imports -->
<!-- - Resource dictionary structure -->
```

---

## Common Mistakes / Lỗi Thường Gặp

### 1. Missing x:DataType in ItemTemplate

```xml
<!-- ❌ SAI -->
<CollectionView ItemsSource="{Binding Products}" x:DataType="vm:ListViewModel">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <!-- Binding uses reflection, slow! -->
            <Label Text="{Binding Name}" />
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

<!-- ✅ ĐÚNG -->
<DataTemplate x:DataType="models:Product">
    <Label Text="{Binding Name}" />
</DataTemplate>
```

### 2. Image Not Caching

```xml
<!-- ❌ SAI: Reload mỗi lần -->
<Image Source="{Binding ImageUrl}" />

<!-- ✅ ĐÚNG: Enable caching -->
<Image>
    <Image.Source>
        <UriImageSource Uri="{Binding ImageUrl}"
                        CachingEnabled="True"
                        CacheValidity="1:00:00:00" />
    </Image.Source>
</Image>
```

### 3. Heavy Work in Converters

```csharp
// ❌ SAI: Slow converter
public object Convert(object value, ...)
{
    // Heavy computation on UI thread!
    return ProcessData(value);
}

// ✅ ĐÚNG: Pre-compute in ViewModel
[ObservableProperty]
private string _processedValue; // Already computed
```

---

## Performance Checklist

- [ ] `x:DataType` declared on every page and DataTemplate
- [ ] No nested StackLayout deeper than 2 levels
- [ ] CollectionView used for lists (not StackLayout)
- [ ] Fixed sizes where possible (WidthRequest, HeightRequest)
- [ ] Image caching enabled for remote images
- [ ] Styles in ResourceDictionary, not inline
- [ ] StaticResource over DynamicResource when possible

---

## Resources

- [.NET MAUI Performance Best Practices](https://learn.microsoft.com/en-us/dotnet/maui/deployment/performance)
- [Compiled Bindings](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/compiled-bindings)
- [MVVM Rules](./mvvm-rules.md)
- [DI Setup](./di-setup.md)
