Babysitter winui3-migration-helper
Assist migration from WPF to WinUI 3 / Windows App SDK with code transformation and compatibility guidance
install
source · Clone the upstream repo
git clone https://github.com/a5c-ai/babysitter
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/a5c-ai/babysitter "$T" && mkdir -p ~/.claude/skills && cp -r "$T/library/specializations/desktop-development/skills/winui3-migration-helper" ~/.claude/skills/a5c-ai-babysitter-winui3-migration-helper && rm -rf "$T"
manifest:
library/specializations/desktop-development/skills/winui3-migration-helper/SKILL.mdsource content
winui3-migration-helper
Assist migration from WPF to WinUI 3 / Windows App SDK. This skill analyzes WPF applications and provides migration paths, code transformations, and compatibility guidance for modernizing to WinUI 3.
Capabilities
- Analyze WPF codebase for migration compatibility
- Identify API differences and required changes
- Generate WinUI 3 project structure
- Transform XAML syntax differences
- Migrate code-behind to modern patterns
- Handle namespace and type mappings
- Configure Windows App SDK dependencies
- Generate migration task list with priorities
Input Schema
{ "type": "object", "properties": { "projectPath": { "type": "string", "description": "Path to the WPF project" }, "migrationStrategy": { "enum": ["full", "incremental", "analysis-only"], "default": "analysis-only" }, "targetSdk": { "type": "string", "default": "1.5", "description": "Target Windows App SDK version" }, "preserveWpfComponents": { "type": "array", "items": { "type": "string" }, "description": "WPF components to keep via XAML Islands" }, "generateReport": { "type": "boolean", "default": true } }, "required": ["projectPath"] }
Output Schema
{ "type": "object", "properties": { "success": { "type": "boolean" }, "compatibility": { "type": "object", "properties": { "score": { "type": "number" }, "blockers": { "type": "array" }, "warnings": { "type": "array" } } }, "migrationTasks": { "type": "array", "items": { "type": "object", "properties": { "category": { "type": "string" }, "task": { "type": "string" }, "effort": { "enum": ["low", "medium", "high"] }, "automated": { "type": "boolean" } } } }, "codeTransformations": { "type": "array", "items": { "type": "object", "properties": { "file": { "type": "string" }, "original": { "type": "string" }, "transformed": { "type": "string" } } } } }, "required": ["success"] }
Key Differences
Namespace Changes
| WPF | WinUI 3 |
|---|---|
| |
| |
| |
| |
| |
XAML Namespace
<!-- WPF --> <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- WinUI 3 --> <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyApp">
Window Creation
// WPF public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } // WinUI 3 public sealed partial class MainWindow : Window { public MainWindow() { this.InitializeComponent(); // WinUI 3: No automatic window sizing this.SetWindowSize(800, 600); } private void SetWindowSize(int width, int height) { var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this); var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd); var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId); appWindow.Resize(new Windows.Graphics.SizeInt32(width, height)); } }
Common Control Differences
<!-- WPF: DataGrid --> <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Name" Binding="{Binding Name}"/> </DataGrid.Columns> </DataGrid> <!-- WinUI 3: Community Toolkit DataGrid --> <toolkit:DataGrid ItemsSource="{x:Bind ViewModel.Items}" AutoGenerateColumns="False"> <toolkit:DataGrid.Columns> <toolkit:DataGridTextColumn Header="Name" Binding="{Binding Name}"/> </toolkit:DataGrid.Columns> </toolkit:DataGrid>
Binding Syntax
<!-- WPF: Classic binding --> <TextBlock Text="{Binding Name}"/> <Button Command="{Binding SaveCommand}"/> <!-- WinUI 3: x:Bind (compiled bindings, recommended) --> <TextBlock Text="{x:Bind ViewModel.Name, Mode=OneWay}"/> <Button Command="{x:Bind ViewModel.SaveCommand}"/> <!-- WinUI 3: Classic binding still works --> <TextBlock Text="{Binding Name}"/>
Resource Dictionaries
<!-- WPF --> <ResourceDictionary> <SolidColorBrush x:Key="AccentBrush" Color="#0078D4"/> <Style TargetType="Button"> <Setter Property="Background" Value="{StaticResource AccentBrush}"/> </Style> </ResourceDictionary> <!-- WinUI 3 --> <ResourceDictionary> <SolidColorBrush x:Key="AccentBrush" Color="#0078D4"/> <Style TargetType="Button"> <Setter Property="Background" Value="{StaticResource AccentBrush}"/> </Style> </ResourceDictionary> <!-- Note: Largely compatible, but some default styles differ -->
Project Configuration
WPF .csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows</TargetFramework> <UseWPF>true</UseWPF> </PropertyGroup> </Project>
WinUI 3 .csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion> <UseWinUI>true</UseWinUI> <WindowsPackageType>None</WindowsPackageType> <Platforms>x64;x86;arm64</Platforms> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000"/> <PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.756"/> </ItemGroup> </Project>
Migration Blockers
Not Available in WinUI 3
| Feature | Alternative |
|---|---|
| NavigationWindow | Custom navigation with Frame |
| DataGrid (built-in) | Community Toolkit DataGrid |
| RichTextBox | RichEditBox |
| WebBrowser | WebView2 |
| WindowsFormsHost | Not available (use XAML Islands in reverse) |
| System tray icons | Win32 APIs directly |
Requires Changes
| WPF Feature | WinUI 3 Approach |
|---|---|
| Application.Current.Dispatcher | DispatcherQueue |
| RoutedUICommand | ICommand implementation |
| Triggers in styles | VisualStateManager |
| Effect (blur, etc.) | Composition APIs |
| DynamicResource | StaticResource (mostly) |
Code Transformations
Dispatcher
// WPF Application.Current.Dispatcher.Invoke(() => { // UI code }); // WinUI 3 DispatcherQueue.GetForCurrentThread().TryEnqueue(() => { // UI code });
Triggers to VisualStateManager
<!-- WPF: Style Trigger --> <Style TargetType="Button"> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="LightBlue"/> </Trigger> </Style.Triggers> </Style> <!-- WinUI 3: VisualStateManager --> <Style TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="RootBorder" Background="{TemplateBinding Background}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="PointerOver"> <Storyboard> <ColorAnimation Storyboard.TargetName="RootBorder" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="LightBlue"/> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <ContentPresenter/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
Best Practices
- Start with analysis: Understand scope before migrating
- Migrate incrementally: Move feature by feature
- Use x:Bind: Better performance than classic binding
- Embrace WinUI styles: Don't fight the defaults
- Test on Windows 10 min version: Verify compatibility
- Consider XAML Islands: For gradual migration
Related Skills
- MVVM pattern (works in both)wpf-mvvm-scaffold
- WinUI 3 packagingmsix-package-generator
process - Full migration workflowdesktop-migration
Related Agents
- WPF expertisewpf-dotnet-expert
- Migration planningdesktop-migration-strategist