{"record":{"id":"7a49134346ad7273","repo":"dotnet/wpf","slug":"0-must-be-the-root-element-of-a-tree-but-has-a-logical","errorCode":null,"errorMessage":"'{0}' must be the root element of a tree, but has a logical parent '{1}'.","messagePattern":"'(.+?)' must be the root element of a tree, but has a logical parent '(.+?)'\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs","lineNumber":890,"sourceCode":"        /// <summary>\n        ///     Internal implementation of CreateRootPopup to allow tooltips to\n        ///     override the popup's placement in case the tooltip comes from keyboard focus.\n        /// </summary>\n        /// <param name=\"popup\">The parent popup that the child will be hooked up to.</param>\n        /// <param name=\"child\">The element to be the child of the popup.</param>\n        /// <param name=\"bindTreatMousePlacementAsBottomProperty\">Whether to bind TreatMousePlacementAsBottomProperty to the child's FromKeyboard property</param>\n        internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool bindTreatMousePlacementAsBottomProperty)\n        {\n            ArgumentNullException.ThrowIfNull(popup);\n            ArgumentNullException.ThrowIfNull(child);\n\n            Debug.Assert(!bindTreatMousePlacementAsBottomProperty || child is ToolTip, \"child must be a Tooltip to bind TreatMousePlacementAsBottomProperty\");\n\n            // When we get here, the Child must not have already been visually or logically parented.\n            object currentParent = null;\n            if ((currentParent = LogicalTreeHelper.GetParent(child)) != null)\n            {\n                throw new InvalidOperationException(SR.Format(SR.CreateRootPopup_ChildHasLogicalParent, child, currentParent));\n            }\n\n            if ((currentParent = VisualTreeHelper.GetParent(child)) != null)\n            {\n                throw new InvalidOperationException(SR.Format(SR.CreateRootPopup_ChildHasVisualParent, child, currentParent));\n            }\n\n            // PlacementTarget must be set before hooking up the child so that resource\n            // lookups can work.  The Popup for tooltip and context menu isn't in the tree\n            // so FE relies on GetUIParentCore to return the placement target as the\n            // effective logical parent\n            Binding binding = new Binding(\"PlacementTarget\")\n            {\n                Mode = BindingMode.OneWay,\n                Source = child\n            };\n            popup.SetBinding(PlacementTargetProperty, binding);\n","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Primitives/Popup.cs#L872-L908","documentation":"Popup.CreateRootPopupInternal (used by ContextMenu, ToolTip, etc.) requires the popup's Child to be a root element: before attaching it, the child must have no existing logical parent. WPF throws InvalidOperationException because an element with a logical parent cannot be reparented into the popup's visual/logical tree.","triggerScenarios":"Setting popup.Child (or passing a child to CreateRootPopup) with an element that already has a logical parent, e.g. an element that is still in a Window/Page's logical tree, or reusing a shared resource element across two popups.","commonSituations":"Reusing the same UIElement instance for two popups; moving a control from a window into a popup without calling Detach/RemoveChild first; declaring a resource element and assigning it both in XAML and code.","solutions":["Remove the child from its current logical parent first (e.g. remove it from the containing Panel or set the property holding it to null).","Use a fresh instance for the popup instead of a shared element (e.g. create a new instance from the DataTemplate/Resource).","If intentionally moving the element, disconnect it via LogicalTreeHelper / clear the parent property before assigning Child."],"exampleFix":"// before\nvar panel = (StackPanel)FindResource(\"myPanel\");\npopup.Child = panel; // panel already parented\n// after\npopup.Child = new StackPanel { Children = { new TextBlock { Text = \"hi\" } } }; // fresh instance","handlingStrategy":"validation","validationCode":"if (LogicalTreeHelper.GetParent(child) != null || VisualTreeHelper.GetParent(child) != null)\n    throw new InvalidOperationException(\"Child must be a root element before assigning to Popup.Child\");","typeGuard":"bool CanBePopupChild(UIElement child) =>\n    LogicalTreeHelper.GetParent(child) == null && VisualTreeHelper.GetParent(child) == null;","tryCatchPattern":"try { popup.Child = element; }\ncatch (InvalidOperationException ex) { /* detach element or instantiate a new one */ }","preventionTips":["Never share one UIElement across two popups or between a window and a popup","Instantiate fresh elements from templates/resources","Detach from parent before reparenting"],"tags":["wpf","popup","logical-tree","parent-conflict"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}