{"record":{"id":"24dea17014d93dc5","repo":"HandyOrg/HandyControl","slug":"relativepanel-error-circular-dependency-detected-layout","errorCode":null,"errorMessage":"RelativePanel error: Circular dependency detected. Layout could not complete.","messagePattern":"RelativePanel error: Circular dependency detected\\. Layout could not complete\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs","lineNumber":456,"sourceCode":"                /*\n                 * 该节点无任何依赖，所以从这里开始计算元素位置。\n                 * 因为无任何依赖，所以忽略同级元素\n                 */\n                if (!node.Measured && !node.OutgoingNodes.Any())\n                {\n                    MeasureChild(node);\n                    continue;\n                }\n\n                //  判断依赖元素是否全部排列完毕\n                if (node.OutgoingNodes.All(item => item.Measured))\n                {\n                    MeasureChild(node);\n                    continue;\n                }\n\n                //  判断是否有循环\n                if (!set.Add(node.Element)) throw new Exception(\"RelativePanel error: Circular dependency detected. Layout could not complete.\");\n\n                //  没有循环，且有依赖，则继续往下\n                Measure(node.OutgoingNodes, set);\n\n                if (!node.Measured)\n                {\n                    MeasureChild(node);\n                }\n            }\n        }\n\n        private void MeasureChild(GraphNode node)\n        {\n            var child = node.Element;\n            child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));\n            node.OriginDesiredSize = child.DesiredSize;\n\n            var alignLeftWithPanel = GetAlignLeftWithPanel(child);","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/HandyOrg/HandyControl/blob/2c0875ebd67326e0c67282967e3e809c69282fee/src/Shared/HandyControl_Shared/Controls/Panel/RelativePanel.cs#L438-L474","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n<TextBox x:Name=\"A\" RelativePanel.Below=\"B\" />\n<TextBlock x:Name=\"B\" RelativePanel.Above=\"A\" /> <!-- cycle -->\n// after\n<TextBlock x:Name=\"B\" RelativePanel.AlignParentTop=\"True\" />\n<TextBox x:Name=\"A\" RelativePanel.Below=\"B\" />","handlingStrategy":"validation","validationCode":"// validate that no two children mutually reference each other before layout\nvar refs = new HashSet<string>();\nforeach (var dep in elementDependencies)\n    if (!refs.Add(dep.Key)) throw new InvalidOperationException($\"Cycle at {dep.Key}\");","typeGuard":null,"tryCatchPattern":"try { panel.UpdateLayout(); }\ncatch (Exception ex) when (ex.Message.Contains(\"Circular dependency\")) { FixCycleInXaml(); }","preventionTips":["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"],"tags":["relativepanel","layout","circular-dependency"],"backgroundTag":"circular-dependency-detected","analyzedSha":"2c0875ebd67326e0c67282967e3e809c69282fee","analyzedAt":"2026-09-14T14:45:29.754Z","contentChangedAt":"2026-09-14T14:45:29.754Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}