TemplateColumn<TModel> renders cells through DataTemplate and optional editing template.
Use it when TextColumn/CheckBoxColumn are not enough.
Choose one of the following constructor families based on how templates are provided.
new TemplateColumn<Person>(
header: "Selected",
cellTemplate: new FuncDataTemplate<Person>((_, _) => new CheckBox
{
[!CheckBox.IsCheckedProperty] = new Binding("IsSelected"),
}))
new TemplateColumn<Person>("Region", "RegionCell", "RegionEditCell")
This resolves templates from control resources at runtime.
<TreeDataGrid Source="{Binding Source}">
<TreeDataGrid.Resources>
<DataTemplate x:Key="RegionCell">
<TextBlock Text="{Binding Region}"/>
</DataTemplate>
<DataTemplate x:Key="RegionEditCell">
<ComboBox ItemsSource="{x:Static m:Countries.Regions}"
SelectedItem="{Binding Region}"/>
</DataTemplate>
</TreeDataGrid.Resources>
</TreeDataGrid>
A template column is editable only if editing template is provided.
cellEditingTemplate is null: read-onlyTemplateColumnOptions<TModel> supports:
IsTextSearchEnabledTextSearchValueSelectorColumnOptions<TModel> (sorting, width, edit gestures, etc.)Example with text search and custom sort:
new TemplateColumn<FileNode>(
"Name",
"FileNameCell",
"FileNameEditCell",
GridLength.Star,
new TemplateColumnOptions<FileNode>
{
IsTextSearchEnabled = true,
TextSearchValueSelector = x => x.Name,
CompareAscending = (a, b) => string.Compare(a?.Name, b?.Name, StringComparison.OrdinalIgnoreCase),
CompareDescending = (a, b) => string.Compare(b?.Name, a?.Name, StringComparison.OrdinalIgnoreCase),
})
If resource key is missing, template lookup throws KeyNotFoundException.
Recommendation:
Feature behavior differs from expectations
Cause: one or more options in this scenario are configured differently (source type, column options, sort/selection/edit state).
Fix: compare your setup with the snippet in this article and verify runtime values on Source, Columns, and Selection.
Data changes are not visible in UI
Cause: model or collection notifications are missing, or a replaced collection/source is not re-bound.
Fix: ensure INotifyPropertyChanged/INotifyCollectionChanged flow is active and reassign Source after replacing underlying collections.