Skip to content

Rating

Rating is a lookless Control owning the authoritative decimal? value plus a transient hover-preview value; it builds Max NaviusRatingItem stars into a PART_ItemsHost panel and drives selection, hover, and roving tabindex centrally, the same root-owns-children shape NaviusRadioGroup uses for its items. Step/clamp/select math is factored into the pure, unit-tested NaviusRatingMath.

xmlns:navius="clr-namespace:Navius.Wpf.Primitives.Controls;assembly=Navius.Wpf.Primitives"
<navius:NaviusRating x:Name="Stars"
Value="{Binding Score, Mode=TwoWay}"
Max="5"
AllowHalf="True" />
Property Type Default From Description
Value decimal? null NaviusRating Controlled value; null = unrated. Kept exact-parity decimal? (not double?) so AllowHalf’s 0.5-step snapping stays exact. Two-way bindable via a Binding.
Max int 5 NaviusRating Number of visual stars, coerced to >= 1. Changing it rebuilds the star items.
AllowHalf bool false NaviusRating Enables half-star pointer zones and 0.5 keyboard steps.
AllowClear bool true NaviusRating Re-selecting the current value, or arrowing/Backspace/Delete below the lowest star, clears to unrated.
ReadOnly bool false NaviusRating Focusable but non-editable; HandleKey, SelectItem, and pointer selection all no-op.
Required bool false NaviusRating Drives ISelectionProvider.IsSelectionRequired on the automation peer.
Invalid bool false NaviusRating Exposed for API parity; no further wiring beyond the dependency property itself.
Label Func<decimal, string>? null NaviusRating Accessible-name factory per star value; falls back to NaviusRating.DefaultLabel (“1 star” singular, “N stars” otherwise).
Index int 1 NaviusRatingItem 1-based position, pushed by the owning NaviusRating’s registration order via SetCurrentValue, not set directly by the consumer.
FillState NaviusRatingFillState Empty NaviusRatingItem Empty / Half / Full, computed and pushed by the owner from the effective (hover-or-committed) value.
IsHighlighted bool false NaviusRatingItem true while under the group’s hover preview.
Method Description
HandleKey(Key) Public, not the more natural internal, so the full keyboard table is directly unit-testable without constructing real KeyEventArgs. Returns whether the key was consumed.
Event Signature Fires when
ValueChanged RoutedPropertyChangedEventHandler<decimal?> Value changes via click, keyboard edit, or programmatic set.
SelectRequested (item) EventHandler<NaviusRatingSelectEventArgs> A star is clicked; bubbles to the owning NaviusRating, which resolves half-vs-whole selection from IsHalf.
HoverChanged (item) EventHandler<NaviusRatingSelectEventArgs> Pointer enters/leaves a star; IsHalf is null on leave, clearing the hover preview.
Key Behavior
ArrowUp, ArrowRight (ArrowLeft under rtl) Increase by Step (0.5 with AllowHalf, else 1), clamped to Max.
ArrowDown, ArrowLeft (ArrowRight under rtl) Decrease by Step; clears to unrated when AllowClear and the result would fall below Step, otherwise floors at Step.
Home Jump to 1.
End Jump to Max.
Backspace / Delete Clear to unrated when AllowClear, otherwise no-op.
Digit 1-9 Jump directly to that value, clamped to Max.
Space / Enter Selects the roving-focused star (FocusIndex(Value, Max)); re-selecting the current value clears it when AllowClear. Fixed by the M6 audit, see Web deltas.

All keyboard handling no-ops when Disabled or ReadOnly; focus moves to the star holding the new value after every edit.

NaviusRatingAutomationPeer (FrameworkElementAutomationPeer + ISelectionProvider) reports AutomationControlType.Group, the same choice NaviusRadioGroupAutomationPeer makes since WPF has no built-in radiogroup-of-buttons peer; GetSelection() resolves the currently focused star. NaviusRatingItemAutomationPeer (+ ISelectionItemProvider) reports AutomationControlType.RadioButton and overrides GetNameCore() to announce the real fractional Value when the item is the checked star, or its own whole Index otherwise, via a single peer override rather than per-star peer subclasses. The unit suite exercises HandleKey for every table entry (including RTL mirroring), the Space/Enter fix below, and the automation peers’ selection/name behavior.

  • Confirmed fixed by the M6 audit: Space/Enter were silently unhandled in NaviusRating.HandleKey, since NaviusRatingItem is a plain Control, not a native button, so nothing wired the contract’s “native button-click semantics” activation. Fixed by adding explicit Space/Enter cases to HandleKey that select the roving-focused star.
  • ChildContent (a custom star glyph slot on the web) is dropped: the star is a single fixed PathGeometry in Themes/Rating.xaml, styleable but not swappable per-instance without editing the template.
  • Name (a hidden bubble input for form submission) and Dir (an explicit reading-direction string) are not present on NaviusRating; the port reads FlowDirection directly (isRtl = FlowDirection == FlowDirection.RightToLeft) rather than exposing a Dir property. This is a discrepancy against the parity doc’s web-contract parameter table, which lists both: the sibling NaviusRadioGroup/NaviusToggleGroup in this same batch do expose a Dir string alongside a FlowDirection fallback, but NaviusRating’s shipped code has neither a Name nor a Dir dependency property. Found during manifest extraction; not called out in the parity doc’s own “WPF implementation notes”.
  • Hover preview uses OnMouseEnter/OnMouseLeave (not PreviewMouseMove) plus a bubbling HoverChanged routed event, the same bubble-to-owner shape NaviusRadioGroup uses for OnItemChecked.
  • Residual noted then resolved during the M6 RTL wave: the half-fill visual’s Clip was previously flagged as not RTL-mirrored; pixel-rendered verification showed WPF’s FlowDirection mirroring already reflects it correctly, so no residual remains for the fill clip. Keyboard arrow mirroring under rtl was already correct throughout.
  • Attributes splat and the hidden <input> form mirror are dropped; no WPF form-submission model.

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

Rating Gallery page in the light theme

Rating Gallery page in the dark theme

Rating Gallery page in the high contrast theme