Primary APIs:
ILogical.LogicalParentILogical.LogicalChildrenILogical.IsAttachedToLogicalTreeILogical.AttachedToLogicalTreeILogical.DetachedFromLogicalTreeLogicalExtensions.GetLogicalAncestors(...)LogicalExtensions.GetSelfAndLogicalAncestors(...)LogicalExtensions.FindLogicalAncestorOfType<T>(...)LogicalExtensions.GetLogicalChildren(...)LogicalExtensions.GetLogicalDescendants(...)LogicalExtensions.GetSelfAndLogicalDescendants(...)LogicalExtensions.FindLogicalDescendantOfType<T>(...)LogicalExtensions.GetLogicalParent(...)LogicalExtensions.GetLogicalSiblings(...)LogicalExtensions.IsLogicalAncestorOf(...)LogicalTreeAttachmentEventArgsStyledElement.OnAttachedToLogicalTree(...)StyledElement.OnDetachedFromLogicalTree(...)Reference source files:
src/Avalonia.Base/LogicalTree/ILogical.cssrc/Avalonia.Base/LogicalTree/LogicalExtensions.cssrc/Avalonia.Base/LogicalTree/LogicalTreeAttachmentEventArgs.cssrc/Avalonia.Base/StyledElement.cssrc/Avalonia.Controls/Templates/DataTemplateExtensions.csThe logical tree models ownership/composition semantics and is used heavily for:
DataContext,Logical relationships can differ from visual relationships (for example popups, presenters, overlays).
using Avalonia.Controls;
using Avalonia.LogicalTree;
var ownerItemsControl = this.FindLogicalAncestorOfType<ItemsControl>();
var firstPopup = this.FindLogicalDescendantOfType<Popup>();
using Avalonia.LogicalTree;
foreach (var node in myElement.GetSelfAndLogicalAncestors())
{
Console.WriteLine(node.GetType().Name);
}
using Avalonia.LogicalTree;
var parent = myElement.GetLogicalParent();
var siblings = myElement.GetLogicalSiblings();
bool isAncestor = parent.IsLogicalAncestorOf(myElement);
Use these patterns when diagnosing ownership and scoping issues rather than rendering issues.
Attachment hooks for logical-root-dependent setup:
using Avalonia.LogicalTree;
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
// e.Root, e.Source, e.Parent available
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
// cleanup logical-scope subscriptions/resources
}
Guidance:
IsAttachedToLogicalTree before relying on logical ancestor scopes.Logical ancestry directly affects common framework behavior:
IDataTemplateHost ancestors.DataContext propagation is logical-tree-driven.Practical implication:
Quick logical tree dump helper:
using Avalonia.LogicalTree;
static void DumpLogical(ILogical logical, int depth = 0)
{
Console.WriteLine($"{new string(' ', depth * 2)}{logical.GetType().Name}");
foreach (var child in logical.GetLogicalChildren())
{
DumpLogical(child, depth + 1);
}
}
Use this to verify containment and scope boundaries in composite controls.
DataContext not found:
IDataTemplateHost overrides app-level templates.null: