This article explains TreeDataGrid selection contracts below the basic row/cell usage layer.
The internal stack has three levels:
Use batching when applying many selection changes.
Two public patterns:
BeginBatchUpdate() / EndBatchUpdate() on ITreeSelectionModelTreeSelectionModelBase<T>.BatchUpdateOperation from BatchUpdate() on concrete modelusing Avalonia.Controls;
using Avalonia.Controls.Selection;
if (source.RowSelection is TreeDataGridRowSelectionModel<Person> rows)
{
using var update = rows.BatchUpdate();
rows.Clear();
rows.Select(new IndexPath(0));
rows.Select(new IndexPath(2));
rows.Select(new IndexPath(4));
}
Batching delays expensive notifications and keeps selection-change events coherent.
Key event args:
TreeSelectionModelSelectionChangedEventArgs<T>Important behavior:
SelectionChanged can be skipped by source Reset semantics in INotifyCollectionChanged providers.SelectionChanged handling with SourceReset when you need durable consistency.SelectionNodeBase<T> manages range state for each tree level and updates selection ranges on source changes.
You usually do not instantiate it directly, but it is the core reason hierarchical selection remains stable across add/remove/replace operations.
ITreeDataGridColumnSelectionModel and TreeDataGridColumnSelectionModel represent selected columns and are composed by cell-selection logic.
Duplicate or noisy selection events Cause: batch boundaries are missing during grouped updates.
Selection disappears after source reset
Cause: consumer listens only to SelectionChanged and ignores SourceReset.
Keyboard/pointer behavior differs after custom selection assignment Cause: assigned selection does not implement ITreeDataGridSelectionInteraction.