MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · ArgumentException

visualAncestry must contains at least one Visual control ins

Error message

visualAncestry must contains at least one Visual control inside.

What it means

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.

Source

Thrown at src/MaterialDesignThemes.Wpf/ComboBoxPopup.cs:250

        {
            newY = -(defaultVerticalOffsetIndependent + data.PopupSize.Height);
            direction = PopupDirection.Up;
        }
        else
        {
            newY = defaultVerticalOffsetIndependent + data.TargetSize.Height;
            direction = PopupDirection.Down;
        }

        SetCurrentValue(OpenDirectionProperty, direction);
        return new[] { new CustomPopupPlacement(new Point(data.OffsetX, newY), PopupPrimaryAxis.Horizontal) };

        PositioningData GetPositioningData(IEnumerable<DependencyObject?> visualAncestry, Size popupSize, Size targetSize)
        {
            var locationFromScreen = PlacementTarget.PointToScreen(new Point(0, 0));

            var mainVisual = visualAncestry.OfType<Visual>().LastOrDefault()
                ?? throw new ArgumentException($"{nameof(visualAncestry)} must contains at least one {nameof(Visual)} control inside.");
            var controlVisual = visualAncestry.OfType<Visual>().FirstOrDefault()
                ?? throw new ArgumentException($"{nameof(visualAncestry)} must contains at least one {nameof(Visual)} control inside.");
            var screen = Screen.FromPoint(locationFromScreen);
            var screenWidth = (int)screen.Bounds.Width;
            var screenHeight = (int)screen.Bounds.Height;

            //Adjust the location to be in terms of the current screen
            var locationX = (int)(locationFromScreen.X - screen.Bounds.X) % screenWidth;
            var locationY = (int)(locationFromScreen.Y - screen.Bounds.Y) % screenHeight;

            var upVerticalOffsetIndependent = DpiHelper.TransformToDeviceY(mainVisual, UpVerticalOffset) * ScaleHelper.GetTotalTransformScaleY(controlVisual);
            var newUpY = upVerticalOffsetIndependent - popupSize.Height + targetSize.Height;
            var newDownY = DpiHelper.TransformToDeviceY(mainVisual, DownVerticalOffset) * ScaleHelper.GetTotalTransformScaleY(controlVisual);
            var offsetX = DpiHelper.TransformToDeviceX(mainVisual, RelativeHorizontalOffset) * ScaleHelper.GetTotalTransformScaleX(controlVisual);
            offsetX = FlowDirection == FlowDirection.LeftToRight
                ? Round(offsetX)
                : Math.Truncate(offsetX - targetSize.Width);

View on GitHub (pinned to 98edec3a0b)

Solutions

  1. Ensure the `ComboBox`/`PlacementTarget` is loaded into a visible window before opening the dropdown (subscribe to `Loaded`).
  2. Avoid opening the popup during `Unloaded`/`Closed` or while the element is being reparented.
  3. If reproducing in design mode or tests, supply a real presentation source or suppress placement.
  4. Upgrade MaterialDesignThemes — defensive placement handling has improved across versions.

Example fix

// before
comboBox.IsDropDownOpen = true; // called before the control is in a live visual tree -> throws

// after
comboBox.Loaded += (s, e) => comboBox.IsDropDownOpen = true;
Defensive patterns

Strategy: validation

Validate before calling

void OpenWhenLoaded(ComboBox cb)
{
    if (cb.IsLoaded && AdornerLayer.GetAdornerLayer(cb) is not null)
        cb.IsDropDownOpen = true;
    else
        cb.Loaded += (s, _) => cb.IsDropDownOpen = true;
}

Type guard

static bool HasVisualAncestry(UIElement e)
    => PresentationSource.FromVisual(e as Visual) is not null;

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13). Data as JSON: /api/errors/44aa65d09d9b15a7. Report an issue: GitHub.