Skip to main content

wpf-to-winui3-migration

Guide for migrating PowerToys modules from WPF to WinUI 3 (Windows App SDK). Use when asked to migrate WPF code, convert WPF XAML to WinUI, replace System.Windows namespaces with Microsoft.UI.Xaml, update Dispatcher to DispatcherQueue, replace DynamicResource with ThemeResource, migrate imaging APIs from System.Windows.Media.Imaging to Windows.Graphics.Imaging, convert WPF Window to WinUI Window, migrate .resx to .resw resources, migrate custom Observable/RelayCommand to CommunityToolkit.Mvvm source generators, handle WPF-UI (Lepo) to WinUI native control migration, or fix installer/build pipeline issues after migration. Keywords: WPF, WinUI, WinUI3, migration, porting, convert, namespace, XAML, Dispatcher, DispatcherQueue, imaging, BitmapImage, Window, ContentDialog, ThemeResource, DynamicResource, ResourceLoader, resw, resx, CommunityToolkit, ObservableProperty, WPF-UI, SizeToContent, AppWindow, SoftwareBitmap.

설치로 이동

소스 정보

저장소
microsoft/PowerToys
최근 소스 활동
2026년 7월 31일 08:28
감지된 SKILL.md 언어
영어
스타
138,874
포크
8,588

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
6 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
wpf-to-winui3-migration
description
Guide for migrating PowerToys modules from WPF to WinUI 3 (Windows App SDK). Use when asked to migrate WPF code, convert WPF XAML to WinUI, replace System.Windows namespaces with Microsoft.UI.Xaml, update Dispatcher to DispatcherQueue, replace DynamicResource with ThemeResource, migrate imaging APIs from System.Windows.Media.Imaging to Windows.Graphics.Imaging, convert WPF Window to WinUI Window, migrate .resx to .resw resources, migrate custom Observable/RelayCommand to CommunityToolkit.Mvvm source generators, handle WPF-UI (Lepo) to WinUI native control migration, or fix installer/build pipeline issues after migration. Keywords: WPF, WinUI, WinUI3, migration, porting, convert, namespace, XAML, Dispatcher, DispatcherQueue, imaging, BitmapImage, Window, ContentDialog, ThemeResource, DynamicResource, ResourceLoader, resw, resx, CommunityToolkit, ObservableProperty, WPF-UI, SizeToContent, AppWindow, SoftwareBitmap.
license
Complete terms in LICENSE.txt
# WPF to WinUI 3 Migration Skill Migrate PowerToys modules from WPF (`System.Windows.*`) to WinUI 3 (`Microsoft.UI.Xaml.*` / Windows App SDK). Based on patterns validated in the ImageResizer module migration. ## When to Use This Skill - Migrate a PowerToys module from WPF to WinUI 3 - Convert WPF XAML files to WinUI 3 XAML - Replace `System.Windows` namespaces with `Microsoft.UI.Xaml` - Migrate `Dispatcher` usage to `DispatcherQueue` - Migrate custom `Observable`/`RelayCommand` to CommunityToolkit.Mvvm source generators - Replace WPF-UI (Lepo) controls with native WinUI 3 controls - Convert imaging code from `System.Windows.Media.Imaging` to `Windows.Graphics.Imaging` - Handle WPF `Window` vs WinUI `Window` differences (sizing, positioning, SizeToContent) - Migrate resource files from `.resx` to `.resw` with `ResourceLoader` - Fix installer/build pipeline issues after WinUI 3 migration - Update project files, NuGet packages, and signing config ## Prerequisites - Visual Studio 2022 17.4+ - Windows App SDK NuGet package (`Microsoft.WindowsAppSDK`) - .NET 8+ with `net8.0-windows10.0.19041.0` TFM - Windows 10 1803+ (April 2018 Update or newer) ## Migration Strategy ### Phase-by-Phase Scope Work on bounded problems, not the entire codebase at once. Each phase should compile before moving to the next. 1. **Project file** — Update TFM, NuGet packages, set `<UseWinUI>true</UseWinUI>` 2. **Data models and business logic** — No UI dependencies, migrate first 3. **MVVM framework** — Replace custom Observable/RelayCommand with CommunityToolkit.Mvvm 4. **Resource strings** — Migrate `.resx` → `.resw`, introduce `ResourceLoaderInstance` 5. **Services and utilities** — Replace `System.Windows` types, async-ify imaging code 6. **ViewModels** — Update Dispatcher usage, binding patterns 7. **Views/Pages** — Starting from leaf pages with fewest dependencies 8. **Main page / shell** — Last, since it depends on everything 9. **App.xaml / startup code** — Merge carefully (do NOT overwrite WinUI 3 boilerplate) 10. **Installer & build pipeline** — Update WiX, signing, build events 11. **Tests** — Adapt for WinUI 3 runtime, async patterns ### Migration Contract: Prohibited Patterns These rules capture human judgment and must be applied consistently across every file. Do NOT deviate. **Architecture prohibitions:** - **Do NOT overwrite `App.xaml` / `App.xaml.cs`** — WinUI 3 has different lifecycle boilerplate. Merge resources and init code into the generated WinUI 3 App class. - **Do NOT create Exe→WinExe `ProjectReference`** — Extract shared code to a Library project. Causes phantom build artifacts. - **Do NOT instantiate services directly** — Use DI and CommunityToolkit.Mvvm patterns. - **Do NOT create a `Window` subclass for every dialog or sub-page** — use `ContentDialog` for in-app dialogs and `Frame`/`Page` navigation for sub-views. Separate `Window` classes are reserved for distinct top-level surfaces (e.g., FancyZones editor, OOBE). - **Do NOT omit `WindowsPackageType=None` and `WindowsAppSDKSelfContained=true`** — Both are mandatory in the csproj for every WinUI 3 module in PowerToys. Without them the app crashes at startup with `COMException: ClassFactory cannot supply requested class` because the WinUI 3 runtime DLLs are not found. - **Do NOT default to a bare `Window`, and do NOT hand-write code-behind for windowing that XAML can express** — For a top-level window in a WinUI 3 module, use `WinUIEx.WindowEx` or an existing PowerToys base derived from it (for example, `TransparentWindow` for transient overlays). `WindowEx` restores WPF-like `Window` members as XAML properties (`MinWidth`/`MinHeight`, `Width`/`Height`, `IsResizable`, `IsMaximizable`/`IsMinimizable`, `IsTitleBarVisible`, `IsAlwaysOnTop`, `IsShownInSwitchers`, `WindowState`, `SystemBackdrop`) plus helpers (`CenterOnScreen()`, `PersistenceId`), so windowing is declared in XAML instead of manual `AppWindow`/`OverlappedPresenter` code-behind. This is the established PowerToys convention across ImageResizer, PowerDisplay, Peek, AdvancedPaste, MeasureTool, ShortcutGuide, Settings, Hosts, FileLocksmith, QuickAccess, and other WinUI 3 modules. Only drop to raw `AppWindow`/presenter code for behavior `WindowEx` does not expose. See [Threading and Window Management → WindowEx](./references/threading-and-windowing.md#prefer-windowex-over-bare-window). **XAML prohibitions:** - **Do NOT use `{DynamicResource}`** — Replace with `{ThemeResource}` (theme-reactive) or `{StaticResource}`. - **Do NOT use `{Binding}` in `Setter.Value`** — Not supported in WinUI 3. Use `{StaticResource}`. - **Do NOT use `{x:Static}`** — Replace with `{x:Bind}`, `x:Uid`, or code-behind. - **Do NOT use `{x:Type}`** — Not supported. Use `x:DataType` for DataTemplate, or code-behind. - **Do NOT use `clr-namespace:`** — Replace with `using:` in all xmlns declarations. - **Do NOT use `Style.Triggers` / `DataTrigger` / `EventTrigger`** — Replace with `VisualStateManager`. - **Do NOT use `MultiBinding`** — Replace with `x:Bind` function binding or computed ViewModel property. - **Do NOT mechanically port WPF `IValueConverter` classes** — Prefer control `VisualState`s, direct `{x:Bind}` Boolean-to-`Visibility` conversion, resources supplied by `XamlControlsResources`, or `CommunityToolkit.WinUI.Converters`. Reuse converter instances and invert them with `ConverterParameter=True` when supported; write a custom converter only for app-specific conversion logic. See [Value Converter Decision Guide](./references/xaml-migration.md#value-converter-decision-guide). - **Do NOT use `Visibility="Hidden"`** — WinUI only has `Visible` and `Collapsed`. Use `Opacity="0"` if layout must be preserved. - **Do NOT use `IsDefault` / `IsCancel`** — Use `AccentButtonStyle` for primary button; handle Enter/Escape in code-behind. - **Do NOT omit `BasedOn` when overriding default styles** — Without it, your style replaces the entire default. Always use `BasedOn="{StaticResource DefaultButtonStyle}"` etc. - **Do NOT omit `XamlControlsResources` as first merged dictionary** — It provides default Fluent styles. Without it, controls have no visual appearance. **Code-behind prohibitions:** - **Do NOT use `Application.Current.Dispatcher`** — Store `DispatcherQueue` in a static field explicitly. - **Do NOT use `Window.Current`** — Not supported. Use a custom `App.Window` static property. - **Do NOT put `DataContext`, `Resources`, or `VisualStateManager` on `Window`** — WinUI 3 `Window` is NOT a `DependencyObject`. Use a root `Page`/`UserControl`/`Grid`. - **Do NOT use tunneling/preview events** (`PreviewMouseDown`, `PreviewKeyDown`) — WinUI has no tunneling. Use bubbling equivalents with `Handled` property or `AddHandler(handledEventsToo: true)`. **Resource prohibitions:** - **Do NOT use `Properties.Resources.MyString`** — Replace with `ResourceLoaderInstance.ResourceLoader.GetString("MyString")`. - **Do NOT initialize `ResourceLoader`-dependent values as static fields** — Wrap in `Lazy<T>` or null-coalescing property. - **Do NOT use `pack://` URIs** — Replace with `ms-appx:///` scheme. ## Quick Reference Tables ### Namespace Mapping | WPF | WinUI 3 | Notes | |-----|---------|-------| | `System.Windows` | `Microsoft.UI.Xaml` | Root namespace | | `System.Windows.Controls` | `Microsoft.UI.Xaml.Controls` | Core controls | | `System.Windows.Controls.Primitives` | `Microsoft.UI.Xaml.Controls.Primitives` | Low-level primitives | | `System.Windows.Media` | `Microsoft.UI.Xaml.Media` | Brushes, transforms | | `System.Windows.Media.Animation` | `Microsoft.UI.Xaml.Media.Animation` | Storyboard, animations | | `System.Windows.Media.Imaging` | `Microsoft.UI.Xaml.Media.Imaging` (UI) / `Windows.Graphics.Imaging` (processing) | Split by purpose | | `System.Windows.Media.Media3D` | **No equivalent** | Use Win2D or Composition APIs | | `System.Windows.Shapes` | `Microsoft.UI.Xaml.Shapes` | Rectangle, Ellipse, Path | | `System.Windows.Input` | `Microsoft.UI.Xaml.Input` | Pointer, keyboard, focus | | `System.Windows.Data` | `Microsoft.UI.Xaml.Data` | Binding, IValueConverter | | `System.Windows.Documents` | `Microsoft.UI.Xaml.Documents` | Limited — RichTextBlock + Paragraph | | `System.Windows.Markup` | `Microsoft.UI.Xaml.Markup` | XAML parsing, markup extensions | | `System.Windows.Automation` | `Microsoft.UI.Xaml.Automation` | Accessibility / UI Automation | | `System.Windows.Navigation` | **No direct equivalent** | Use `Frame.Navigate()` | | `System.Windows.Threading` | `Microsoft.UI.Dispatching` | Dispatcher → DispatcherQueue | | `System.Windows.Interop` | `WinRT.Interop` / `Microsoft.UI.Xaml.Hosting` | HWND interop | ### Control Replacements (No 1:1 Mapping) These WPF controls have no direct counterpart and require a different control or third-party package: | WPF Control | WinUI 3 Replacement | Notes | |-------------|---------------------|-------| | `DataGrid` | [`WinUI.TableView`](https://github.com/w-ahmad/WinUI.TableView) | Community library; the Toolkit `DataGrid` is no longer maintained. Legacy code may still pin v7 `CommunityToolkit.WinUI.UI.Controls.DataGrid` 7.1.2 | | `Ribbon` | `CommandBar` / `NavigationView`, or [Toolkit Labs Ribbon](https://github.com/CommunityToolkit/Labs-Windows/tree/main/components/Ribbon) | No first-party Ribbon in WinUI; Labs component is experimental/partial | | `Menu` / `MenuItem` | `MenuBar` / `MenuBarItem` / `MenuFlyout` | `MenuBar` for classic menu, `MenuFlyout` for context | | `ContextMenu` | `MenuFlyout` | Assign to `ContextFlyout` property | | `ToolBar` / `ToolBarTray` | `CommandBar` + `AppBarButton` | | | `StatusBar` | Custom `Grid`/`StackPanel` or `InfoBar` | No StatusBar control | | `TabControl` | `TabView` or `NavigationView` (top mode) | `TabView` for closeable tabs | | `DocumentViewer` | `WebView2` | Render PDFs/XPS inside WebView2 | | `FlowDocument` | `RichTextBlock` | Partial replacement only | | `RichTextBox` | `RichEditBox` | Rich text editing | | `GroupBox` | `Expander` (built-in) or `HeaderedContentControl` (Toolkit) | See [Layout & Header Controls from CommunityToolkit.WinUI](#layout--header-controls-from-communitytoolkitwinui) below | | `Label` | `TextBlock` | WPF `Label` is a `ContentControl`; use `TextBlock` + `AccessKey` | | `TreeView` | `TreeView` (native) | Available natively, but data binding model differs significantly | | `MessageBox` | `ContentDialog` | Must set `XamlRoot` before `ShowAsync()` | | `MediaElement` | `MediaPlayerElement` | Different API | | `AccessText` | Not available | Use `AccessKey` property on target control | ### Layout & Header Controls from CommunityToolkit.WinUI These WPF controls have no built-in WinUI 3 equivalent — install the corresponding CommunityToolkit package. **The NuGet package id and the XAML namespace differ intentionally**: package names end in `.Primitives` / `.HeaderedControls`, but the registered XAML namespace is the shorter `CommunityToolkit.WinUI.Controls` (confirmed in the [official Microsoft Q&A](https://learn.microsoft.com/en-us/answers/questions/5746230/why-does-communitytoolkit-uwp-controls-primitive-u)). | WPF Control | WinUI 3 Replacement | NuGet Package | XAML Namespace | |-------------|---------------------|---------------|----------------| | `WrapPanel` | `WrapPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` | | `UniformGrid` | `UniformGrid` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` | | `DockPanel` | `DockPanel` | `CommunityToolkit.WinUI.Controls.Primitives` | `using:CommunityToolkit.WinUI.Controls` | | `GroupBox` (alt.) | `HeaderedContentControl` | `CommunityToolkit.WinUI.Controls.HeaderedControls` | `using:CommunityToolkit.WinUI.Controls` | ### No Equivalent — Requires Architectural Rework These WPF features have no WinUI counterpart and require redesign, not find-and-replace: | WPF Feature | WinUI 3 Replacement Strategy | |-------------|------------------------------| | `Style.Triggers` / `DataTrigger` | `VisualStateManager` with `StateTrigger` — see [XAML Migration](./references/xaml-migration.md) | | `MultiBinding` | `x:Bind` function binding: `{x:Bind local:Converters.Format(VM.A, VM.B), Mode=OneWay}` | | `RoutedUICommand` / `CommandBinding` | `ICommand` / `[RelayCommand]` from CommunityToolkit.Mvvm. WinUI also has `StandardUICommand` / `XamlUICommand` for platform commands. | | `AdornerLayer` / `Adorner` | Depends on use case: `TeachingTip`/`InfoBar` (validation), `Popup` (overlays), `PlaceholderText` (watermarks), Canvas overlay (decorations) | | `Visibility.Hidden` | `Opacity="0"` with `Visibility="Visible"` (preserves layout space) | | `Window.Resources` / `Window.DataContext` | Move to root `Grid.Resources` / root `Page`/`UserControl` — WinUI `Window` is NOT a DependencyObject | | Tunneling events (`Preview*`) | Use bubbling equivalents + `Handled` property or `AddHandler(handledEventsToo: true)` | ### Critical API Replacements | WPF | WinUI 3 | Notes | |-----|---------|-------| | `Dispatcher.Invoke()` | `DispatcherQueue.TryEnqueue()` | Different return type (`bool`), async by default | | `Dispatcher.CheckAccess()` | `DispatcherQueue.HasThreadAccess` | Property vs method |
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기