xaml-csharp-development-skill-for-avalonia

Data Templates and IDataTemplate Selector Patterns

Table of Contents

  1. Scope and APIs
  2. Template Resolution Order
  3. WPF TemplateSelector Equivalent in Avalonia
  4. Typed Templates and DataType Rules
  5. ItemTemplate, DisplayMemberBinding, and Recycling
  6. TreeDataTemplate Patterns
  7. Function Tree Templates and Template Utility APIs
  8. Best Practices
  9. Troubleshooting

Scope and APIs

Primary APIs:

Reference source files:

Template Resolution Order

DataTemplateExtensions.FindDataTemplate(...) resolves in this order:

  1. Primary template (for example ContentTemplate/ItemTemplate) if Match succeeds.
  2. Nearest logical-tree IDataTemplateHost.DataTemplates moving up ancestors.
  3. Global app templates (Application.DataTemplates via IGlobalDataTemplates).

ContentPresenter then falls back to default templates when needed:

This precedence is critical when multiple templates can match the same data.

WPF TemplateSelector Equivalent in Avalonia

Avalonia does not use WPF DataTemplateSelector; use IDataTemplate instead.

Selector-style implementation:

using Avalonia.Controls;
using Avalonia.Controls.Templates;

public sealed class MessageTemplateSelector : IDataTemplate
{
    public bool Match(object? data) => data is MessageViewModel;

    public Control? Build(object? data)
    {
        return data switch
        {
            ErrorMessageViewModel vm => new ErrorMessageView { DataContext = vm },
            WarningMessageViewModel vm => new WarningMessageView { DataContext = vm },
            InfoMessageViewModel vm => new InfoMessageView { DataContext = vm },
            MessageViewModel vm => new DefaultMessageView { DataContext = vm },
            _ => null
        };
    }
}

Register in templates:

<Application.DataTemplates>
  <local:MessageTemplateSelector />
</Application.DataTemplates>

Alternative selector pattern with FuncDataTemplate ordering:

var templates = new DataTemplates
{
    new FuncDataTemplate<ErrorMessageViewModel>((vm, _) => new ErrorMessageView { DataContext = vm }),
    new FuncDataTemplate<MessageViewModel>((vm, _) => new DefaultMessageView { DataContext = vm })
};

Typed Templates and DataType Rules

Important rule from DataTemplates:

Example:

<Application.DataTemplates>
  <DataTemplate x:DataType="vm:DashboardViewModel">
    <views:DashboardView />
  </DataTemplate>
</Application.DataTemplates>

Untyped custom IDataTemplate implementations can still participate without DataType.

ItemTemplate, DisplayMemberBinding, and Recycling

ItemsControl behavior highlights:

Recycling:

Example:

listBox.ItemTemplate = new FuncDataTemplate<RowViewModel>(
    (row, _) => new RowView { DataContext = row },
    supportsRecycling: true);

TreeDataTemplate Patterns

For hierarchical data, use TreeDataTemplate/ITreeDataTemplate.

<TreeDataTemplate xmlns="https://github.com/avaloniaui"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:vm="using:MyApp.ViewModels"
                  x:DataType="vm:NodeViewModel"
                  ItemsSource="{CompiledBinding Children}">
  <TextBlock Text="{CompiledBinding Title}" />
</TreeDataTemplate>

In 11.3.12, TreeDataTemplate.ItemsSource supports:

Function Tree Templates and Template Utility APIs

Function-based tree templates:

Template utility contracts often used with this space:

API-index compatibility note:

For end-to-end advanced coverage of these APIs, see:

Best Practices

Troubleshooting

  1. Wrong template applied:
    • A broader template matched earlier in order.
    • Local template host shadows global app templates.
  2. Exception adding template to DataTemplates:
    • Typed template missing DataType.
  3. Item template appears ignored:
    • DisplayMemberBinding is also set (not allowed with ItemTemplate).
  4. Recycled item shows stale state:
    • Template opted into recycling but control state is not reset correctly.
  5. Tree template children not showing:
    • ItemsSource binding is invalid or not one-way observable for children.