Draft. This spec runs the same three-checks-per-control audit as
spec 039 against the Microsoft.UI.Reactor (Reactor)-original
controls under src/Reactor/Controls/**. Spec 039 deliberately scoped
these out (see 039 §13) and scheduled this follow-up; spec 039 Phase 7.1
created this draft. Outline only — no answers yet. A companion task list
(docs/specs/tasks/040-specialized-control-scrub-implementation.md) will
be created once the audit below is filled in; it does not yet exist.
For every Reactor-original specialized control surface, answer the same three questions as spec 039:
- Event parity. Every callback property (constructor positional /
init-only
Action<T>?) should also be reachable via a fluent extension. - Property coverage. Commonly-used properties of the underlying
conceptual control should be first-class on the Reactor element (init
property or fluent extension), so the default scenario never requires
.Set(c => c.Foo = bar). - Naming alignment. Property / factory / element-record names should
be internally consistent (no equivalent WinUI control exists, so the
bar is self-consistency rather than WinUI parity). Where a folder /
type / factory disagree (e.g.
MaskedTextBoxfolder vsMaskedTextFieldtype — see 039 §3.1 / §16.3), call it out.
Sources surveyed:
src/Reactor/Controls/AutoSuggest/**—AutoSuggestElement<T>.src/Reactor/Controls/DataGrid/**—DataGridElement<T>and related template-context records (CellContext<T>,RowContext<T>,HeaderContext,FieldDescriptor).src/Reactor/Controls/MaskedTextBox/**—MaskedTextFieldElement.src/Reactor/Controls/PropertyGrid/**—PropertyGridElement.src/Reactor/Controls/Virtualization/**—VirtualListElement.
Per-control audit columns mirror spec 039 §0:
| Field | Meaning |
|---|---|
| Factory | Public DSL entry point in Factories |
| Element | Backing record |
| Conceptual peer | Closest WinForms / WinUI / web equivalent (or "(custom)") |
| Events on element | All Action/Action<T> callbacks |
| Events with fluent | Which of those events also have a fluent extension |
| Missing common properties | Properties of the conceptual peer (or expected by callers) that are not surfaced as init property or fluent |
| Naming notes | Internal-consistency observations |
File: src/Reactor/Controls/AutoSuggest/AutoSuggestElement.cs.
- Event parity. Inventory every callback on
AutoSuggestElement<T>and confirm each has a fluent extension insrc/Reactor/Elements/ElementExtensions.Events.cs. - Property coverage. Compare against
AutoSuggestBoxElement(spec 039 §3.4) — the typed peer should expose at minimum the same common properties as its untyped sibling, plus a typed item template / display selector surface. - Naming alignment. Confirm factory name, element-record name,
and namespace are self-consistent. The Reactor untyped sibling is
AutoSuggestBoxElement— call out theBoxsuffix delta.
File: src/Reactor/Controls/DataGrid/DataGridElement.cs + sibling files
in the same folder.
- Event parity. Inventory every callback on
DataGridElement<T>(OnSelectionChanged,OnRowChanged, …) and confirm each has a fluent extension. Note:OnRowChangedisFunc<RowKey, T, Task>?(notAction), so spec 040 decides whetherFunc-shaped callbacks should also get fluents (spec 039 only coveredAction/Action<T>). - Property coverage. Audit against
Microsoft.UI.Xaml.Controls.DataGrid(Community Toolkit) and WinFormsDataGridView. Likely gaps: sort/group state, column auto-sizing, frozen columns, alternating row brushes, cell-validation surface, copy/paste keymap. - Naming alignment. Confirm
DataGridElement<T>vsMicrosoft.UI.Xaml.Controls.DataGrid(CT) vsDataGridView(WinForms) — the Reactor name is fine; document the chosen reference peer for callers.
File: src/Reactor/Controls/MaskedTextBox/MaskedTextFieldElement.cs.
- Event parity. Inventory every callback (currently
OnChanged) and confirm fluent coverage. - Property coverage. Audit against WinForms
MaskedTextBox. Likely gaps:PromptChar,HidePromptOnLeave,BeepOnError,RejectInputOnFirstFailure,CutCopyMaskFormat,MaskCompleted/MaskFullstate surface. - Naming alignment. The folder is
MaskedTextBox/while the type isMaskedTextFieldElementand the factory isMaskedTextField. Spec 039 §16.3 already flagged this — if/when we renameTextField→TextBoxwe bundle this rename in the same change. Spec 040 either re-confirms keep-as-is or proposes the rename.
File: src/Reactor/Controls/PropertyGrid/PropertyGridElement.cs + sibling
files (PropertyGridDefaults, TypeRegistry, TypeMetadata,
Attributes, ReflectionTypeMetadataProvider).
- Event parity. Inventory every callback (currently
OnRootChanged) and confirm fluent coverage. Decide whether per-property change events should also surface. - Property coverage. Audit against WinForms
PropertyGrid. Likely gaps:BrowsableAttributes/ categorization toggle,HelpVisible,ToolbarVisible, sort mode (categorized vs alphabetic),SelectedGridItemChanged,PropertySortenum surface. - Naming alignment. Confirm element-record / factory /
attribute namespace are self-consistent.
Controls.Attributescurrently exports[BrowsableInPropertyGrid]etc. — call out the pattern.
File: src/Reactor/Controls/Virtualization/VirtualListElement.cs.
- Event parity. Inventory every callback (currently
OnVisibleRangeChanged) and confirm fluent coverage. Decide whether scroll-position / mount/unmount-per-item events should surface (these tend to be hot paths — be deliberate). - Property coverage. Audit against WinUI
ItemsRepeaterandListViewvirtualization surface. Likely gaps:Orientation,EstimatedItemSizevsFixedItemSize(currently only fixed), anchor-based scrolling,IncrementalLoadingTrigger, bidirectional incremental loading. - Naming alignment. Reactor's
VirtualListElementis generic virtualization (vsLazyVStack<T>/LazyHStack<T>which are typedItemsRepeaterwrappers — spec 039 §0.3). Document the relationship between the three.
To be filled out once §1–§5 are audited. Likely to mirror spec 039 §14:
- Event-fluent parity (most controls already covered by spec 039 Phase 7.2; expect this section to be mostly a no-op).
- Property-coverage gaps with the most user-visible impact (DataGrid + PropertyGrid are likely to dominate).
- Naming-alignment decisions (the
MaskedTextFieldvsMaskedTextBoxquestion carries forward from spec 039 §16.3).
Spec 039 Phase 3.7 deferred five niche WinUI event surfaces to this spec. None require a new Reactor element record beyond what already exists, so they slot in as follow-ons to the §1–§5 audit above. Per-item rationale lives in the 039 implementation task list; what's recorded here is the ownership transfer.
-
MenuFlyout.Opening/MenuFlyout.Closing— needs a Reactor-shaped cancellation pattern. Open question: how do we model cancellable args without leakingCancelEventArgsinto user callbacks? -
CommandBar.IsOpenChanged— no existing consumer; bundle with any futureCommandBar-using sample. -
SemanticZoom.ViewChangeStarted/SemanticZoom.ViewChangeCompleted—SemanticZoomis not currently modelled as a Reactor element; modelling the control is a prerequisite. -
AnnotatedScrollBar.DetailLabelRequested—AnnotatedScrollBar(WinUI 3 1.5+) is not yet exposed as a Reactor element. -
MapControl.ViewChanged— depends on the Windows Maps SDK which is not currently a Reactor dependency. Likely stays deferred until a consumer pulls the SDK in.
To be filled out during audit. Likely candidates:
- Should
Func<…, Task>?callbacks (e.g.DataGridElement<T>.OnRowChanged) get fluents the same wayAction-shaped callbacks do? Spec 039 §0.1 only coveredAction/Action<T>. - For
PropertyGridandDataGrid, do we model per-cell/per-property change events or rely on the existing whole-root / whole-row events? - For
VirtualListElement, do we exposeMountItem/UnmountItemlifecycle events — and at what cost on hot scroll paths?