reactor-wrapping

Generates declarative Reactor wrappers for arbitrary WinUI controls via a source generator.

625|52|Updated Apr 16, 2026
One-click install
npx skills add https://github.com/microsoft/microsoft-ui-reactor --skill reactor-wrapping
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: reactor-wrapping
Source: https://github.com/microsoft/microsoft-ui-reactor/tree/main/plugins/reactor/skills/reactor-wrapping
Command: npx skills add https://github.com/microsoft/microsoft-ui-reactor --skill reactor-wrapping

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

When building a Reactor app you often need a control that has no built-in factory — a Windows Community Toolkit control, a third-party vendor control, or your own custom Control subclass. Writing the wrapper, handler, and registration code by hand is repetitive and error-prone. This Skill turns any such control into a first-class declarative Reactor element from a single annotated partial record, with zero hand-written wrapper code.

Core Features & Use Cases

  • Source-generated wrappers: Annotate an empty partial record with [GenerateReactorWrapper(typeof(T))] and the generator emits init-props, the ControlDescriptor, Pattern-A registration, and a factory named after the control.
  • Auto-inference: Props, content slots, panel children, ItemsControl items, two-way value/event pairs, and event callbacks are inferred automatically; [Wrap*] attributes ([WrapControlled], [WrapAlias], [WrapContent], [WrapEvent], [WrapLifecycle], [WrapElementSlot], and more) cover non-conventional cases.
  • Imperative lifecycle support: [WrapLifecycle] runs mount/unmount methods (e.g. CameraPreview.StartAsync) so call sites stay purely declarative.
  • Use Case: Wrap the CommunityToolkit Segmented control whose SelectedIndex changes through SelectionChanged by adding [WrapControlled("SelectedIndex", ChangedEvent = "SelectionChanged")], then consume it as Segmented(selectedIndex: idx, onSelectedIndexChanged: setIdx, items: ...).

Quick Start

Wrap the CommunityToolkit SettingsCard control as a declarative Reactor element using the GenerateReactorWrapper source generator and show me how to use it in a component.

Frequently Asked Questions about reactor-wrapping

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I wrap a third-party WinUI control for use in Reactor?

Declare an empty partial record annotated with [GenerateReactorWrapper(typeof(YourControl))]. The source generator emits the init-props, ControlDescriptor, registration, and a factory named after the control, so no hand-written wrapper code is needed.

How do I make a control property two-way when its change event is not named PropertyChanged?

Add [WrapControlled("PropertyName", ChangedEvent = "ActualEventName")] to the partial record. For example, Segmented.SelectedIndex pairs with SelectionChanged, which the strict {P}Changed auto-pairing convention cannot infer.

Can I wrap Windows Community Toolkit controls like SettingsCard or CameraPreview?

Yes. Reference the WCT package and Microsoft.UI.Reactor, then annotate a partial record with [GenerateReactorWrapper]. For imperative controls like CameraPreview, add [WrapLifecycle] to run StartAsync on mount and Stop on unmount.

What are the requirements for a control to be wrappable by the generator?

The target must be a non-static FrameworkElement with a public parameterless constructor, otherwise diagnostic REACTORGEN001 is emitted. The declaring record must be partial and live in a namespace you control.

When should I write a hand-written ControlDescriptor instead of using the generator?

Drop to the manual ControlDescriptor/IElementHandler path only when a control's contract cannot be expressed with the [Wrap*] attributes. The generator targets the common case; prefer adding a reusable [Wrap*] capability over a one-off handler.

Why does my wrapped control library crash with 0xC000027B on first use?

That crash occurs when the control library's Themes/Generic.xaml is not loaded before first realization. The generator prevents it by emitting ReactorApp.RegisterControlAssembly in the element's static constructor automatically.