Skip to content

Fieldset

Fieldset is a plain lookless ContentControl grouping related fields under a legend. Disabled drives IsEnabled directly rather than reimplementing the web’s native <fieldset disabled> propagation, since WPF’s IsEnabled already inherits down the visual/logical tree the same way. It deliberately does not derive from GroupBox, whose ControlTemplate pins the header inline with the border: NaviusFieldsetLegend is instead an ordinary child placeable anywhere, matching the web contract’s legend being “a free-floating div, not a native legend, for positioning freedom”.

xmlns:fieldset="clr-namespace:Navius.Wpf.Primitives.Controls.Fieldset;assembly=Navius.Wpf.Primitives"
<fieldset:NaviusFieldset Disabled="{Binding IsSubmitting}">
<StackPanel>
<fieldset:NaviusFieldsetLegend Content="Shipping address" />
<!-- NaviusField controls placed here inherit Disabled via IsEnabled -->
</StackPanel>
</fieldset:NaviusFieldset>
Property Type Default From Description
Disabled bool false NaviusFieldset Drives IsEnabled directly; an outer disabled scope still wins via WPF’s own IsEnabled AND-coercion. Cascades into every descendant NaviusField’s effective disabled state (Disabled || Fieldset.Disabled) for free via tree inheritance, no reimplemented propagation.
Content object - ContentControl Fieldset body (legend + fields).
Content object - ContentControl (NaviusFieldsetLegend) Legend content; carries no properties of its own, its disabled visual comes from the same IsEnabled inheritance.

NaviusFieldsetAutomationPeer (a FrameworkElementAutomationPeer) reports AutomationControlType.Group. NaviusFieldset actively wires AutomationProperties.SetLabeledBy(this, legend) to the first NaviusFieldsetLegend descendant on OnContentChanged (WireLegend), giving the group a real accessible-name association: the web contract’s own code comment claims an equivalent association exists there, but no id/ aria-labelledby wiring backs it, so the WPF port does not copy that gap. Disabled visuals (Opacity 0.5 on the fieldset, muted foreground on the legend) come from Themes/Fieldset.xaml, since IsEnabled alone gives no default disabled look and the web leaves that styling entirely to consumer CSS. The unit suite (FieldTests.cs) covers the IsEnabled disabled-cascade into NaviusField.

  • GroupBox is deliberately not used: its ControlTemplate pins the header into the border, breaking the web contract’s free-floating legend positioning; the root is a plain lookless ContentControl instead.
  • FieldsetContext (the web’s single-property cascaded object) needs no WPF equivalent at all: IsEnabled inheritance already is the context.
  • The legend-to-fieldset accessible-name association is real in the WPF port (AutomationProperties.LabeledBy), where the web contract’s own code comment claiming the same was found unbacked by any actual id/aria-labelledby wiring.
  • Disabled visuals (Opacity 0.5 plus muted legend foreground) are a WPF-only addition: the web leaves fieldset disabled styling entirely to consumer CSS.
  • Known residual (M6 audit): the LabeledBy wiring and the Group automation peer have no dedicated unit-test coverage (only the disabled cascade is tested); correct by inspection but not verified with a UIA client or screen reader.
  • Known residual (M6 audit): WireLegend only runs on OnContentChanged, so a legend added or swapped after initial content assignment (rare in XAML, possible in code) would not re-wire LabeledBy; not exercised by any current usage.