{"record":{"id":"44aa65d09d9b15a7","repo":"MaterialDesignInXAML/MaterialDesignInXamlToolkit","slug":"visualancestry-must-contains-at-least-one-visual-c","errorCode":null,"errorMessage":"visualAncestry must contains at least one Visual control inside.","messagePattern":"visualAncestry must contains at least one Visual control inside\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/MaterialDesignThemes.Wpf/ComboBoxPopup.cs","lineNumber":250,"sourceCode":"        {\n            newY = -(defaultVerticalOffsetIndependent + data.PopupSize.Height);\n            direction = PopupDirection.Up;\n        }\n        else\n        {\n            newY = defaultVerticalOffsetIndependent + data.TargetSize.Height;\n            direction = PopupDirection.Down;\n        }\n\n        SetCurrentValue(OpenDirectionProperty, direction);\n        return new[] { new CustomPopupPlacement(new Point(data.OffsetX, newY), PopupPrimaryAxis.Horizontal) };\n\n        PositioningData GetPositioningData(IEnumerable<DependencyObject?> visualAncestry, Size popupSize, Size targetSize)\n        {\n            var locationFromScreen = PlacementTarget.PointToScreen(new Point(0, 0));\n\n            var mainVisual = visualAncestry.OfType<Visual>().LastOrDefault()\n                ?? throw new ArgumentException($\"{nameof(visualAncestry)} must contains at least one {nameof(Visual)} control inside.\");\n            var controlVisual = visualAncestry.OfType<Visual>().FirstOrDefault()\n                ?? throw new ArgumentException($\"{nameof(visualAncestry)} must contains at least one {nameof(Visual)} control inside.\");\n            var screen = Screen.FromPoint(locationFromScreen);\n            var screenWidth = (int)screen.Bounds.Width;\n            var screenHeight = (int)screen.Bounds.Height;\n\n            //Adjust the location to be in terms of the current screen\n            var locationX = (int)(locationFromScreen.X - screen.Bounds.X) % screenWidth;\n            var locationY = (int)(locationFromScreen.Y - screen.Bounds.Y) % screenHeight;\n\n            var upVerticalOffsetIndependent = DpiHelper.TransformToDeviceY(mainVisual, UpVerticalOffset) * ScaleHelper.GetTotalTransformScaleY(controlVisual);\n            var newUpY = upVerticalOffsetIndependent - popupSize.Height + targetSize.Height;\n            var newDownY = DpiHelper.TransformToDeviceY(mainVisual, DownVerticalOffset) * ScaleHelper.GetTotalTransformScaleY(controlVisual);\n            var offsetX = DpiHelper.TransformToDeviceX(mainVisual, RelativeHorizontalOffset) * ScaleHelper.GetTotalTransformScaleX(controlVisual);\n            offsetX = FlowDirection == FlowDirection.LeftToRight\n                ? Round(offsetX)\n                : Math.Truncate(offsetX - targetSize.Width);\n","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/blob/98edec3a0b96ef272c587b14bcd67ef5f928a7ed/src/MaterialDesignThemes.Wpf/ComboBoxPopup.cs#L232-L268","documentation":"Inside `ComboBoxPopup.GetPositioningData` (a local function used during custom popup placement), `mainVisual = visualAncestry.OfType<Visual>().LastOrDefault()` is expected to be the root presentation source. If the `PlacementTarget`'s visual ancestry contains no `Visual`, it throws `ArgumentException`, because DPI/transform calculations need a real visual root.","triggerScenarios":"The combo box popup performs custom placement while `PlacementTarget` is detached from any window/presentation source (no `Visual` ancestor): opening the popup before the control is in a live visual tree, during teardown, or on a disconnected element.","commonSituations":"Opening a `ComboBox` whose popup uses this host before `Loaded`; hosting the combo in a `Popup`/`ContextMenu` not yet shown; element removed from the tree while a placement pass runs; design-time/hosted scenarios without a real visual root.","solutions":["Ensure the `ComboBox`/`PlacementTarget` is loaded into a visible window before opening the dropdown (subscribe to `Loaded`).","Avoid opening the popup during `Unloaded`/`Closed` or while the element is being reparented.","If reproducing in design mode or tests, supply a real presentation source or suppress placement.","Upgrade MaterialDesignThemes — defensive placement handling has improved across versions."],"exampleFix":"// before\ncomboBox.IsDropDownOpen = true; // called before the control is in a live visual tree -> throws\n\n// after\ncomboBox.Loaded += (s, e) => comboBox.IsDropDownOpen = true;","handlingStrategy":"validation","validationCode":"void OpenWhenLoaded(ComboBox cb)\n{\n    if (cb.IsLoaded && AdornerLayer.GetAdornerLayer(cb) is not null)\n        cb.IsDropDownOpen = true;\n    else\n        cb.Loaded += (s, _) => cb.IsDropDownOpen = true;\n}","typeGuard":"static bool HasVisualAncestry(UIElement e)\n    => PresentationSource.FromVisual(e as Visual) is not null;","tryCatchPattern":null,"preventionTips":["Open combo dropdowns only after Loaded.","Don't open popups during Unloaded/teardown.","Keep MaterialDesignThemes up to date for hardened placement logic."],"tags":["wpf","popup","visual-tree","combobox","dpi","lifecycle","material-design"],"backgroundTag":null,"analyzedSha":"98edec3a0b96ef272c587b14bcd67ef5f928a7ed","analyzedAt":"2026-08-13T14:31:19.111Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}