HandyOrg/HandyControl · error · Exception
RelativePanel error: Circular dependency detected. Layout…
Error message
RelativePanel error: Circular dependency detected. Layout could not complete.
What it means
During layout, RelativePanel performs a topological traversal of dependency nodes between children. If it revisits an element already in the processed set, the relationships form a cycle (e.g. A aligned relative to B and B aligned relative to A) and layout cannot complete, so it throws.
Solutions
- Review the RelativePanel children's Element* / Align*With properties and remove the mutual reference making the cycle
- Break the cycle by anchoring one element to the panel itself (e.g. AlignParentTop) instead of a sibling
- Wrap panel layout in a design-time-safe approach: validate dependency graph before assigning relative properties
Example fix
// before <TextBox x:Name="A" RelativePanel.Below="B" /> <TextBlock x:Name="B" RelativePanel.Above="A" /> <!-- cycle --> // after <TextBlock x:Name="B" RelativePanel.AlignParentTop="True" /> <TextBox x:Name="A" RelativePanel.Below="B" />
Defensive patterns
Strategy: validation
Validate before calling
// validate that no two children mutually reference each other before layout
var refs = new HashSet<string>();
foreach (var dep in elementDependencies)
if (!refs.Add(dep.Key)) throw new InvalidOperationException($"Cycle at {dep.Key}"); Try / catch
try { panel.UpdateLayout(); }
catch (Exception ex) when (ex.Message.Contains("Circular dependency")) { FixCycleInXaml(); } Prevention
- Draw the dependency graph of alignment properties before writing XAML
- Anchor at least one element to the panel itself
- Avoid mutually recursive ElementBelow/ElementAbove pairs
- Rename elements carefully so alignment attributes don't loop back
When it happens
Trigger: Defining child alignments in XAML that mutually reference each other, e.g. ElementBelow='B' on A while ElementAbove='A' on B, or circular AlignLeftWith/AlignRightWith chains.
Common situations: Copy-pasted XAML alignment attributes creating loops; dynamic code that sets relative properties based on each other; refactoring that renames elements and accidentally re-targets dependencies.
AI-assisted analysis of HandyOrg/HandyControl@2c0875ebd6 (2026-09-14).
Data as JSON: /api/errors/24dea17014d93dc5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs:456
/*
* 该节点无任何依赖,所以从这里开始计算元素位置。
* 因为无任何依赖,所以忽略同级元素
*/
if (!node.Measured && !node.OutgoingNodes.Any())
{
MeasureChild(node);
continue;
}
// 判断依赖元素是否全部排列完毕
if (node.OutgoingNodes.All(item => item.Measured))
{
MeasureChild(node);
continue;
}
// 判断是否有循环
if (!set.Add(node.Element)) throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete.");
// 没有循环,且有依赖,则继续往下
Measure(node.OutgoingNodes, set);
if (!node.Measured)
{
MeasureChild(node);
}
}
}
private void MeasureChild(GraphNode node)
{
var child = node.Element;
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
node.OriginDesiredSize = child.DesiredSize;
var alignLeftWithPanel = GetAlignLeftWithPanel(child);View on GitHub (pinned to 2c0875ebd6)