This guide covers advanced TreeDataGrid theming where you replace built-in ControlTheme templates with fully new templates.
Use this when BasedOn overrides cannot express the visual tree or interaction behavior you need.
When replacing templates, preserve required part names used by control code.
| Control | Required part(s) |
|---|---|
TreeDataGrid |
PART_HeaderScrollViewer, PART_ColumnHeadersPresenter, PART_ScrollViewer, PART_RowsPresenter |
TreeDataGridColumnHeader |
PART_Resizer |
TreeDataGridRow |
PART_CellsPresenter |
TreeDataGridExpanderCell |
PART_Content |
TreeDataGridTextCell |
PART_Edit (editing template) |
TreeDataGridTemplateCell |
PART_EditingContentPresenter (editing template) |
If a required part is missing, features such as resizing, editing focus, realization, or expansion content rendering will break.
This example replaces the entire TreeDataGridColumnHeader theme and keeps sorting and resize behavior by preserving SortIcon and PART_Resizer.
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ControlTheme x:Key="NeoTreeDataGridColumnHeaderTheme"
TargetType="TreeDataGridColumnHeader">
<Setter Property="Padding" Value="12 6" />
<Setter Property="Template">
<ControlTemplate>
<Border Name="DataGridBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid ColumnDefinitions="*,Auto,Auto">
<ContentPresenter Name="PART_ContentPresenter"
Grid.Column="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
<Path Name="SortIcon"
Grid.Column="1"
Margin="6 0"
Width="10"
Height="10"
IsVisible="False"
Fill="{TemplateBinding Foreground}"
Stretch="Uniform" />
<Thumb Name="PART_Resizer"
Grid.Column="2"
Width="6"
Background="Transparent"
Cursor="SizeWestEast"
IsVisible="{TemplateBinding CanUserResize}" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^:pointerover /template/ Border#DataGridBorder">
<Setter Property="Background" Value="#22000000" />
</Style>
<Style Selector="^:pressed /template/ Border#DataGridBorder">
<Setter Property="Background" Value="#44000000" />
</Style>
<Style Selector="^[SortDirection=Ascending] /template/ Path#SortIcon">
<Setter Property="IsVisible" Value="True" />
<Setter Property="Data" Value="{DynamicResource TreeDataGridSortIconAscendingPath}" />
</Style>
<Style Selector="^[SortDirection=Descending] /template/ Path#SortIcon">
<Setter Property="IsVisible" Value="True" />
<Setter Property="Data" Value="{DynamicResource TreeDataGridSortIconDescendingPath}" />
</Style>
</ControlTheme>
</Application.Resources>
<Application.Styles>
<FluentTheme/>
<StyleInclude Source="avares://Avalonia.Controls.TreeDataGrid/Themes/Fluent.axaml"/>
<Style Selector="TreeDataGridColumnHeader">
<Setter Property="Theme" Value="{DynamicResource NeoTreeDataGridColumnHeaderTheme}" />
</Style>
</Application.Styles>
</Application>
When replacing TreeDataGridTextCell, keep a dedicated editing template with PART_Edit so edit activation and initial selection still work.
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ControlTheme x:Key="NeoTreeDataGridTextCellTheme"
TargetType="TreeDataGridTextCell">
<Setter Property="Padding" Value="8 4" />
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<TextBlock Text="{TemplateBinding Value}"
TextTrimming="{TemplateBinding TextTrimming}"
TextWrapping="{TemplateBinding TextWrapping}"
TextAlignment="{TemplateBinding TextAlignment}"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^:editing">
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<TextBox Name="PART_Edit"
Text="{TemplateBinding Value, Mode=TwoWay}" />
</Border>
</ControlTemplate>
</Setter>
</Style>
</ControlTheme>
</Application.Resources>
<Application.Styles>
<FluentTheme/>
<StyleInclude Source="avares://Avalonia.Controls.TreeDataGrid/Themes/Fluent.axaml"/>
<Style Selector="TreeDataGridTextCell">
<Setter Property="Theme" Value="{DynamicResource NeoTreeDataGridTextCellTheme}" />
</Style>
</Application.Styles>
</Application>
Generic.axaml templates and copy only the control(s) you need to replace.:editing, SortDirection=...) for behavior-critical visuals.Column header resize no longer works
Cause: PART_Resizer missing or renamed.
Fix: restore Thumb Name="PART_Resizer" in the header template.
Text editing starts but focus is not inside editor
Cause: editing template does not include TextBox Name="PART_Edit".
Fix: restore PART_Edit in :editing template.
Expander cell content disappears
Cause: TreeDataGridExpanderCell template is missing Decorator Name="PART_Content".
Fix: restore PART_Content host in the expander cell template.