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

  1. Only assign defined TitleBarButtonType values (Unknown, Help, Minimize, Close, Restore, Maximize).
  2. Validate bound values before assignment; clamp unknown values to Unknown.
  3. 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

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


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