wpf-to-winui3-migration
- Repo stars 133,756
- License Complete terms in LICENSE.txt
- Author updated Live
- Author repo PowerToys
- Domain
- Engineering
- Compatible agents
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- Trust score
- 94 / 100 · audit passed
- Author / version / license
- @microsoft · Complete terms in LICENSE.txt
- Token usage
- Lean
- Setup complexity
- Guided setup
- External API key
- Not required
- Operating systems
- Windows
- Runtime requirements
- No special requirements
- Permissions
-
- Read-only
- Write / modify
- Shell exec
- Network behavior
- Local-only
- Install commands
- 26 variants
Profile is derived at build time from SKILL.md and install vectors. Subject to drift from author intent.
Heads up: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: wpf-to-winui3-migration
description: Guide for migrating PowerToys modules from WPF to WinUI 3 (Windows App SDK). Use when asked to m…
category: engineering
runtime: no special runtime
---
# wpf-to-winui3-migration output preview
## PART A: Task fit
- Use case: 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..
- Inputs: target material, constraints, expected output, and acceptance criteria.
- Evidence boundary: follow “When to Use This Skill / Prerequisites / Migration Strategy” and do not present inference as author intent.
## PART B: Execution result
- **01** The card summarizes the use case; runtime output centers on “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.”.
- **02** When the source has headings, the agent prioritizes “When to Use This Skill / Prerequisites / Migration Strategy” so the result follows the author’s structure.
- **03** Typical output includes task judgment, concrete steps, required commands or file edits, validation, and follow-up options.
- **04** Risk context follows the fingerprint: read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
## Running Rules
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding scope.
- Return the result, validation criteria, and next iteration options. The source does not require a stable slash command. After installation, invoke the skill by name and describe the task.
Name target files or source material, expected output, forbidden changes, and whether network or shell access is allowed. Permission fingerprint: read files, write/modify files, run shell commands.
Start with a small task and check whether the result follows “When to Use This Skill / Prerequisites / Migration Strategy”. Inspect diffs, logs, previews, or tests before expanding scope.
Confirm the final output includes a concrete result, evidence, and next action. If it stays generic, tighten inputs, boundaries, and acceptance criteria.
---
name: wpf-to-winui3-migration
description: Guide for migrating PowerToys modules from WPF to WinUI 3 (Windows App SDK). Use when asked to m…
category: engineering
source: microsoft/PowerToys
---
# wpf-to-winui3-migration
## When to use
- Guide for migrating PowerToys modules from WPF to WinUI 3 (Windows App SDK). Use when asked to migrate WPF code, conve…
- Use it when the task has clear inputs, repeatable steps, and validation criteria.
## What to provide
- Target material, scope, expected result, and forbidden changes.
- Whether network, commands, file writes, or external services are allowed.
## Execution rules
- Organize steps around “When to Use This Skill / Prerequisites / Migration Strategy” and keep inference separate from source facts.
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding the task.
## Output requirements
- Return the deliverable, key evidence, validation method, and next action.
- Mark missing information as unknown; do not invent commands, platforms, or dependencies. The author source anchors workflow facts; repository files anchor sources and commands; Fluxly only adds fit, limitations, and quality judgment.
skill "wpf-to-winui3-migration" {
input -> user goal + target files + boundaries + acceptance criteria
context -> When to Use This Skill / Prerequisites / Migration Strategy
rules -> SKILL.md triggers / order / output contract
runtime -> no special runtime | read files, write/modify files, run shell commands | mostly runs locally
guardrails -> usually needs no extra API key + small-sample validation + diff/log review
output -> copyable result + checklist + next iteration
} 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.Windowsnamespaces withMicrosoft.UI.Xaml - Migrate
Dispatcherusage toDispatcherQueue - Migrate custom
Observable/RelayCommandto CommunityToolkit.Mvvm source generators - Replace WPF-UI (Lepo) controls with native WinUI 3 controls
- Convert imaging code from
System.Windows.Media.ImagingtoWindows.Graphics.Imaging - Handle WPF
Windowvs WinUIWindowdifferences (sizing, positioning, SizeToContent) - Migrate resource files from
.resxto.reswwithResourceLoader - 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.0TFM - Windows 10 1803+ (April 2018 Update or newer)
Migration Strategy
Recommended Order
- Project file — Update TFM, NuGet packages, set
<UseWinUI>true</UseWinUI> - Data models and business logic — No UI dependencies, migrate first
- MVVM framework — Replace custom Observable/RelayCommand with CommunityToolkit.Mvvm
- Resource strings — Migrate
.resx→.resw, introduceResourceLoaderInstance - Services and utilities — Replace
System.Windowstypes, async-ify imaging code - ViewModels — Update Dispatcher usage, binding patterns
- Views/Pages — Starting from leaf pages with fewest dependencies
- Main page / shell — Last, since it depends on everything
- App.xaml / startup code — Merge carefully (do NOT overwrite WinUI 3 boilerplate)
- Installer & build pipeline — Update WiX, signing, build events
- Tests — Adapt for WinUI 3 runtime, async patterns
Key Principles
- Do NOT overwrite
App.xaml/App.xaml.cs— WinUI 3 has different application lifecycle boilerplate. Merge your resources and initialization code into the generated WinUI 3 App class. - Do NOT create Exe→WinExe
ProjectReference— Extract shared code to a Library project. This causes phantom build artifacts. - Use
Lazy<T>for resource-dependent statics —ResourceLoaderis not available at class-load time in all contexts.
Quick Reference Tables
Namespace Mapping
| WPF | WinUI 3 |
|---|---|
System.Windows |
Microsoft.UI.Xaml |
System.Windows.Controls |
Microsoft.UI.Xaml.Controls |
System.Windows.Media |
Microsoft.UI.Xaml.Media |
System.Windows.Media.Imaging |
Microsoft.UI.Xaml.Media.Imaging (UI) / Windows.Graphics.Imaging (processing) |
System.Windows.Input |
Microsoft.UI.Xaml.Input |
System.Windows.Data |
Microsoft.UI.Xaml.Data |
System.Windows.Threading |
Microsoft.UI.Dispatching |
System.Windows.Interop |
WinRT.Interop |
Critical API Replacements
| WPF | WinUI 3 | Notes |
|---|---|---|
Dispatcher.Invoke() |
DispatcherQueue.TryEnqueue() |
Different return type (bool) |
Dispatcher.CheckAccess() |
DispatcherQueue.HasThreadAccess |
Property vs method |
Application.Current.Dispatcher |
Store DispatcherQueue in static field |
See Threading |
MessageBox.Show() |
ContentDialog |
Must set XamlRoot |
DynamicResource |
ThemeResource |
Theme-reactive only |
clr-namespace: |
using: |
XAML namespace prefix |
{x:Static props:Resources.Key} |
x:Uid or ResourceLoader.GetString() |
.resx → .resw |
DataType="{x:Type m:Foo}" |
Remove or use code-behind | x:Type not supported |
Properties.Resources.MyString |
ResourceLoaderInstance.ResourceLoader.GetString("MyString") |
Lazy-init pattern |
Application.Current.MainWindow |
Custom App.Window static property |
Must track manually |
SizeToContent="Height" |
Custom SizeToContent() via AppWindow.Resize() |
See Windowing |
MouseLeftButtonDown |
PointerPressed |
Mouse → Pointer events |
Pack URI (pack://...) |
ms-appx:/// |
Resource URI scheme |
Observable (custom base) |
ObservableObject + [ObservableProperty] |
CommunityToolkit.Mvvm |
RelayCommand (custom) |
[RelayCommand] source generator |
CommunityToolkit.Mvvm |
JpegBitmapEncoder |
BitmapEncoder.CreateAsync(JpegEncoderId, stream) |
Async, unified API |
encoder.QualityLevel = 85 |
BitmapPropertySet { "ImageQuality", 0.85f } |
int 1-100 → float 0-1 |
NuGet Package Migration
| WPF | WinUI 3 |
|---|---|
Microsoft.Xaml.Behaviors.Wpf |
Microsoft.Xaml.Behaviors.WinUI.Managed |
WPF-UI (Lepo) |
Remove — use native WinUI 3 controls |
CommunityToolkit.Mvvm |
CommunityToolkit.Mvvm (same) |
Microsoft.Toolkit.Wpf.* |
CommunityToolkit.WinUI.* |
| (none) | Microsoft.WindowsAppSDK |
| (none) | Microsoft.Windows.SDK.BuildTools |
| (none) | WinUIEx (optional, for window helpers) |
| (none) | CommunityToolkit.WinUI.Converters |
XAML Syntax Changes
| WPF | WinUI 3 |
|---|---|
xmlns:local="clr-namespace:MyApp" |
xmlns:local="using:MyApp" |
{DynamicResource Key} |
{ThemeResource Key} |
{x:Static Type.Member} |
{x:Bind} or code-behind |
{x:Type local:MyType} |
Not supported |
<Style.Triggers> / <DataTrigger> |
VisualStateManager |
{Binding} in Setter.Value |
Not supported — use StaticResource |
Content="{x:Static p:Resources.Cancel}" |
x:Uid="Cancel" with .Content in .resw |
<ui:FluentWindow> / <ui:Button> (WPF-UI) |
Native <Window> / <Button> |
<ui:NumberBox> / <ui:ProgressRing> (WPF-UI) |
Native <NumberBox> / <ProgressRing> |
BasedOn="{StaticResource {x:Type ui:Button}}" |
BasedOn="{StaticResource DefaultButtonStyle}" |
IsDefault="True" / IsCancel="True" |
Style="{StaticResource AccentButtonStyle}" / handle via KeyDown |
<AccessText> |
Not available — use AccessKey property |
<behaviors:Interaction.Triggers> |
Migrate to code-behind or WinUI behaviors |
Detailed Reference Docs
Read only the section relevant to your current task:
- Namespace and API Mapping — Full type mapping, NuGet changes, project file, CsWinRT interop
- XAML Migration Guide — XAML syntax, WPF-UI removal, markup extensions, styles, resources, data binding
- Threading and Window Management — Dispatcher, DispatcherQueue, SizeToContent, AppWindow, HWND interop, custom entry point
- Imaging API Migration — BitmapEncoder/Decoder, SoftwareBitmap, CodecHelper, async patterns, int→uint
- PowerToys-Specific Patterns — MVVM migration, ResourceLoader, Lazy init, installer, signing, test adaptation, build pipeline
Common Pitfalls (from ImageResizer migration)
| Pitfall | Solution |
|---|---|
ContentDialog throws "does not have a XamlRoot" |
Set dialog.XamlRoot = this.Content.XamlRoot before ShowAsync() |
FilePicker throws error in desktop app |
Call WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd) |
Window.Dispatcher returns null |
Use Window.DispatcherQueue instead |
Resources on Window element not found |
Move resources to root layout container (Grid.Resources) |
VisualStateManager on Window fails |
Use UserControl or Page inside the Window |
Satellite assembly installer errors (WIX0103) |
Remove .resources.dll refs from Resources.wxs; WinUI 3 uses .pri |
Phantom .exe/.deps.json in root output dir |
Avoid Exe→WinExe ProjectReference; use Library project |
ResourceLoader crash at static init |
Wrap in Lazy<T> or null-coalescing property — see Lazy Init |
SizeToContent not available |
Implement manual content measurement + AppWindow.Resize() with DPI scaling |
x:Bind default mode is OneTime |
Explicitly set Mode=OneWay or Mode=TwoWay |
DynamicResource / x:Static not compiling |
Replace with ThemeResource / ResourceLoader or x:Uid |
IValueConverter.Convert signature mismatch |
Last param: CultureInfo → string (language tag) |
| Test project can't resolve WPF types | Add <UseWPF>true</UseWPF> temporarily; remove after imaging migration |
Pixel dimension type mismatch (int vs uint) |
WinRT uses uint for pixel sizes — add u suffix in test assertions |
$(SolutionDir) empty in standalone project build |
Use $(MSBuildThisFileDirectory) with relative paths instead |
| JPEG quality value wrong after migration | WPF: int 1-100; WinRT: float 0.0-1.0 |
| MSIX packaging fails in PreBuildEvent | Move to PostBuildEvent; artifacts not ready at PreBuild time |
| RC file icon path with forward slashes | Use double-backslash escaping: ..\\ui\\Assets\\icon.ico |
Troubleshooting
| Issue | Solution |
|---|---|
| Build fails after namespace rename | Check for lingering System.Windows usings; some types have no direct equivalent |
Missing PresentationCore.dll at runtime |
Ensure ALL imaging code uses Windows.Graphics.Imaging, not System.Windows.Media.Imaging |
DataContext not working on Window |
WinUI 3 Window is not a DependencyObject; use a root Page or UserControl |
| XAML designer not available | WinUI 3 does not support XAML Designer; use Hot Reload instead |
| NuGet restore failures | Run build-essentials.cmd after adding Microsoft.WindowsAppSDK package |
Parallel.ForEach compilation error |
Migrate to Parallel.ForEachAsync for async imaging operations |
| Signing check fails on leaked artifacts | Run generateAllFileComponents.ps1; verify only WinUI3Apps\\ paths in signing config |
Decide Fit First
Design Intent
How To Use It
Boundaries And Review