lepoco/wpfui · error · InvalidOperationException

dpiScale is not initialized.

Error message

dpiScale is not initialized.

What it means

TitleBar caches the screen DPI in the static field dpiScale via 'dpiScale ??= VisualTreeHelper.GetDpi(this)' inside the window's ContentRendered handler. The right-click handler TitleBar_MouseRightButtonUp reads dpiScale to convert pointer coordinates before opening the system menu. If a right-click arrives before ContentRendered has run (dpiScale still null), the handler throws InvalidOperationException.

Source

Thrown at src/Wpf.Ui/Controls/TitleBar/TitleBar.cs:762

                return htResult;
            case PInvoke.WM_NCHITTEST when this.IsMouseOverElement(lParam) && !isMouseOverHeaderContent:
                handled = true;
                return (IntPtr)PInvoke.HTCAPTION;
            default:
                return IntPtr.Zero;
        }
    }

    /// <summary>
    /// Show 'SystemMenu' on mouse right button up.
    /// </summary>
    private void TitleBar_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
    {
        Point point = PointToScreen(e.GetPosition(this));

        if (dpiScale is null)
        {
            throw new InvalidOperationException("dpiScale is not initialized.");
        }

        SystemCommands.ShowSystemMenu(
            _parentWindow as Window,
            new Point(point.X / dpiScale.Value.DpiScaleX, point.Y / dpiScale.Value.DpiScaleY)
        );
    }

    private T GetTemplateChild<T>(string name)
        where T : DependencyObject
    {
        DependencyObject element = GetTemplateChild(name);

        if (element is not T tElement)
        {
            throw new InvalidOperationException(
                $"Template part '{name}' is not found or is not of type {typeof(T)}"
            );

View on GitHub (pinned to ffebacd610)

Solutions

  1. Ensure the owning window has rendered (ContentRendered fired) before driving title-bar input in tests.
  2. In production this is a transient race; suppress right-click handling until the window is fully loaded, or initialise dpiScale earlier.
  3. If subclassing TitleBar, set dpiScale via VisualTreeHelper.GetDpi in OnLoaded as an additional init point.

Example fix

// guard before invoking system menu in a subclass
protected override void OnMouseRightButtonUp(MouseButtonEventArgs e)
{
    if (VisualTreeHelper.GetDpi(this) is { } scale)
    {
        base.OnMouseRightButtonUp(e);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

var scale = VisualTreeHelper.GetDpi(titleBar);
if (scale is { }) { /* safe to compute screen coords */ } else { /* window not rendered yet */ }

Type guard

static bool IsDpiKnown(FrameworkElement e) => VisualTreeHelper.GetDpi(e).DpiScaleX > 0;

Try / catch

try { /* trigger system menu */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("dpiScale"))
{
    _logger.LogWarning(ex, "Right-click before window rendered; ignoring.");
}

Prevention

When it happens

Trigger: User right-clicks the title bar during the brief window between the control being interactive and the owning window firing ContentRendered - e.g. on a very slow first render, or programmatically raising MouseRightButtonUp in tests before the window has rendered.

Common situations: Automated UI tests that drive mouse input before showing the window fully; very heavy first-frame rendering that delays ContentRendered; custom windows that suppress ContentRendered.

Related errors


AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13). Data as JSON: /api/errors/1c94ecd079a81a22. Report an issue: GitHub.