[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M69B92C846XMSNJ4PZGVYY3C":3,"skill-same:01M69B92C846XMSNJ4PZGVYY3C":69},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":41,"linkOnly":42,"markdownContent":43,"markdownBody":44,"frontMatter":45,"refName":46,"commitSha":47,"skillDirectory":48,"forksCount":49,"repositoryHtmlUrl":50,"repositoryHomepageUrl":6,"ownerHtmlUrl":51,"ownerBlogUrl":52,"ownerDescription":53,"updatedAt":54,"install":55,"resources":68},"01M69B92C846XMSNJ4PZGVYY3C","reactor-wrapping",null,"Turn ANY WinUI control — a vendor\u002Fthird-party control, your own custom Control, or a Windows Community Toolkit one — into a first-class declarative Reactor element with the [GenerateReactorWrapper] source generator, zero hand-written wrapper code. Covers auto-inference (props, content, two-way pairs, panel\u002Fitems children, events), the [Wrap*] annotation cheat-sheet, imperative-lifecycle controls, diagnostics, and when to fall back to a hand-written ControlDescriptor.","microsoft\u002Fmicrosoft-ui-reactor","microsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F6154722?v=4","01M698VYDXZ6JW5WH3CRV650R8","Microsoft","01M69B6EF21X2GHARCXN2BH1K1",885,"MIT","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-wrapping\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"reactor wrapping","lifecycle","with","hand","code","cheat","generator","when","auto","controls","custom","element","declarative","winui","ZeRO","panel","community","back","inference","diagnostics","toolkit","windows","2026-11-10 10:12:30",false,"---\nname: reactor-wrapping\ndescription: \"Turn ANY WinUI control — a vendor\u002Fthird-party control, your own custom Control, or a Windows Community Toolkit one — into a first-class declarative Reactor element with the [GenerateReactorWrapper] source generator, zero hand-written wrapper code. Covers auto-inference (props, content, two-way pairs, panel\u002Fitems children, events), the [Wrap*] annotation cheat-sheet, imperative-lifecycle controls, diagnostics, and when to fall back to a hand-written ControlDescriptor.\"\n---\n\n# Reactor — Wrapping Arbitrary Controls (source generator)\n\nUse this skill when the app needs a control Reactor has **no built-in factory\nfor** — a Windows Community Toolkit control, a third-party vendor control, or the\napp's own custom `Control` subclass. The `Reactor.Wrappers.Generator` source\ngenerator turns the control into a first-class declarative element (init-props +\n`ControlDescriptor` + Pattern-A registration + a parameterized factory named after\nthe control) from a single annotated partial record. **No hand-written wrapper,\nhandler, or registration code.**\n\n> Canonical worked example: `samples\u002Fapps\u002Fwct-controls\u002F` (declarations in\n> `WctControls.cs`, usage in `Program.cs`). Design spec: `docs\u002Fspecs\u002F058-control-wrapper-generator.md`.\n> For controls the generator still can't express, drop to the hand-written\n> `ControlDescriptor` \u002F `IElementHandler` path in `docs\u002Fguide\u002Fextending-reactor-controls.md`.\n\n## The whole feature in one example\n\n```csharp\nusing Microsoft.UI.Reactor.Wrappers;   \u002F\u002F the [Wrap*] authoring attributes\n\nnamespace MyApp;\n\n\u002F\u002F 1. Declare an empty partial record, annotated with the control to wrap.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.SettingsCard))]\npublic partial record SettingsCardElement;\n```\n\n```csharp\n\u002F\u002F 2. Consume the generated factory via `using static` (named after the control).\nusing static MyApp.SettingsCardElement;\n\nSettingsCard(\n    header: \"Wi-Fi\",\n    description: wifiOn ? \"Connected\" : \"Disconnected\",\n    content: ToggleSwitch(isOn: wifiOn, onIsOnChanged: setWifiOn))  \u002F\u002F a Reactor child INSIDE a WCT control\n```\n\nThe generator fills the rest of that partial: one init-property per surfaced\ncontrol property, the single-content\u002Fchildren slot, `On{Event}` callbacks, the\n`ControlDescriptor`, the trim-rooting `static` cctor registration, and the\n`SettingsCard(...)` factory. `Setters` is always emitted as an escape hatch\n(`.Set(c => c.Foo = …)`) for anything not surfaced.\n\nThe generator emits `ReactorApp.TryRegisterControlAssembly(typeof(X).Assembly)`\nin the element's static constructor to discover a control library's metadata\nbefore first realization (spec 058 §9a). The `Try` call quietly returns `false`\nif the provider has been trimmed; a `0xC000027B` crash when the wrapped control\nis first realized is a symptom that explicit registration may be needed.\n\nFor code-only Native AOT apps, implicit discovery of the toolkit provider can be\ntrimmed. Explicitly construct and register its generated `XamlMetaDataProvider`\nbefore realization when needed; see `docs\u002Faot-support.md`. The observable Items\ncollection's generated WinRT exposure does not root toolkit metadata.\n\n## Requirements & setup\n\n- Reference `Microsoft.UI.Reactor` (carries the generator in `analyzers\u002Fdotnet\u002Fcs\u002F`\n  and the authoring attributes in `Reactor.Wrappers.Abstractions.dll`).\n- Reference the control's own package (e.g. the WCT\n  `CommunityToolkit.WinUI.Controls.*` packages).\n- The target must be a **non-static `FrameworkElement`** with a **public\n  parameterless constructor** (else `REACTORGEN001`).\n- Keep the record `partial` (the generator fills the other half) and in a\n  namespace you control.\n\n## What is auto-inferred (zero config)\n\nThe generator walks members from the most-derived type **up to but excluding**\n`Control`\u002F`FrameworkElement` (Reactor already models that layout plumbing via\ngeneric modifiers like `.Margin()`, `.Width()`):\n\n| Control shape | Becomes |\n|---|---|\n| Settable value prop (`string`\u002F`object`→text, `bool`\u002F`int`\u002F`double`\u002Fenum, structs like `Thickness`\u002F`Color`, `Brush`\u002F`FontFamily`, `bool?`\u002F`DateTimeOffset?` tri-state) | a nullable \u002F `Optional\u003CT>` **one-way** init-prop (skipped when unset) |\n| Value prop `P` **paired with** a `{P}Changed` event | a **two-way controlled** `Optional\u003CT>` prop + `On{P}Changed` callback, with echo suppression |\n| The control's `[ContentProperty]` (a `UIElement` child, or `object` named exactly `Content`) | the single **`content:`** child slot |\n| A public `Children` of `UIElementCollection` (a `Panel`) | a `params Element[]` children slot |\n| A public `Items` whose type is\u002Fimplements `IList\u003Cobject>` (an `ItemsControl`) | a `params object[] items` slot; incremental reconciliation, `.WithKey(...)` preserves state across reorders, and writable `IList\u003Cobject>` sinks get an observable list on mount |\n| A fire-and-forget `RoutedEventHandler` \u002F `TypedEventHandler\u003C,>` \u002F `EventHandler\u003CA>` event | an `On{Event}` callback (typed events auto-surface the whole args as `Action\u003CA>`) |\n\nTwo-way auto-pairing keys **strictly on the `{P}Changed` name**. Controls whose\nchange event breaks that convention (`ToggleSwitch.IsOn`↔`Toggled`,\n`Segmented.SelectedIndex`↔`SelectionChanged`) stay one-way until you add\n`[WrapControlled]`.\n\n## Annotation cheat-sheet (opt-in, when inference isn't enough)\n\nAll live in `Microsoft.UI.Reactor.Wrappers`. All are repeatable unless noted.\n\n| Attribute | Use it to… |\n|---|---|\n| `[GenerateReactorWrapper(typeof(T), Exclude\u002FInclude\u002FAutoDiscover)]` | wrap `T`; prune noisy inherited props (`Exclude = new[]{ \"CommandParameter\" }`) or switch to explicit opt-in (`AutoDiscover = false, Include = new[]{ … }`). |\n| `[WrapControlled(\"P\", ChangedEvent = \"…\")]` | make `P` two-way when its event isn't `{P}Changed`. Use `Events = new[]{ \"Checked\",\"Unchecked\" }` for multi-event values (read back after any fire). `Deferred = true` for coercing or deferred string boxes (`PasswordBox.Password`); it uses the suppress counter, so two writes whose echoes merge into one event (a debounced box) leave a token that drops the next user edit. The built-in `AutoSuggestBox` and `RichEditBox` use the value-diff arm instead, which the generator doesn't emit. A control has **one** controlled slot — two `[WrapControlled]` on one control warns `REACTORGEN012`. |\n| `[WrapOneWay(\"P\")]` | opt a prop **out** of two-way auto-pairing (display-only despite a `{P}Changed`, e.g. `ProgressBar.Value`). |\n| `[WrapAlias(\"FriendlyName\", \"ControlProperty\")]` | surface a control prop under a nicer name (`\"Min\"`→`\"Minimum\"`). Aliasing the content property turns it into a string value prop (no child slot). |\n| `[WrapContent(\"Prop\")]` | override which property is the `content:` child slot. |\n| `[WrapConvert(\"Prop\")]` | surface a struct prop (`CornerRadius`, `Thickness`) as an ergonomic scalar via its single-arg constructor (`double?` → `new CornerRadius(v)`). |\n| `[WrapEvent(\"Foo\", Arg = \"ErrorMessage\")]` | project event args into a typed `On{Event}(args.Arg)` callback; `Args = new[]{ … }` for multi-param. |\n| `[WrapLifecycle(nameof(Start), OnUnmounted = nameof(Stop))]` | run a `static void M(TControl)` on mount\u002Funmount for imperative controls (`CameraPreview.StartAsync`) — **no call-site boilerplate**. |\n| `[WrapPanelChildren(PerChild = …)]` | wire per-child attached props (`Grid.SetRow`, `Canvas.SetLeft`) onto a panel; `AfterAll` for two-pass (RelativePanel). |\n| `[WrapManual(\"P\")]` + `static partial Customize(d)` | hand-chain one entry the generator can't infer while it still generates the rest. |\n| `[WrapElementSlot(\"Prop\", ControlProperty = \"…\")]` | auto-wire a **secondary single-element slot** that writes a dedicated control property (`TabView.TabStripHeader`, `SettingsCard.HeaderIcon`) — mounts via `ctx.MountChild`, updates via state-preserving `ctx.ReconcileChild`, and terminally unmounts the child before detaching it, independently of the descriptor author's `OnUnmount`. When no slot element is declared, the control's constructor default is left untouched. Use `ControlProperty=` when the element-facing name differs from the control property. The control property must be public-settable and `object`\u002F`UIElement`-typed. For the **primary** child use `[WrapContent]`; for a slot that shares a control prop with a string fallback (`Expander.Header`) stay manual. |\n| `[WrapPolymorphic(nameof(Resolve))]` \u002F `[WrapDecorator(nameof(Create))]` | controls whose concrete type is chosen at runtime, or that need a fully custom mount\u002Fupdate\u002Funmount lifecycle (emit an `IDecoratorElementHandler`, not a descriptor). |\n\n### Imperative control (lifecycle) — paste-ready\n\n```csharp\n\u002F\u002F CameraPreview must be StartAsync'd after mount and Stop'd on unmount. Declared\n\u002F\u002F ONCE here, so every call site is a plain declarative `CameraPreview(...)`.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.CameraPreview))]\n[WrapEvent(\"PreviewFailed\", Arg = \"Error\")]\n[WrapLifecycle(nameof(StartPreview), OnUnmounted = nameof(StopPreview))]\npublic partial record CameraPreviewElement\n{\n    private static async void StartPreview(CommunityToolkit.WinUI.Controls.CameraPreview cp)\n    {\n        try { await cp.StartAsync(cp.CameraHelper); } catch { \u002F* surfaced via PreviewFailed *\u002F }\n    }\n    private static void StopPreview(CommunityToolkit.WinUI.Controls.CameraPreview cp)\n    {\n        try { cp.Stop(); } catch { \u002F* already torn down *\u002F }\n    }\n}\n```\n\n### Non-conventional two-way event\n\n```csharp\n\u002F\u002F SelectedIndex changes through SelectionChanged, not SelectedIndexChanged.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.Segmented))]\n[WrapControlled(\"SelectedIndex\", ChangedEvent = \"SelectionChanged\")]\npublic partial record SegmentedElement;\n\u002F\u002F → Segmented(selectedIndex: idx, onSelectedIndexChanged: setIdx, items: …)\n```\n\n## Hand-tuning a single generated member\n\nWrite the member yourself in your half of the partial; the generator skips any\nmember you declare. Example — treat `Header` as templated Reactor content instead\nof plain text:\n\n```csharp\npublic partial record SettingsCardElement\n{\n    public Element? Header { get; init; }\n}\n```\n\n## Diagnostics\n\n`REACTORGEN001` (target isn't a non-static `FrameworkElement` with a public\nparameterless ctor) · `…002` (bad Include\u002FExclude name) · `…003`\u002F`…004`\n(WrapControlled property \u002F change-event) · `…005` (WrapAlias control property) ·\n`…006` (WrapOneWay) · `…007` (WrapContent) · `…008` (WrapConvert) ·\n`…009`\u002F`…010` (WrapEvent target \u002F arg) · `…011` (WrapLifecycle method) · `…012` (two\ncontrolled props share one control) · `…013` (WrapElementSlot control property\nmissing\u002Fnot-settable — set `ControlProperty=`) · `…014` (WrapElementSlot control\nproperty not `UIElement`-assignable) · `…015` (WrapElementSlot slot name not a valid\nidentifier). Run `mur check \u003Cpath>` — it surfaces these\nwith skill pointers.\n\n## When to drop to a hand-written descriptor\n\nThe generator targets the common case. Reach for the manual\n`ControlDescriptor` \u002F `IElementHandler` path (`docs\u002Fguide\u002Fextending-reactor-controls.md`,\nregistered via `ControlRegistry.RegisterHandler`) only when a control's contract\nis something the attributes above can't yet express — and prefer adding a reusable\n`[Wrap*]` capability over a one-off handler when the shape is general.\n","# Reactor — Wrapping Arbitrary Controls (source generator)\n\nUse this skill when the app needs a control Reactor has **no built-in factory\nfor** — a Windows Community Toolkit control, a third-party vendor control, or the\napp's own custom `Control` subclass. The `Reactor.Wrappers.Generator` source\ngenerator turns the control into a first-class declarative element (init-props +\n`ControlDescriptor` + Pattern-A registration + a parameterized factory named after\nthe control) from a single annotated partial record. **No hand-written wrapper,\nhandler, or registration code.**\n\n> Canonical worked example: `samples\u002Fapps\u002Fwct-controls\u002F` (declarations in\n> `WctControls.cs`, usage in `Program.cs`). Design spec: `docs\u002Fspecs\u002F058-control-wrapper-generator.md`.\n> For controls the generator still can't express, drop to the hand-written\n> `ControlDescriptor` \u002F `IElementHandler` path in `docs\u002Fguide\u002Fextending-reactor-controls.md`.\n\n## The whole feature in one example\n\n```csharp\nusing Microsoft.UI.Reactor.Wrappers;   \u002F\u002F the [Wrap*] authoring attributes\n\nnamespace MyApp;\n\n\u002F\u002F 1. Declare an empty partial record, annotated with the control to wrap.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.SettingsCard))]\npublic partial record SettingsCardElement;\n```\n\n```csharp\n\u002F\u002F 2. Consume the generated factory via `using static` (named after the control).\nusing static MyApp.SettingsCardElement;\n\nSettingsCard(\n    header: \"Wi-Fi\",\n    description: wifiOn ? \"Connected\" : \"Disconnected\",\n    content: ToggleSwitch(isOn: wifiOn, onIsOnChanged: setWifiOn))  \u002F\u002F a Reactor child INSIDE a WCT control\n```\n\nThe generator fills the rest of that partial: one init-property per surfaced\ncontrol property, the single-content\u002Fchildren slot, `On{Event}` callbacks, the\n`ControlDescriptor`, the trim-rooting `static` cctor registration, and the\n`SettingsCard(...)` factory. `Setters` is always emitted as an escape hatch\n(`.Set(c => c.Foo = …)`) for anything not surfaced.\n\nThe generator emits `ReactorApp.TryRegisterControlAssembly(typeof(X).Assembly)`\nin the element's static constructor to discover a control library's metadata\nbefore first realization (spec 058 §9a). The `Try` call quietly returns `false`\nif the provider has been trimmed; a `0xC000027B` crash when the wrapped control\nis first realized is a symptom that explicit registration may be needed.\n\nFor code-only Native AOT apps, implicit discovery of the toolkit provider can be\ntrimmed. Explicitly construct and register its generated `XamlMetaDataProvider`\nbefore realization when needed; see `docs\u002Faot-support.md`. The observable Items\ncollection's generated WinRT exposure does not root toolkit metadata.\n\n## Requirements & setup\n\n- Reference `Microsoft.UI.Reactor` (carries the generator in `analyzers\u002Fdotnet\u002Fcs\u002F`\n  and the authoring attributes in `Reactor.Wrappers.Abstractions.dll`).\n- Reference the control's own package (e.g. the WCT\n  `CommunityToolkit.WinUI.Controls.*` packages).\n- The target must be a **non-static `FrameworkElement`** with a **public\n  parameterless constructor** (else `REACTORGEN001`).\n- Keep the record `partial` (the generator fills the other half) and in a\n  namespace you control.\n\n## What is auto-inferred (zero config)\n\nThe generator walks members from the most-derived type **up to but excluding**\n`Control`\u002F`FrameworkElement` (Reactor already models that layout plumbing via\ngeneric modifiers like `.Margin()`, `.Width()`):\n\n| Control shape | Becomes |\n|---|---|\n| Settable value prop (`string`\u002F`object`→text, `bool`\u002F`int`\u002F`double`\u002Fenum, structs like `Thickness`\u002F`Color`, `Brush`\u002F`FontFamily`, `bool?`\u002F`DateTimeOffset?` tri-state) | a nullable \u002F `Optional\u003CT>` **one-way** init-prop (skipped when unset) |\n| Value prop `P` **paired with** a `{P}Changed` event | a **two-way controlled** `Optional\u003CT>` prop + `On{P}Changed` callback, with echo suppression |\n| The control's `[ContentProperty]` (a `UIElement` child, or `object` named exactly `Content`) | the single **`content:`** child slot |\n| A public `Children` of `UIElementCollection` (a `Panel`) | a `params Element[]` children slot |\n| A public `Items` whose type is\u002Fimplements `IList\u003Cobject>` (an `ItemsControl`) | a `params object[] items` slot; incremental reconciliation, `.WithKey(...)` preserves state across reorders, and writable `IList\u003Cobject>` sinks get an observable list on mount |\n| A fire-and-forget `RoutedEventHandler` \u002F `TypedEventHandler\u003C,>` \u002F `EventHandler\u003CA>` event | an `On{Event}` callback (typed events auto-surface the whole args as `Action\u003CA>`) |\n\nTwo-way auto-pairing keys **strictly on the `{P}Changed` name**. Controls whose\nchange event breaks that convention (`ToggleSwitch.IsOn`↔`Toggled`,\n`Segmented.SelectedIndex`↔`SelectionChanged`) stay one-way until you add\n`[WrapControlled]`.\n\n## Annotation cheat-sheet (opt-in, when inference isn't enough)\n\nAll live in `Microsoft.UI.Reactor.Wrappers`. All are repeatable unless noted.\n\n| Attribute | Use it to… |\n|---|---|\n| `[GenerateReactorWrapper(typeof(T), Exclude\u002FInclude\u002FAutoDiscover)]` | wrap `T`; prune noisy inherited props (`Exclude = new[]{ \"CommandParameter\" }`) or switch to explicit opt-in (`AutoDiscover = false, Include = new[]{ … }`). |\n| `[WrapControlled(\"P\", ChangedEvent = \"…\")]` | make `P` two-way when its event isn't `{P}Changed`. Use `Events = new[]{ \"Checked\",\"Unchecked\" }` for multi-event values (read back after any fire). `Deferred = true` for coercing or deferred string boxes (`PasswordBox.Password`); it uses the suppress counter, so two writes whose echoes merge into one event (a debounced box) leave a token that drops the next user edit. The built-in `AutoSuggestBox` and `RichEditBox` use the value-diff arm instead, which the generator doesn't emit. A control has **one** controlled slot — two `[WrapControlled]` on one control warns `REACTORGEN012`. |\n| `[WrapOneWay(\"P\")]` | opt a prop **out** of two-way auto-pairing (display-only despite a `{P}Changed`, e.g. `ProgressBar.Value`). |\n| `[WrapAlias(\"FriendlyName\", \"ControlProperty\")]` | surface a control prop under a nicer name (`\"Min\"`→`\"Minimum\"`). Aliasing the content property turns it into a string value prop (no child slot). |\n| `[WrapContent(\"Prop\")]` | override which property is the `content:` child slot. |\n| `[WrapConvert(\"Prop\")]` | surface a struct prop (`CornerRadius`, `Thickness`) as an ergonomic scalar via its single-arg constructor (`double?` → `new CornerRadius(v)`). |\n| `[WrapEvent(\"Foo\", Arg = \"ErrorMessage\")]` | project event args into a typed `On{Event}(args.Arg)` callback; `Args = new[]{ … }` for multi-param. |\n| `[WrapLifecycle(nameof(Start), OnUnmounted = nameof(Stop))]` | run a `static void M(TControl)` on mount\u002Funmount for imperative controls (`CameraPreview.StartAsync`) — **no call-site boilerplate**. |\n| `[WrapPanelChildren(PerChild = …)]` | wire per-child attached props (`Grid.SetRow`, `Canvas.SetLeft`) onto a panel; `AfterAll` for two-pass (RelativePanel). |\n| `[WrapManual(\"P\")]` + `static partial Customize(d)` | hand-chain one entry the generator can't infer while it still generates the rest. |\n| `[WrapElementSlot(\"Prop\", ControlProperty = \"…\")]` | auto-wire a **secondary single-element slot** that writes a dedicated control property (`TabView.TabStripHeader`, `SettingsCard.HeaderIcon`) — mounts via `ctx.MountChild`, updates via state-preserving `ctx.ReconcileChild`, and terminally unmounts the child before detaching it, independently of the descriptor author's `OnUnmount`. When no slot element is declared, the control's constructor default is left untouched. Use `ControlProperty=` when the element-facing name differs from the control property. The control property must be public-settable and `object`\u002F`UIElement`-typed. For the **primary** child use `[WrapContent]`; for a slot that shares a control prop with a string fallback (`Expander.Header`) stay manual. |\n| `[WrapPolymorphic(nameof(Resolve))]` \u002F `[WrapDecorator(nameof(Create))]` | controls whose concrete type is chosen at runtime, or that need a fully custom mount\u002Fupdate\u002Funmount lifecycle (emit an `IDecoratorElementHandler`, not a descriptor). |\n\n### Imperative control (lifecycle) — paste-ready\n\n```csharp\n\u002F\u002F CameraPreview must be StartAsync'd after mount and Stop'd on unmount. Declared\n\u002F\u002F ONCE here, so every call site is a plain declarative `CameraPreview(...)`.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.CameraPreview))]\n[WrapEvent(\"PreviewFailed\", Arg = \"Error\")]\n[WrapLifecycle(nameof(StartPreview), OnUnmounted = nameof(StopPreview))]\npublic partial record CameraPreviewElement\n{\n    private static async void StartPreview(CommunityToolkit.WinUI.Controls.CameraPreview cp)\n    {\n        try { await cp.StartAsync(cp.CameraHelper); } catch { \u002F* surfaced via PreviewFailed *\u002F }\n    }\n    private static void StopPreview(CommunityToolkit.WinUI.Controls.CameraPreview cp)\n    {\n        try { cp.Stop(); } catch { \u002F* already torn down *\u002F }\n    }\n}\n```\n\n### Non-conventional two-way event\n\n```csharp\n\u002F\u002F SelectedIndex changes through SelectionChanged, not SelectedIndexChanged.\n[GenerateReactorWrapper(typeof(CommunityToolkit.WinUI.Controls.Segmented))]\n[WrapControlled(\"SelectedIndex\", ChangedEvent = \"SelectionChanged\")]\npublic partial record SegmentedElement;\n\u002F\u002F → Segmented(selectedIndex: idx, onSelectedIndexChanged: setIdx, items: …)\n```\n\n## Hand-tuning a single generated member\n\nWrite the member yourself in your half of the partial; the generator skips any\nmember you declare. Example — treat `Header` as templated Reactor content instead\nof plain text:\n\n```csharp\npublic partial record SettingsCardElement\n{\n    public Element? Header { get; init; }\n}\n```\n\n## Diagnostics\n\n`REACTORGEN001` (target isn't a non-static `FrameworkElement` with a public\nparameterless ctor) · `…002` (bad Include\u002FExclude name) · `…003`\u002F`…004`\n(WrapControlled property \u002F change-event) · `…005` (WrapAlias control property) ·\n`…006` (WrapOneWay) · `…007` (WrapContent) · `…008` (WrapConvert) ·\n`…009`\u002F`…010` (WrapEvent target \u002F arg) · `…011` (WrapLifecycle method) · `…012` (two\ncontrolled props share one control) · `…013` (WrapElementSlot control property\nmissing\u002Fnot-settable — set `ControlProperty=`) · `…014` (WrapElementSlot control\nproperty not `UIElement`-assignable) · `…015` (WrapElementSlot slot name not a valid\nidentifier). Run `mur check \u003Cpath>` — it surfaces these\nwith skill pointers.\n\n## When to drop to a hand-written descriptor\n\nThe generator targets the common case. Reach for the manual\n`ControlDescriptor` \u002F `IElementHandler` path (`docs\u002Fguide\u002Fextending-reactor-controls.md`,\nregistered via `ControlRegistry.RegisterHandler`) only when a control's contract\nis something the attributes above can't yet express — and prefer adding a reusable\n`[Wrap*]` capability over a one-off handler when the shape is general.\n",{"name":5,"description":7},"main","587dd6ae61699a11cd5e7fe5be123c8d8e0f1812","plugins\u002Freactor\u002Fskills\u002Freactor-wrapping",67,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor","https:\u002F\u002Fgithub.com\u002Fmicrosoft","https:\u002F\u002Fopensource.microsoft.com","Open source projects and samples from Microsoft","2026-11-14 02:51:08",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add microsoft\u002Fmicrosoft-ui-reactor --skill reactor-wrapping",{"tool":61,"command":62},"bunx","bunx skills add microsoft\u002Fmicrosoft-ui-reactor --skill reactor-wrapping",{"tool":64,"command":65},"pnpm","pnpm dlx skills add microsoft\u002Fmicrosoft-ui-reactor --skill reactor-wrapping","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-wrapping\u002FSKILL.md",true,[],[70,76,101,126,149,167],{"skillNo":71,"name":72,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":75,"publishedAt":41},"01M69B94E15PYYWXAGFV832MRK","Charting","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fsrc\u002FReactor.Advanced\u002FCharting\u002Fskill.md",[],[72],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":80,"categories":81,"keywords":82,"publishedAt":41},"01M69B90PW92BQ4YNZYTP4SERB","reactor-windowing","Reactor top-level windowing cookbook: WindowSpec, OpenWindow, draggable windows, borderless\u002Ftool windows, placement persistence, taskbar visibility, z-order, aspect ratio, SizeToContent, displays, taskbar integration, and owner-window file\u002Ffolder pickers.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-windowing\u002FSKILL.md",[],[83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,40,100],"reactor windowing","window","make","position","persistence","cookbook","integration","folder","command","command palette","top","progress","palette","file","restore","open","tool","remember",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":107,"publishedAt":41},"01M69B8Y5Y0VKXADXCN3W1NK89","reactor-recipes","Paste-ready single-file Reactor recipes indexed by intent — list with add\u002Fdelete\u002Ftoggle, sidebar navigation between pages, form with validation + submit gating, async fetch with loading\u002Ferror\u002Fdata states, themed Win11 card surface. Use a recipe instead of synthesizing from prose: copy, adjust, ship.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-recipes\u002FSKILL.md",[],[108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,21,96,125],"recipes","reactor recipes","adjust","pages","single","recipe","async","card","submit","loading","states","fetch","form","single-file","ready","error","use","gating",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":41},"01M69B8WNYS31M4P012P2QTX6R","reactor-navigation","Reactor navigation — `UseNavigation` hook, `NavigationHost` renderer, `NavigationView` sidebar, `TabView` tabs, route params, stack operations, page lifecycle, deep linking, transitions, caching. Use when building multi-page apps or wiring sidebar\u002Ftab navigation.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-navigation\u002FSKILL.md",[],[133,134,135,136,137,138,139,140,141,142,143,26,144,124,20,145,146,147,148],"navigation","reactor navigation","transitions","hook","operations","multi","page","stack","route","wiring","caching","apps","renderer","multi-page","linking","deep",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":155,"publishedAt":41},"01M69B8TGJA43N8X6BFVWTXC1H","reactor-input","Reactor input — gestures (`OnPan`, `OnPinch`, `OnRotate`), pointer events, drag-and-drop (`OnDragStarting`), focus management (`UseElementFocus`, `UseFocus`, `UseFocusTrap`). Use when implementing direct manipulation or custom focus behavior.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-input\u002FSKILL.md",[],[156,157,158,159,160,29,161,162,163,164,165,166,26,124],"reactor input","input","implementing","drag","gestures","events","direct","management","behavior","focus","drop",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":181,"publishedAt":41},"01M69B8R3MR39KBJ6V4NXGEB2N","reactor-getting-started","Reactor essentials in one place — React-to-Reactor mental model, minimal app shape, hooks, the most-used factories, the critical gotchas, and project setup. This is the only skill you need loaded for typical Reactor work; load topical skills (`reactor-async`, `reactor-design`, etc.) only when the task explicitly calls for them.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fmicrosoft-ui-reactor\u002Fblob\u002Fmain\u002Fplugins\u002Freactor\u002Fskills\u002Freactor-getting-started\u002FSKILL.md",[173,178],{"categoryNo":174,"categoryName":175,"taxonomyType":176,"taxonomyTypeDesc":177},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",{"categoryNo":179,"categoryName":180,"taxonomyType":176,"taxonomyTypeDesc":177},"01JBSEEDCAT000000000000015","视觉设计",[182,183,184,185,186,187,188,114,189,190,191,26,192,193,194,195,196,197,198,199],"reactor getting started","getting started","work","task","load","minimal","calls","mental model","for","you","critical","only","hooks","project","model","app","react","design"]