$npx -y skills add microsoft/win-dev-skills --skill winui-code-reviewCode quality review for WinUI 3 apps — MVVM compliance, x:Bind correctness, accessibility, theming, security, and performance. Use before committing to catch issues that the compiler and UI tests won't find.
| 1 | ### When to Use |
| 2 | |
| 3 | Run a code review **after the app builds and before committing**. This catches quality issues that aren't build errors and aren't visible in UI tests — patterns that compile and run but are wrong, fragile, or slow. |
| 4 | |
| 5 | ### How to Review |
| 6 | |
| 7 | Read through the project's XAML and C# files and check each section below. The `Microsoft.WindowsAppSDK.Analyzers` Roslyn analyzer ships with the `winui-dev-workflow` skill and is injected into your build when you compile via the `BuildAndRun.ps1` script that ships with that skill — the script drops a temporary `Directory.Build.props` into the project that loads the analyzer DLL and its `.targets`, then cleans up after the build. Plain `dotnet build` (or VS) does **not** load the analyzer automatically; if you want it to surface as build diagnostics outside the script, add the `<Analyzer Include="..." />` and `<Import Project="..." />` to your project's own `Directory.Build.props` (or wait for the planned NuGet package). |
| 8 | |
| 9 | The analyzer catches a curated set of WinUI 3 / Windows App SDK issues with categorized 4-digit IDs: |
| 10 | |
| 11 | * **WUI0xxx** — UWP → WinUI 3 API compatibility (`UwpXamlNamespace`, `Window.Current`, `CoreDispatcher`, `GetForCurrentView`) |
| 12 | * **WUI1xxx** — Migration-table data-driven hints (UWP API has WinAppSDK equivalent, no equivalent, feature-area hint) |
| 13 | * **WUI2xxx** — Runtime / layout / XAML pitfalls (raw `TabView` content, nested `x:Bind` without fallback, `x:Bind` without `Mode`, null `Converter`, missing `AutomationId`, attached-property syntax) |
| 14 | * **WUI3xxx** — MVVM patterns (old `[ObservableProperty]` field syntax) |
| 15 | * **WUI4xxx** — Interop (`WebView2` not initialized, removed ONNX Runtime GenAI APIs `WUI4101`-`WUI4103`) |
| 16 | |
| 17 | Every diagnostic ships at `Warning` severity (no rule is `Error`) and includes a `helpLinkUri`. Suppress noise with `#pragma warning disable WUIxxxx` or `<NoWarn>` as usual — the analyzer's `SuppressionTests` verify that pragma suppression round-trips correctly. |
| 18 | |
| 19 | ### MVVM Compliance |
| 20 | |
| 21 | - [ ] ViewModels extend `ObservableObject`, use `[ObservableProperty]` partial properties (not fields) |
| 22 | - [ ] Commands use `[RelayCommand]` attribute, not manual `ICommand` implementations |
| 23 | - [ ] No UI types in ViewModels (`SolidColorBrush`, `Visibility`, `BitmapImage`) — these belong in converters or XAML |
| 24 | - [ ] No business logic in code-behind — only navigation, dialog coordination, and event wiring |
| 25 | - [ ] `async Task` for async methods, `async void` only for event handlers |
| 26 | - [ ] Never replace `ObservableCollection<T>` — use `.Clear()` + re-add |
| 27 | |
| 28 | ### x:Bind and Data Binding |
| 29 | |
| 30 | - [ ] All bindings use `{x:Bind}`, not `{Binding}` |
| 31 | - [ ] `Mode=OneWay` or `TwoWay` set explicitly — `OneTime` default causes blank UI for dynamic data |
| 32 | - [ ] `x:DataType` set on every `DataTemplate` — required for compiled x:Bind |
| 33 | - [ ] No nested nullable paths (e.g., `ViewModel.Selected.Name`) without `FallbackValue` |
| 34 | - [ ] Command bindings can use OneTime (commands don't change) — don't add `Mode=OneWay` to `Command="{x:Bind}"` |
| 35 | |
| 36 | ### Accessibility |
| 37 | |
| 38 | - [ ] `AutomationProperties.AutomationId` on every interactive control (Button, TextBox, ComboBox, ToggleSwitch, ListView, NavigationViewItem) |
| 39 | - [ ] `AutomationProperties.Name` on icon-only buttons and controls without visible text |
| 40 | - [ ] Semantic controls (`Button`, `HyperlinkButton`) — not clickable `Border`/`TextBlock` |
| 41 | - [ ] No information conveyed by color alone |
| 42 | |
| 43 | ### Theming |
| 44 | |
| 45 | - [ ] All colors use `{ThemeResource}` brushes — no hardcoded `#FF0000` or `Color="Blue"` |
| 46 | - [ ] Typography uses built-in styles (`TitleTextBlockStyle`, `SubtitleTextBlockStyle`, `BodyTextBlockStyle`, `CaptionTextBlockStyle`) — no raw `FontSize` |
| 47 | - [ ] Spacing uses 4px grid multiples (4, 8, 12, 16, 24, 32, 48) |
| 48 | - [ ] Corner radius uses `ControlCornerRadius` / `OverlayCornerRadius` — not hardcoded values |
| 49 | - [ ] Styles referenced with `{StaticResource}` not `{ThemeResource}` (except for brush usage sites) |
| 50 | |
| 51 | ### Security |
| 52 | |
| 53 | - [ ] No secrets, API keys, or tokens in source code |
| 54 | - [ ] No `Process.Start` with unsanitized user input |
| 55 | - [ ] External input validated and sanitized before use |
| 56 | - [ ] File paths from user input not used directly in `File.Delete` / `File.WriteAllText` without validation |
| 57 | |
| 58 | ### Performance |
| 59 | |
| 60 | - [ ] Long or dynamic lists use `ListView`/`GridView` (virtualized), not `StackPanel` with `foreach` |
| 61 | - [ ] `x:Load` for content that's not always visible (e.g., dialogs, secondary panels) |
| 62 | - [ ] Heavy work off UI thread via `Task.Run` or `async/await` — never block UI |
| 63 | - [ ] No `.Result` / `.Wait()` / `.GetAwaiter().GetResult()` — these deadlock the UI thread |
| 64 | - [ ] `using` statements on all disposable objects (`Model`, `Tokenizer`, `InferenceSession`, `Generator`) |
| 65 | |
| 66 | ### Globalization |
| 67 | |
| 68 | - [ ] User-facing strings use `x:Uid` in |