lepoco/wpfui · error · ArgumentOutOfRangeException
Unsupported button type: {buttonType}.
Error message
Unsupported button type: {buttonType}. What it means
TitleBarButton.OnButtonTypeChanged maps each TitleBarButtonType enum value to a Windows hit-test code. The switch is exhaustive over the known enum members, so the default branch only fires when the dependency property is set to a numeric value that does not correspond to any defined TitleBarButtonType - which is possible because dependency properties accept raw values via SetValue and the code casts e.NewValue directly. This is essentially an unreachable-in-normal-use defensive guard against an invalid/corrupted enum value.
Source
Thrown at src/Wpf.Ui/Controls/TitleBar/TitleBarButton.cs:228
return;
}
titleBarButton.OnButtonTypeChanged(e);
}
protected void OnButtonTypeChanged(DependencyPropertyChangedEventArgs e)
{
var buttonType = (TitleBarButtonType)e.NewValue;
_returnValue = buttonType switch
{
TitleBarButtonType.Unknown => PInvoke.HTNOWHERE,
TitleBarButtonType.Help => PInvoke.HTHELP,
TitleBarButtonType.Minimize => PInvoke.HTMINBUTTON,
TitleBarButtonType.Close => PInvoke.HTCLOSE,
TitleBarButtonType.Restore => PInvoke.HTMAXBUTTON,
TitleBarButtonType.Maximize => PInvoke.HTMAXBUTTON,
_ => throw new ArgumentOutOfRangeException(
"e.NewValue",
buttonType,
$"Unsupported button type: {buttonType}."
),
};
}
// TODO: Incorrectly calculates mouse position for high DPI displays.
// PresentationSource presentationSource = null;
// protected bool IsMouseOverElement(nint lParam)
// {
// System.Drawing.Point winPoint;
// bool gotCursorPos = User32.GetCursorPos(out winPoint);
// if (!gotCursorPos)
// {
// int fallbackX = unchecked((short)((long)lParam & 0xFFFF));
// int fallbackY = unchecked((short)(((long)lParam >> 16) & 0xFFFF));View on GitHub (pinned to ffebacd610)
Solutions
- Only assign defined TitleBarButtonType values (Unknown, Help, Minimize, Close, Restore, Maximize).
- Validate bound values before assignment; clamp unknown values to Unknown.
- Update WPF UI to a version whose switch covers the enum value you are binding.
Example fix
// before button.SetValue(TitleBarButton.ButtonTypeProperty, (TitleBarButtonType)42); // after button.ButtonType = TitleBarButtonType.Unknown;
Defensive patterns
Strategy: validation
Validate before calling
if (!Enum.IsDefined(typeof(TitleBarButtonType), value))
{
throw new ArgumentOutOfRangeException(nameof(value), "Invalid TitleBarButtonType.");
} Type guard
static bool IsDefinedButtonType(TitleBarButtonType v) => Enum.IsDefined(v);
Try / catch
try { button.ButtonType = (TitleBarButtonType)raw; }
catch (ArgumentOutOfRangeException ex) when (ex.Message.Contains("Unsupported button type"))
{
_logger.LogError(ex, "Invalid TitleBarButtonType {Raw}", raw);
button.ButtonType = TitleBarButtonType.Unknown;
} Prevention
- Only assign defined TitleBarButtonType enum members.
- Validate external/deserialised values with Enum.IsDefined before assignment.
- Keep the library version current so new enum members are covered.
When it happens
Trigger: Calling button.SetValue(TitleBarButton.ButtonTypeProperty, (TitleBarButtonType)999) or otherwise assigning a numeric value outside the enum's defined range; future enum members added without updating the switch; XAML binding that produces an out-of-range value.
Common situations: Programmatic misuse via SetValue with a cast; deserialised/bound values that fall outside the enum; version skew where a newer enum value is bound against an older library build.
Related errors
- Window is null
- dpiScale is not initialized.
- Template part '{name}' is not found or is not of type {typeo
- The argument {nameof(index)} must be >= 0 and < the number o
- {nameof(value)} is not type: {typeof(TEnum)}
AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13).
Data as JSON: /api/errors/a947cf10e0ab3d05.
Report an issue: GitHub.