Skip to content

TimePicker

TimePicker collapses the web contract’s five-part shell (Root/Input/Trigger/Content/Column) onto one templated Control: PART_Input is a real embedded NaviusTimeInput bound two-way to Value/Granularity/HourCycle/MinuteStep/SecondStep so typed edits and popup column selections share one value with no extra glue, PART_Trigger is a ToggleButton opening a NaviusAnchoredPopup, and each unit column (PART_HourColumn/PART_MinuteColumn/ PART_SecondColumn/PART_DayPeriodColumn) is a themed native ListBox populated from the pure TimePickerOptionBuilder rather than a hand-rolled option/column pair.

xmlns:timePicker="clr-namespace:Navius.Wpf.Primitives.Controls.TimePicker;assembly=Navius.Wpf.Primitives"
<timePicker:NaviusTimePicker Value="{Binding AppointmentTime, Mode=TwoWay}"
Granularity="minute"
MinuteStep="15" />
Property Type Default From Description
Value TimeOnly? null NaviusTimePicker Two-way bindable by default.
IsOpen bool false NaviusTimePicker Two-way bindable.
Granularity string "minute" NaviusTimePicker "hour"/"minute"/"second"; controls which columns render.
HourCycle int? null NaviusTimePicker 12 or 24; null defaults to the culture’s short-time pattern sniff.
MinuteStep int 1 NaviusTimePicker Clamped to >= 1 when rebuilding the minute column’s options.
SecondStep int 1 NaviusTimePicker Clamped to >= 1.
Culture CultureInfo? null (→ CultureInfo.CurrentCulture) NaviusTimePicker
EffectiveHourCycle int - NaviusTimePicker Read-only CLR property: the resolved 12/24 in effect right now.
IsEnabled - - Control No Disabled DP: native IsEnabled is used directly, matching the NaviusSelectBase/NaviusNumberField precedent.
Event Signature Fires when
ValueChanged RoutedPropertyChangedEventHandler<TimeOnly?> Whenever the composed value changes, from either typed input or column selection.
OpenChanged RoutedPropertyChangedEventHandler<bool> When IsOpen changes.
Key Behavior
Enter / Space / ArrowDown (embedded input or trigger, popup closed) Delegated to the embedded NaviusTimeInput’s own segment keyboard model, or opens the popup via the trigger.
ArrowUp / ArrowDown (a column, popup open) Native ListBox selection navigation, one item at a time.
Home / End (a column) Native ListBox jump to first/last item.
Digit 0-9 (a column) Native ListBox TextSearch typeahead, kept as-is rather than the web’s custom buffer-reset Typeahead() logic; native reset timing differs slightly but functionally satisfies “type digits, jump to the matching option”.
Enter / Space (a column item) Native ListBoxItem selection, which commits that unit via OnColumnSelectionChanged.
Escape (popup open) Closes the popup via the inherited overlay/session dismissal, not a custom key handler in this class.

NaviusTimePickerAutomationPeer reports AutomationControlType.ComboBox (the same shape as NaviusSelectAutomationPeer, since both controls are trigger+popup+value shells) plus a read-only IValueProvider surfacing the composed HH:mm:ss text and IExpandCollapseProvider over IsOpen. Each column is a native ListBox, so its ListBoxAutomationPeer/ListBoxItemAutomationPeer already report SelectionPattern (the UIA analog of role="listbox"/role="option") with no custom peer needed; roving tabindex and Up/Down/Home/End navigation come from ListBox natively. Verified by TimePickerTests.cs: 5 [Fact] tests for TimePickerOptionBuilder, 10 [StaFact] tests for the control (column visibility per granularity/hour-cycle, value-to-column sync both directions, MinuteStep-driven option rebuilding, the embedded PART_Input wiring) and the automation peer’s ComboBox type, ValuePattern, and ExpandCollapse round-trip.

  • No separate NaviusTimePickerColumn/NaviusTimePickerOption CLR types: each column is a themed native ListBox populated from TimePickerOptionBuilder; ListBoxItem stands in for NaviusTimePickerOption, with roving tabindex and role="listbox"/"option"-equivalent automation coming from ListBox natively instead of being reimplemented.
  • Native ListBox TextSearch typeahead is kept rather than reimplementing the web’s custom per-keystroke buffer-reset Typeahead() logic; the reset timing differs slightly (a short pause vs. per-keystroke) but functionally satisfies the same “type digits, jump to option” behavior.
  • The web’s Highlighted-vs-Selected two-state distinction (roving-active vs. actually-chosen unit) collapses to one state: native ListBox/ListBoxItem selection already conflates roving-focus and the chosen value together on Arrow keys, matching the platform’s own interaction model rather than fighting it.
  • No Disabled DP: native IsEnabled is used directly, matching the NaviusSelectBase/ NaviusNumberField precedent in this repo rather than the web contract’s separate Disabled bool parameter.
  • ValuePattern on the root is a WPF-only addition (not asserted by the web contract, which relies on the DOM subtree instead): required because a template-only control otherwise exposes nothing over UIA (the M3 gate finding referenced by this family’s own parity doc).
  • Known residual: column keyboard behavior (Up/Down/Home/End/typeahead, Enter/Space activation) is entirely native ListBox behavior with no custom handler, so it was not independently re-tested by the M6 audit beyond confirming it is reachable and functionally correct; native TextSearch’s buffer-reset timing specifically was not verified bit-for-bit against the web’s custom buffer.

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

TimePicker Gallery page in the light theme

TimePicker Gallery page in the dark theme

TimePicker Gallery page in the high contrast theme