Skip to content

Collapsible

Collapsible is a lookless ContentControl root (NaviusCollapsible) that owns a single Open boolean and discovers its NaviusCollapsibleTrigger/NaviusCollapsiblePanel descendants through the logical tree, the same “root owns state, discovers descendants” shape as NaviusAccordion and NaviusRadioGroup. WPF’s native Expander was rejected as a base because it fuses header and content into one control and cannot preserve the contract’s separately addressable Trigger/Panel parts.

xmlns:navius="clr-namespace:Navius.Wpf.Primitives.Controls;assembly=Navius.Wpf.Primitives"
xmlns:collapsible="clr-namespace:Navius.Wpf.Primitives.Controls.Collapsible;assembly=Navius.Wpf.Primitives"
<collapsible:NaviusCollapsible x:Name="Details">
<StackPanel>
<collapsible:NaviusCollapsibleTrigger Content="Show details" />
<collapsible:NaviusCollapsiblePanel>
<TextBlock Text="Hidden content revealed when open." />
</collapsible:NaviusCollapsiblePanel>
</StackPanel>
</collapsible:NaviusCollapsible>
Property Type Default From Description
Open bool false NaviusCollapsible Open/closed state. Bindable via standard WPF binding; OpenChanged fires on every change.
IsPanelOpen bool false NaviusCollapsibleTrigger Mirrors Open; set by the ancestor NaviusCollapsible, not by the trigger itself.
IsOpen bool false NaviusCollapsiblePanel Mirrors Open; set by the ancestor NaviusCollapsible.
KeepMounted bool false NaviusCollapsiblePanel Keeps Content cached and only toggles Visibility instead of clearing Content on close.
Content object - ContentControl Body content on the root, Trigger, and Panel.
Event Signature Fires when
OpenChanged RoutedEventHandler Open changes (a trigger click or a direct Open write).
Key Behavior
Space / Enter Toggles the panel; native Button.Click behavior on the focused NaviusCollapsibleTrigger, no custom key handler.

NaviusCollapsibleAutomationPeer reports AutomationControlType.Group on the root and carries no expand/collapse state of its own, matching the contract’s asymmetry where the root exposes no data-* state attribute at all. NaviusCollapsibleTriggerAutomationPeer reports AutomationControlType.Button and implements both IInvokeProvider (native Button behavior) and IExpandCollapseProvider (ExpandCollapseState from IsPanelOpen), the same dual-pattern shape WPF’s own ExpanderAutomationPeer uses. CollapsibleTests.cs exercises the root-owns-state shape, the dual trigger patterns, and the IsEnabled cascading described below.

  • HiddenUntilFound (the web’s browser in-page-find integration) is dropped entirely; there is no WPF “find in page” affordance to hook a reveal callback into.
  • WPF’s IsEnabled does not automatically cascade through a ContentControl’s logical Content; SyncDescendants explicitly pushes it onto the Trigger, matching “Disabled blocks toggling.”
  • The enter/exit height transition is a plain DoubleAnimation via a shared PanelHeightAnimator helper (also used by NaviusAccordionPanel), not the web’s JS-measured natural-size CSS variables or two-phase “starting-style” mount frame; Height animates from a hard 0 instead.
  • Logical open/closed state (Open, IsPanelOpen, IsOpen, and the peer’s ExpandCollapseState) flips synchronously and independently of the animation clock, so it stays correct in a headless test host where nothing pumps the animation to completion; only the cosmetic Height/Visibility transition is asynchronous.
  • KeepMounted=false (default) additionally caches and clears Content once the close animation’s Completed callback fires, approximating DOM removal; the web’s KeepMounted only toggles visibility/hidden state, since Blazor content isn’t cached/cleared the same way.

The Collapsible Gallery page rendered at the pinned commit, in each theme.

Collapsible Gallery page in the light theme

Collapsible Gallery page in the dark theme

Collapsible Gallery page in the high contrast theme