WinUI Is Windows' Official Platform Now: Should You Migrate?
Microsoft finally picked a lane for native Windows development. Here's what changed, what incremental adoption actually looks like in code, and whether your existing WPF or WinForms app should follow.
Windows developers have heard "this is the framework" before. Win32, then WPF, then UWP, then WinUI 3 — each arriving with a keynote promising it was the one to build on, followed by years of the previous one still quietly running most of the actual software people use. So when Microsoft used Build 2026 to formally name WinUI the official native production platform for Windows apps, the reasonable reaction isn't excitement. It's "we'll see."
Here's what's actually different this time, and what I'd genuinely do if I were maintaining a WPF or WinForms app right now.
In this post:
- What changed at Build 2026
- What the WinUI agent plugin actually does
- What incremental adoption looks like in code
- Where WPF and WinForms still make sense
- A migration case worth walking through
- My take
What Actually Changed at Build 2026
The headline isn't a new feature — it's a declaration. WinUI is now positioned as the single, official path for native Windows development, rather than one option among several Microsoft was quietly hedging across. Alongside that declaration came real tooling investment, not just a slogan:
- Official WinUI project templates for the .NET CLI, so getting started no longer requires Visual Studio and a specific set of IDE-installed templates — a genuine parity gap with ASP.NET Core, MAUI and Blazor that's now closed.
- A new WinUI visual designer in Visual Studio 2026, aiming to match the old WPF designer's drag-and-drop ease while generating clean, modern XAML underneath.
- Hot Reload working across all project types, including those using .NET Native ahead-of-time compilation.
- A revamped data-binding debugging experience, pinpointing the offending property and value rather than leaving you to guess which binding silently failed.
- AI-assisted tooling, including the WinUI agent plugin — which is the piece most worth understanding properly, so it gets its own section below.
The signal I'd weight most heavily, though, wasn't in the developer tooling track at all. Microsoft also confirmed it is rebuilding parts of the Windows 11 shell — Start menu components and core app infrastructure — in native WinUI, replacing remnants of Win32 and XAML Islands.
That matters more than any announcement about templates. A platform team that ships its own most-used surfaces on the framework it's recommending feels the framework's problems on the same schedule you do. Every previous Windows UI pivot came with Microsoft's own flagship experiences conspicuously built on something else. This one doesn't. It's the first version of this pitch that's falsifiable: if WinUI turns out to be a dead end, Microsoft's Start menu goes down with your app.
What the WinUI Agent Plugin Actually Does
This got a passing mention in most Build coverage, which undersells it. It's the most concrete thing shipped in this cycle, and it's worth understanding what problem it solves.
The problem is specific and a bit unusual: AI coding agents struggle with WinUI because the internet is full of incorrect Windows code. Training data contains vastly more historical Win32, WinForms and UWP samples than current WinUI 3 material, so a general-purpose agent asked for a Windows app will confidently produce deprecated APIs, mix UWP-era patterns into WinUI projects, or miss the packaged-execution model entirely. Then it stops before running the thing, so nobody finds out.
The plugin fixes this by injecting explicit WinUI 3 rules as custom instructions that override the agent's training-data defaults. Concretely, it ships:
- A dedicated
winui-devagent plus eight specialised skills covering the loop developers actually run dozens of times a day: scaffold, Build, run, test, package, migrate. - A
winui-setupskill that installs prerequisites — thewinappCLI, .NET SDK, WinUI templates, Developer Mode — so machine setup isn't the first thing that derails you. - A
winui-wpf-migrationskill aimed specifically at porting WPF apps: updating XAML namespaces, mapping controls, restructuring the project. - Failure-mode awareness. The skills are built to recognise common failures that get generic agents stuck in retry loops and steer toward patterns that actually work.
The efficiency claim is the eye-catching part: around 70% fewer tokens than a generic agent for equivalent work. It achieves that with a local native-AOT CLI that indexes documentation and UI scenarios, so the agent looks things up rather than carrying enormous context on every turn.
Two practical notes. It works with the GitHub Copilot CLI and Claude Code, but not VS Code Copilot Chat, which trips people up. And the registry IDs differ between the two:
# GitHub Copilot CLI
/plugin install winui@awesome-copilot
/winui:winui-setup
# Claude Code
claude plugin marketplace add microsoft/win-dev-skills
claude plugin install winui@win-dev-skills
Then prefix requests with @winui-dev.
I'd treat the migration skill as a triage tool rather than a migration tool — more on that below.
What Incremental Adoption Actually Looks Like
Everyone describing migration says "you can do it gradually." Far fewer show what that means, which matters, because the shape of the code determines how much risk you're taking on.
The mechanism is XAML Islands, via DesktopWindowXamlSource in Microsoft.UI.Xaml.Hosting. It's been production-stable since Windows App SDK 1.6, and it lets a WPF or WinForms app host anything deriving from Microsoft.UI.Xaml.UIElement. In WPF, the idiomatic wrapper is an HwndHost subclass:
using System;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using Microsoft.UI;
using Microsoft.UI.Content;
using Microsoft.UI.Xaml.Hosting;
using WinUI = Microsoft.UI.Xaml.Controls;
public sealed class WinUIHost : HwndHost
{
private DesktopWindowXamlSource? _xamlSource;
private static WindowsXamlManager? _xamlManager;
protected override HandleRef BuildWindowCore(HandleRef hwndParent)
{
// One per UI thread. Holds the reference to the XAML framework.
_xamlManager ??= WindowsXamlManager.InitializeForCurrentThread();
var parentId = Win32Interop.GetWindowIdFromWindow(hwndParent.Handle);
_xamlSource = new DesktopWindowXamlSource();
_xamlSource.Initialize(parentId);
// Without this the island renders at zero size and you see nothing.
_xamlSource.SiteBridge.ResizePolicy =
ContentSizePolicy.ResizeContentToParentWindow;
_xamlSource.Content = BuildSettingsPanel();
_xamlSource.SiteBridge.Show();
var childHwnd = Win32Interop.GetWindowFromWindowId(
_xamlSource.SiteBridge.WindowId);
return new HandleRef(this, childHwnd);
}
private static WinUI.StackPanel BuildSettingsPanel()
{
var toggle = new WinUI.ToggleSwitch { Header = "Enable telemetry" };
toggle.Toggled += (s, e) => { /* your existing view model */ };
var panel = new WinUI.StackPanel { Spacing = 12 };
panel.Children.Add(toggle);
return panel;
}
protected override void DestroyWindowCore(HandleRef hwnd)
{
_xamlSource?.Dispose();
_xamlSource = null;
}
}
Then it drops into existing WPF markup like any other control:
<Window x:Class="LegacyApp.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LegacyApp">
<DockPanel>
<TextBlock DockPanel.Dock="Top" Text="Settings" FontSize="20" />
<local:WinUIHost />
</DockPanel>
</Window>
Two things are worth noticing about that code, and neither is the part that works.
The ResizePolicy line is a trap that has cost people afternoons. The island's internal child window defaults to zero width and height. Skip that line and your WinUI content is present, alive, correctly constructed — and completely invisible. There's no error. This is the single most common "XAML Islands doesn't work" report, and it's a one-line fix.
Focus does not cross the boundary for free. In pure WPF, you never think about tab traversal. Here, the WPF host and the XAML island maintain separate focus trees, and moving between them requires handling TakeFocusRequested on the island and wiring it back to WPF's focus system. I've left that out above to keep the example readable, which is precisely how it gets left out of real code too. If your app has any keyboard-driven workflow—and line-of-business apps invariably do—this isn't optional polish. It's the feature.
That's the honest shape of incremental adoption: the rendering works almost immediately, and the integration work is all in the seams.
Where WPF and WinForms Still Make Sense
I wouldn't treat "official platform" as "immediately deprecated." A few honest scenarios where staying put is still the right call:
- A stable, working app with no pressing UI needs. If it works, ships, and your users aren't asking for anything WinUI specifically enables, migrating is effort spent following an announcement rather than solving a problem.
- Deep reliance on mature third-party WPF/WinForms component libraries. WinUI's component ecosystem has grown, but it isn't fully on par with WPF/WinForms everywhere, and trading a mature, well-supported control for a rougher WinUI equivalent isn't a win.
- Small teams without migration bandwidth. Microsoft's own messaging acknowledges migration still requires careful planning. The AI tooling helps identify issues; it doesn't remove the need for engineering judgement on each one.
- Apps that must run on older Windows. WinUI 3 targets Windows 10 1809 and later. If you have customers on anything earlier — and in regulated industries, healthcare and manufacturing, you very often do — this ends the conversation before it starts.
A Migration Case Worth Walking Through: DPI and Multi-Monitor
"Better DPI handling" is the most cited technical reason to move, and also the one most likely to be wrong for your specific app. It's worth walking through properly, because the diagnosis matters more than the framework.
The scenario. A line-of-business WPF app, originally written around 2015, now used on laptops that dock to external monitors. Users report that the app looks fine on the laptop display, then goes soft and slightly wrong after docking — text blurry, a toolbar that doesn't quite line up, a chart control that renders at the wrong scale until the window is resized. Undock and it's fine again. Classic mixed-DPI symptoms.
Why this happens. WPF has been genuinely capable here since .NET Framework 4.6.2 and .NET Core 3.0, which added Per-Monitor DPI Awareness V2. Pure WPF content re-renders correctly when a window moves between displays with different scale factors. So if your app is entirely WPF and it's still blurring, the most likely explanation is that it never opted into PerMonitorV2 in its manifest — which is a configuration fix, not a migration.
The harder case is hosted content. WindowsFormsHost, HwndHostEmbedded browser controls, third-party controls wrapping native HWNDs — none of these automatically participate in WPF's DPI handling. The system bitmap-scales them, which is exactly the soft, slightly wrong look users describe. WinUI 3, built for high-DPI displays from the start rather than retrofitted, doesn't carry this history.
And here's the catch that decides it. If your blurriness comes from a hosted legacy control, migrating the shell to WinUI doesn't fix that control. You've moved the framework boundary, not removed it — and if you adopt WinUI incrementally via XAML Islands, you've arguably added one. The legacy component is still a native HWND being scaled by the system, and it will look exactly as bad inside WinUI as it did inside WPF.
So the sequence I'd actually follow:
- Reproduce it on a genuinely mixed-DPI setup — a 150% laptop panel and a 100% external monitor, and test the drag between them, not just the end states. Docking transitions are where this breaks.
- Check the manifest first. If PerMonitorV2 isn't declared, declare it and retest. This is a config change, and it resolves a surprising share of cases.
- Isolate which elements are wrong. If pure WPF content is now crisp and only specific hosted controls are soft, you've found your problem, and it isn't WPF.
- Then decide. If the culprit is a third-party control, ask whether a WinUI-native replacement exists—not whether WinUI is better in the abstract. If it doesn't, migrating buys you nothing on this axis.
That's a genuine migration case when the answer comes back "yes, and there's a good replacement." It's also, more often than people expect, a case for a manifest change and an afternoon's testing.
Where Else Migrating Is Worth Considering
- New projects, unambiguously. Starting fresh on WPF or WinForms in 2026 is a harder case to make than it was a year ago — you'd be adopting a framework Microsoft has explicitly deprioritised for new work.
- Apps needing modern Fluent design or tighter integration with newer Windows APIs. With the shell itself moving to WinUI, integration points like taskbar behaviour and notification handling will be designed WinUI-first.
- Teams is already planning a UI refresh. If a redesign was on the roadmap regardless, doing it on WinUI now makes more sense than it did before Build 2026.
- Apps where memory footprint is a real complaint. Microsoft is making specific claims here, and it's the sort of thing users notice even when they can't name it.
My Take
I'd treat this the way I'd treat any "the platform team finally picked a direction" announcement: real signal, not yet proof. But I want to be more specific than the usual wait-and-see, because I think the framing itself is slightly off.
Migration is the wrong default question. Having worked across iOS, macOS, Android, Linux, and Windows, what strikes me about Windows framework debates is how they're always framed as a replacement. Apple shipped SwiftUI in 2019 and, seven years on, UIKit is neither dead nor deprecated — large apps run both, permanently, and nobody experiences that as failure. The expected posture is coexistence and interop. Windows developers, by contrast, keep being handed a migration narrative, which makes every announcement feel like a threat to working software. XAML Islands being production-stable is the genuinely important development here, and it's the one getting the least attention, because it's the piece that makes coexistence a legitimate end state rather than a transitional embarrassment.
The dogfooding is worth more than the declaration. I'd have discounted this announcement entirely if Microsoft weren't rebuilding the Start menu on it. A framework whose primary vendor ships their own most-scrutinised surface on it has a feedback loop that a framework used only by third parties does not. That's the part I'd watch — not what's said at next year's Build, but whether shell components stay on WinUI when they get hard.
Cheap migration is not correct migration, and I'd be careful here. The agent plugin is a real advance, and the 70% token reduction is a meaningful efficiency claim. But efficiency isn't accuracy, and a tool that makes it fast to produce a WinUI version of your app also makes it fast to produce a plausible one. The failure mode isn't code that doesn't compile — you'd catch that. It's a converted view that renders correctly, passes a smoke test, and quietly loses a keyboard shortcut, an accessibility label, or a validation rule that lived in a converter someone wrote in 2017. Use it to enumerate what needs attention. Don't use it to decide what's done.
Which brings me to the part nobody budgets for: testing the seams. If you adopt incrementally, every island boundary is a new integration surface — focus traversal, keyboard navigation, screen reader announcement order, input routing, DPI transitions across the boundary. None of it is covered by your existing WPF UI tests, because those tests don't know the boundary exists. Automation frameworks often struggle to traverse it at all. My honest estimate is that the boundary testing costs more than the port for any app with serious keyboard or accessibility requirements, and it's the line item that turns a two-week estimate into two months. Please budget for it explicitly, or the hybrid approach will ship an app that looks modern but is harder to use.
And the user-facing test is the only one that settles it. Nobody outside your team has ever cared which UI framework an app uses. They notice startup time, memory, whether text is crisp when they dock, whether the window behaves when they snap it, whether keyboard focus goes where they expect. If you can't name which of those a migration improves for your users, you don't have a migration case — you have an announcement you read.
If you're maintaining something stable: keep it stable, and revisit WinUI the next time you have a real reason to touch the UI layer anyway. If you're starting something new, or already had a rewrite planned: this is a genuinely good moment to default to WinUI rather than second-guessing it.
The real test isn't this announcement — it's whether Microsoft is still saying the same thing in two years, and whether the Start menu is still built on it.