Skip to content

Button

Button derives directly from the native System.Windows.Controls.Button, inheriting its Click routed event and keyboard activation. It adds a soft-disabled mode (Disabled combined with FocusableWhenDisabled) that keeps the control natively focusable and tabbable while suppressing activation, the WPF analog of the web contract’s aria-disabled="true"-while-focusable mode.

xmlns:navius="clr-namespace:Navius.Wpf.Primitives.Controls;assembly=Navius.Wpf.Primitives"
<StackPanel>
<navius:NaviusButton Content="Save" Click="OnSave" />
<!-- soft-disabled: stays focusable/tabbable, activation is suppressed -->
<navius:NaviusButton Content="Save"
Disabled="True"
FocusableWhenDisabled="True"
Click="OnSave" />
</StackPanel>
Property Type Default From Description
Disabled bool false NaviusButton Logical disabled state. Combined with FocusableWhenDisabled to choose native IsEnabled=false (hard-disabled) versus soft-disabled.
FocusableWhenDisabled bool false NaviusButton When true and Disabled, keeps the button natively enabled and focusable/tabbable but suppresses activation, instead of setting IsEnabled=false.
IsSoftDisabled bool false NaviusButton Read-only. true when Disabled && FocusableWhenDisabled: natively enabled/focusable, activation suppressed, AutomationPeer reports disabled.
Content object - ContentControl Button content, inherited via Button.
Event Signature Fires when
Click RoutedEventHandler The button is activated (mouse, keyboard Space/Enter, or UIA Invoke) and is not soft-disabled; OnClick no-ops when IsSoftDisabled is true, so no Click event fires.
Key Behavior
Space / Enter Native ButtonBase keyboard activation, funneled through OnClick. No-ops when IsSoftDisabled is true.

NaviusButtonAutomationPeer (a ButtonAutomationPeer) overrides IsEnabledCore() to report disabled to UIA whenever IsSoftDisabled is true, while the control itself stays natively enabled and focusable. This makes the stock IInvokeProvider.Invoke() throw ElementNotEnabledException on a soft-disabled button rather than silently activating it, the correct UIA behavior for the aria-disabled-while-focusable case. GetAutomationControlTypeCore() is not overridden and is inherited from ButtonAutomationPeer (AutomationControlType.Button). The unit suite (ButtonTests, 11 facts) covers default state, hard- versus soft-disabled IsEnabled/IsSoftDisabled, OnClick suppression (invoked via reflection on the protected ButtonBase.OnClick, the actual mouse/keyboard/UIA funnel), and the peer’s IsEnabled()/ IInvokeProvider.Invoke() behavior in both states.

  • Type (the web’s type="submit"|"button"|"reset" HTML attribute) is not ported: WPF has no form-submission concept for it to map onto. Native Button exposes IsDefault/IsCancel as a partial, non-string-typed analog, but no direct mapping was made; this is an open design question, not a confirmed gap.
  • NativeButton (a Base UI asChild-parity flag that already has no rendering effect on the web side) is dropped entirely: WPF’s ContentPresenter/ControlTemplate model already allows arbitrary templated content without an element-type-swap mechanism.
  • The web’s aria-disabled="true"-while-focusable mode is reproduced via a custom AutomationPeer.IsEnabledCore() override rather than an aria-disabled attribute, since UIA has no first-class “disabled but enabled” concept; this is a platform-idiomatic reinterpretation, not a literal attribute translation.
  • M6 audit note: prior to the 2026-07-09 audit this family shipped as a bare Button subclass with none of the above (no Disabled, no FocusableWhenDisabled, no test file), a confirmed disparity that is now fixed by the properties and peer override described above.