TreeDataGrid distinguishes between model indexes and visible row indexes.
Understanding this difference is critical for selection, expansion, sorting, and drag/drop.
IndexPath: Hierarchical Model AddressIndexPath identifies a model row in the source hierarchy.
Examples:
new IndexPath(0)new IndexPath(0, 1)new IndexPath(0, 1, 0)Conveniences:
int for flat roots (IndexPath p = 3;)IndexPath.Unselected for empty/no selectionAppend(int) to build deeper pathsCellIndex: Cell AddressCellIndex combines:
ColumnIndex (int)RowIndex (IndexPath)It is used by cell selection APIs.
Example:
var cell = new CellIndex(columnIndex: 2, rowIndex: new IndexPath(0, 1));
IndexPath addresses model position. Visible row index addresses current on-screen order.
They can differ when:
Row collections expose conversion APIs:
IRows.ModelIndexToRowIndex(IndexPath)IRows.RowIndexToModelIndex(int)IndexPath (model index), not visible row index.BringIntoView, TryGetRow).Use IndexPath helpers when traversing:
path[..^1]path.Append(childIndex)parent.IsAncestorOf(child)parent.IsParentOf(child)var modelIndex = new IndexPath(0, 1, 0);
Source.RowSelection!.SelectedIndex = modelIndex;
var rowIndex = Source.Rows.ModelIndexToRowIndex(modelIndex);
if (rowIndex >= 0)
grid.RowsPresenter?.BringIntoView(rowIndex);
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.