Skip to content

TimeInput

TimeInput is NaviusDateInput’s time-editing sibling: the same shared SegmentMath/ DateTimeSegment engine and NaviusFieldSegment cell type (Controls/DateInput/NaviusFieldSegment.cs), but its own independent root building an hour/minute/ second/day-period layout (12h or 24h, per culture or an explicit HourCycle) instead of year/ month/day. The two roots stay independent rather than sharing a base class, since their layout-building and Compose() targets (DateOnly? vs TimeOnly?) differ enough that a shared base would mostly be pass-through plumbing.

xmlns:timeInput="clr-namespace:Navius.Wpf.Primitives.Controls.TimeInput;assembly=Navius.Wpf.Primitives"
<timeInput:NaviusTimeInput Value="{Binding StartTime, Mode=TwoWay}"
Granularity="minute"
MinuteStep="5" />
Property Type Default From Description
Value TimeOnly? null NaviusTimeInput Two-way bindable by default.
Granularity string "minute" NaviusTimeInput "hour", "minute", or "second"; rebuilds the segment layout at runtime.
HourCycle int? null NaviusTimeInput 12 or 24; null defaults to the culture’s ShortTimePattern sniff ('H' present => 24), via DateTimeFormatInfo identically to .NET’s own culture data.
MinuteStep int 1 NaviusTimeInput Arrow step for the minute segment; rebuilds the layout when changed.
SecondStep int 1 NaviusTimeInput Arrow step for the second segment.
MinValue TimeOnly? null NaviusTimeInput Drives IsOutOfRange/IsInvalidState; never clamps.
MaxValue TimeOnly? null NaviusTimeInput Same, upper bound.
PlaceholderValue TimeOnly? null (→ DateTime.Now) NaviusTimeInput Basis an empty segment jumps to on the first Arrow key.
ReadOnly bool false NaviusTimeInput Blocks every segment key.
Required bool false NaviusTimeInput Drives IsInvalidState’s ValueMissing signal: Required && Value is null, the same contract NaviusDateInput uses.
Invalid bool false NaviusTimeInput ORed into IsInvalidState alongside IsOutOfRange and the Required-driven ValueMissing signal.
ForceLeadingZeros bool false NaviusTimeInput
Culture CultureInfo? null (→ CultureInfo.CurrentCulture) NaviusTimeInput
Name string? null NaviusTimeInput Marker-only, no native-form mirror.
IsFilled bool false NaviusTimeInput Read-only.
IsOutOfRange bool false NaviusTimeInput Read-only.
IsInvalidState bool false NaviusTimeInput Read-only. Invalid || IsOutOfRange || (Required && Value is null).
EffectiveHourCycle int - NaviusTimeInput Read-only CLR property (not a DP): the resolved 12/24 in effect right now.
IsEnabled - - Control Disabled is not a separate DP: maps onto the inherited Control.IsEnabled.
FlowDirection - - Control (FrameworkElement) Dir is not a separate DP: native FlowDirection drives ArrowLeft/ArrowRight mirroring.
Method Description
FocusFirstSegment() Focuses the first editable segment cell.
Event Signature Fires when
ValueChanged RoutedPropertyChangedEventHandler<TimeOnly?> When the composed value changes on a committing keystroke.

Numeric segments (hour, minute, second):

Key Behavior
ArrowUp +ArrowStep (MinuteStep/SecondStep for those segments), wraps at [Min, Max]; an empty segment reveals the placeholder basis.
ArrowDown -ArrowStep, same rule.
PageUp / PageDown Larger step, same wrap rule.
Home / End Jump to Min / Max.
Backspace / Delete Clear to unfilled.
ArrowLeft / ArrowRight Move focus to the previous/next segment (flipped under FlowDirection.RightToLeft).
Digit 0-9 Appends to the type buffer; auto-advances on an early bound-exceeded candidate or on reaching the max digit count.

Day-period segment (AM/PM):

Key Behavior
ArrowUp / ArrowDown Toggle AM/PM (modeled as a 0/1 range); an empty segment reveals AM first.
A / P Set AM / PM directly.
Backspace / Delete Clear to unfilled.
ArrowLeft / ArrowRight Move focus, same as numeric segments.

Segment-to-segment ArrowLeft/Right focus travel is confirmed against a real hosted window by the M6-audit-added TimeInputTests.SegmentArrowKeys_MoveFocusBetweenSegments.

NaviusTimeInputAutomationPeer reports AutomationControlType.Group plus a read-only IValueProvider surfacing the composed value as HH:mm:ss. Each segment shares NaviusFieldSegment’s own peer (Spinner + IRangeValueProvider), including the day-period segment, modeled as a 0/1 range over the same peer type rather than a second pattern. Verified by TimeInputTests.cs: 8 [Fact] tests for BuildTimeLayout/TimeSegmentComposer, 9 [StaFact] tests for the control (both hour cycles, digit typing, AM/PM letter-key toggling, ReadOnly lockout, MinuteStep-driven increment) and the automation peer’s ValuePattern, the M6-audit-added hosted-focus regression for ArrowLeft/Right segment navigation, and three [StaFact] tests locking Required’s ValueMissing contract (empty required value, non-required empty value, composed required value).

  • Same deltas as NaviusDateInput: no NaviusBubbleInput, no ambient NaviusField (FocusFirstSegment() stands in for Field.FocusControl), Dir is native FlowDirection, placeholder tokens replace the literal "Empty" aria-valuetext.
  • The day-period (AM/PM) segment is modeled over the same IRangeValueProvider as numeric segments (Minimum=0/Maximum=1) rather than a second peer/pattern type, since ArrowUp/Down already treat it as a 2-state range.
  • Segment row RTL fix (ADR-0006): Themes/TimeInput.xaml’s PART_Segments panel is pinned to FlowDirection="LeftToRight", the same fix applied to DateInput.xaml, so the hour/minute/ second/day-period row never mirrors under an ambient RTL FlowDirection while arrow-key focus travel still honors it. Locked in by TimeInputTests.cs’s PartSegments_FlowDirectionPinnedToLeftToRight_* and PartSegments_ChildOrder_UnaffectedByFlowDirection.
  • Required drives IsInvalidState’s ValueMissing signal (Required && Value is null), matching the fix already applied to the sibling NaviusDateInput in that family’s own M6 audit; a parity-vs-code discrepancy found during the original extraction (Required was declared but not read anywhere in UpdateComputedState) has since been closed.

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

TimeInput Gallery page in the light theme

TimeInput Gallery page in the dark theme

TimeInput Gallery page in the high contrast theme