Files
awesome-copilot/instructions/winui3.instructions.md
Niels Laute dcc2ee1086 Add WinUI 3 Expert (#865)
* WinUI agent

* Improvements

* Fixes

* Add WinUI 3 unit testing guidance across agent, instructions, and skill

- Expanded Testing section in agent with Unit Test App project setup,
  [TestMethod] vs [UITestMethod] attributes, and code examples
- Added Testing rules to instructions file
- Added Testing Migration section to migration guide skill with
  UWP-to-WinUI 3 test project mapping and updated checklist

Reference: https://learn.microsoft.com/en-us/windows/apps/winui/winui3/testing/create-winui-unit-test-project

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update agents/winui3-expert.agent.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Copilot tweaks

* Update agents/winui3-expert.agent.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update agents/winui3-expert.agent.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-04 10:04:56 +11:00

167 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: 'WinUI 3 and Windows App SDK coding guidelines. Prevents common UWP API misuse, enforces correct XAML namespaces, threading, windowing, and MVVM patterns for desktop Windows apps.'
applyTo: '**/*.xaml, **/*.cs, **/*.csproj'
---
# WinUI 3 / Windows App SDK
## Critical Rules — NEVER Use Legacy UWP APIs
These UWP patterns are **wrong** for WinUI 3 desktop apps. Always use the Windows App SDK equivalent.
- **NEVER** use `Windows.UI.Popups.MessageDialog`. Use `ContentDialog` with `XamlRoot` set.
- **NEVER** show a `ContentDialog` without setting `dialog.XamlRoot = this.Content.XamlRoot` first.
- **NEVER** use `CoreDispatcher.RunAsync` or `Dispatcher.RunAsync`. Use `DispatcherQueue.TryEnqueue`.
- **NEVER** use `Window.Current`. Track the main window via a static `App.MainWindow` property.
- **NEVER** use `Windows.UI.Xaml.*` namespaces. Use `Microsoft.UI.Xaml.*`.
- **NEVER** use `Windows.UI.Composition`. Use `Microsoft.UI.Composition`.
- **NEVER** use `Windows.UI.Colors`. Use `Microsoft.UI.Colors`.
- **NEVER** use `ApplicationView` or `CoreWindow` for window management. Use `Microsoft.UI.Windowing.AppWindow`.
- **NEVER** use `CoreApplicationViewTitleBar`. Use `AppWindowTitleBar`.
- **NEVER** use `GetForCurrentView()` patterns (e.g., `UIViewSettings.GetForCurrentView()`). These do not exist in desktop WinUI 3. Use `AppWindow` APIs instead.
- **NEVER** use UWP `PrintManager` directly. Use `IPrintManagerInterop` with a window handle.
- **NEVER** use `DataTransferManager` directly for sharing. Use `IDataTransferManagerInterop` with a window handle.
- **NEVER** use UWP `IBackgroundTask`. Use `Microsoft.Windows.AppLifecycle` activation.
- **NEVER** use `WebAuthenticationBroker`. Use `OAuth2Manager` (Windows App SDK 1.7+).
## XAML Patterns
- The default XAML namespace maps to `Microsoft.UI.Xaml`, not `Windows.UI.Xaml`.
- Prefer `{x:Bind}` over `{Binding}` for compiled, type-safe, higher-performance bindings.
- Set `x:DataType` on `DataTemplate` elements when using `{x:Bind}` — this is required for compiled bindings in templates. On Page/UserControl, `x:DataType` enables compile-time binding validation but is not strictly required if the DataContext does not change.
- Use `Mode=OneWay` for dynamic values, `Mode=OneTime` for static, `Mode=TwoWay` only for editable inputs.
- Do not bind static constants — set them directly in XAML.
## Threading
- Use `DispatcherQueue.TryEnqueue(() => { ... })` to update UI from background threads.
- `TryEnqueue` returns `bool`, not a `Task` — it is fire-and-forget.
- Check thread access with `DispatcherQueue.HasThreadAccess` before dispatching.
- WinUI 3 uses standard STA (not ASTA). No built-in reentrancy protection — be cautious with async code that pumps messages.
## Windowing
- Get the `AppWindow` from a WinUI 3 `Window` via `WindowNative.GetWindowHandle``Win32Interop.GetWindowIdFromWindow``AppWindow.GetFromWindowId`.
- Use `AppWindow` for resize, move, title, and presenter operations.
- Custom title bar: use `AppWindow.TitleBar` properties, not `CoreApplicationViewTitleBar`.
- Track the main window as `App.MainWindow` (a static property set in `OnLaunched`).
## Dialogs and Pickers
- **ContentDialog**: Always set `dialog.XamlRoot = this.Content.XamlRoot` before calling `ShowAsync()`.
- **File/Folder Pickers**: Initialize with `WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd)` where `hwnd` comes from `WindowNative.GetWindowHandle(App.MainWindow)`.
- **Share/Print**: Use COM interop interfaces (`IDataTransferManagerInterop`, `IPrintManagerInterop`) with window handles.
## MVVM and Data Binding
- Prefer `CommunityToolkit.Mvvm` (`[ObservableProperty]`, `[RelayCommand]`) for MVVM infrastructure.
- Use `Microsoft.Extensions.DependencyInjection` for service registration and injection.
- Keep UI (Views) focused on layout and bindings; keep logic in ViewModels and services.
- Use `async`/`await` for I/O and long-running work to keep the UI responsive.
## Project Setup
- Target `net10.0-windows10.0.22621.0` (or appropriate TFM for the project's target SDK).
- Set `<UseWinUI>true</UseWinUI>` in the project file.
- Reference the latest stable `Microsoft.WindowsAppSDK` NuGet package.
- Use `System.Text.Json` with source generators for JSON serialization.
## C# Code Style
- Use file-scoped namespaces.
- Enable nullable reference types. Use `is null` / `is not null` instead of `== null`.
- Prefer pattern matching over `as`/`is` with null checks.
- PascalCase for types, methods, properties. camelCase for private fields.
- Allman brace style (opening brace on its own line).
- Prefer explicit types for built-in types; use `var` only when the type is obvious.
## Accessibility
- Set `AutomationProperties.Name` on all interactive controls.
- Use `AutomationProperties.HeadingLevel` on section headers.
- Hide decorative elements with `AutomationProperties.AccessibilityView="Raw"`.
- Ensure full keyboard navigation (Tab, Enter, Space, arrow keys).
- Meet WCAG color contrast requirements.
## Performance
- Prefer `{x:Bind}` (compiled) over `{Binding}` (reflection-based).
- **NativeAOT:** Under Native AOT compilation, `{Binding}` (reflection-based) does not work at all. Only `{x:Bind}` (compiled bindings) is supported. If the project uses NativeAOT, use `{x:Bind}` exclusively.
- Use `x:Load` or `x:DeferLoadStrategy` for UI elements that are not immediately needed.
- Use `ItemsRepeater` with virtualization for large lists.
- Avoid deep layout nesting — prefer `Grid` over nested `StackPanel` chains.
- Use `async`/`await` for all I/O; never block the UI thread.
## App Settings (Packaged vs Unpackaged)
- **Packaged apps**: `ApplicationData.Current.LocalSettings` works as expected.
- **Unpackaged apps**: Use a custom settings file (e.g., JSON in `Environment.GetFolderPath(SpecialFolder.LocalApplicationData)`).
- Do not assume `ApplicationData` is always available — check packaging status first.
## Typography
- **Always** use built-in TextBlock styles (`CaptionTextBlockStyle`, `BodyTextBlockStyle`, `BodyStrongTextBlockStyle`, `SubtitleTextBlockStyle`, `TitleTextBlockStyle`, `TitleLargeTextBlockStyle`, `DisplayTextBlockStyle`).
- Prefer using the built-in TextBlock styles over hardcoding `FontSize`, `FontWeight`, or `FontFamily`.
- Font: Segoe UI Variable is the default — do not change it.
- Use sentence casing for all UI text.
## Theming & Colors
- **Always** use `{ThemeResource}` for brushes and colors to support Light, Dark, and High Contrast themes automatically.
- **Never** hardcode color values (`#FFFFFF`, `Colors.White`, etc.) for UI elements. Use theme resources like `TextFillColorPrimaryBrush`, `CardBackgroundFillColorDefaultBrush`, `CardStrokeColorDefaultBrush`.
- Use `SystemAccentColor` (and `Light1``Light3`, `Dark1``Dark3` variants) for the user's accent color palette.
- For borders: use `CardStrokeColorDefaultBrush` or `ControlStrokeColorDefaultBrush`.
## Spacing & Layout
- Use a **4px grid system**: all margins, padding, and spacing values must be multiples of 4px.
- Standard spacing: 4 (compact), 8 (controls), 12 (small gutters), 16 (content padding), 24 (large gutters).
- Prefer `Grid` over deeply nested `StackPanel` chains for performance.
- Use `Auto` for content-sized rows/columns, `*` for proportional sizing. Avoid fixed pixel sizes.
- Use `VisualStateManager` with `AdaptiveTrigger` for responsive layouts at breakpoints (640px, 1008px).
- Use `ControlCornerRadius` (4px) for small controls and `OverlayCornerRadius` (8px) for cards, dialogs, flyouts.
## Materials & Elevation
- Use **Mica** (`MicaBackdrop`) for the app window backdrop. Requires transparent layers above to show through.
- Use **Acrylic** for transient surfaces only (flyouts, menus, navigation panes).
- Use `LayerFillColorDefaultBrush` for content layers above Mica.
- Use `ThemeShadow` with Z-axis `Translation` for elevation. Cards: 48 px, Flyouts: 32 px, Dialogs: 128 px.
## Motion & Transitions
- Use built-in theme transitions (`EntranceThemeTransition`, `RepositionThemeTransition`, `ContentThemeTransition`, `AddDeleteThemeTransition`).
- Avoid custom storyboard animations when a built-in transition exists.
## Control Selection
- Use `NavigationView` for primary app navigation (not custom sidebars).
- Use `InfoBar` for persistent in-app notifications (not custom banners).
- Use `TeachingTip` for contextual guidance (not custom popups).
- Use `NumberBox` for numeric input (not TextBox with manual validation).
- Use `ToggleSwitch` for on/off settings (not CheckBox).
- Use `ItemsView` as the modern collection control for displaying data with built-in selection, virtualization, and layout flexibility.
- Use `ListView`/`GridView` for standard virtualized lists and grids, especially when built-in selection support is needed.
- Use `ItemsRepeater` only for fully custom virtualizing layouts where you need complete control over rendering and do not need built-in selection or interaction handling.
- Use `Expander` for collapsible sections (not custom visibility toggling).
## Error Handling
- Always wrap `async void` event handlers in try/catch to prevent unhandled crashes.
- Use `InfoBar` (with `Severity = Error`) for user-facing error messages, not `ContentDialog` for routine errors.
- Handle `App.UnhandledException` for logging and graceful recovery.
## Testing
- **NEVER** use a plain MSTest or xUnit project for tests that instantiate WinUI 3 XAML types. Use a **Unit Test App (WinUI in Desktop)** project, which provides the Xaml runtime and UI thread.
- Use `[TestMethod]` for pure logic tests. Use `[UITestMethod]` for any test that creates or interacts with `Microsoft.UI.Xaml` types (controls, pages, user controls).
- Place testable business logic in a **Class Library (WinUI in Desktop)** project, separate from the main app.
- Build the solution before running tests to enable Visual Studio test discovery.
## Resources & Localization
- Store user-facing strings in `Resources.resw` files, not in code or XAML literals.
- Use `x:Uid` in XAML for localized text binding.
- Use DPI-qualified image assets (`logo.scale-200.png`); reference without scale qualifier (`ms-appx:///Assets/logo.png`).