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
- Ensure the owning window has rendered (ContentRendered fired) before driving title-bar input in tests.
- In production this is a transient race; suppress right-click handling until the window is fully loaded, or initialise dpiScale earlier.
- 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
- In tests, fully render the window before simulating title-bar right-clicks.
- Initialise DPI as early as OnLoaded in a TitleBar subclass.
- Avoid programmatic input during the pre-ContentRendered window.
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
- Window is null
- Template part '{name}' is not found or is not of type {typeo
- Unsupported button type: {buttonType}.
- Unable to find the base directory of the application.
- Unable to determine the window source.
AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13).
Data as JSON: /api/errors/1c94ecd079a81a22.
Report an issue: GitHub.