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

  1. Review the RelativePanel children's Element* / Align*With properties and remove the mutual reference making the cycle
  2. Break the cycle by anchoring one element to the panel itself (e.g. AlignParentTop) instead of a sibling
  3. 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

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)