Migration WPF to WinUI
Key Takeaways
  • WPF's System.Windows.* namespaces map to Microsoft.UI.Xaml.* in WinUI, but not every class has a 1:1 equivalent
  • Most core layout and input controls transfer with minimal changes
  • Several WPF controls (DataGrid, Ribbon, StatusBar) require Community Toolkit, community projects, or alternative controls
  • WPF patterns like DataTriggers, MultiBinding, Adorners, and DynamicResource have no direct WinUI equivalent
  • Visibility.Hidden and Focusable require multiple WinUI properties set together to preserve behavior
  • Uno Platform 6.5 on .NET 10 implements the WinUI 3 API surface across all targets
  • Includes a ready-to-use AI prompt template for automated XAML translation

Who this is for: WPF developers actively migrating production code to WinUI 3 and Uno Platform. You should already understand WPF XAML fundamentals and have a migration project underway or planned.

If you are migrating a WPF application to WinUI and Uno Platform, this is the reference you keep open in a second monitor. It covers every major namespace change, control mapping, property translation, and pattern replacement you will encounter.

Bookmark this page. You will come back to it dozens of times during your migration.

Namespaces

Namespace Mapping Table

The single biggest mechanical change in any WPF-to-WinUI migration is swapping namespaces. Every System.Windows reference in your code-behind becomes a Microsoft.UI.Xaml reference.

WPF NamespaceWinUI 3 NamespaceNotes
System.WindowsMicrosoft.UI.XamlRoot namespace
System.Windows.ControlsMicrosoft.UI.Xaml.ControlsCore controls
System.Windows.Controls.PrimitivesMicrosoft.UI.Xaml.Controls.PrimitivesLow-level primitives
System.Windows.MediaMicrosoft.UI.Xaml.MediaBrushes, transforms
System.Windows.Media.AnimationMicrosoft.UI.Xaml.Media.AnimationStoryboard, animations
System.Windows.Media.ImagingMicrosoft.UI.Xaml.Media.ImagingBitmapImage, WriteableBitmap
System.Windows.Media.Media3DNo equivalentUse Win2D or Composition APIs
System.Windows.ShapesMicrosoft.UI.Xaml.ShapesRectangle, Ellipse, Path
System.Windows.DataMicrosoft.UI.Xaml.DataBinding, IValueConverter
System.Windows.InputMicrosoft.UI.Xaml.InputPointer, keyboard, focus
System.Windows.NavigationNo direct equivalentUse Frame.Navigate()
System.Windows.DocumentsNo direct equivalentLimited via RichTextBlock
System.Windows.MarkupMicrosoft.UI.Xaml.MarkupXAML parsing
System.Windows.AutomationMicrosoft.UI.Xaml.AutomationAccessibility
System.Windows.InteropMicrosoft.UI.Xaml.HostingXAML Islands, etc.
System.Windows.ThreadingMicrosoft.UI.DispatchingDispatcher becomes DispatcherQueue

XAML Namespace Declarations

The default XML namespace URI is the same in both WPF and WinUI, but the underlying types it resolves to are different. Your XAML files may compile without namespace changes, but your code-behind requires a full using statement update.

WPFWinUI
xmlns:local="clr-namespace:MyApp"xmlns:local="using:MyApp"
clr-namespace:MyApp;assembly=MyLibusing:MyApp (assembly inferred)

Code-Behind Transformation

WPF
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
WinUI / Uno
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Dispatching;

Common Using Pitfalls

WPF CodeWinUI ReplacementWhy It Breaks
Application.Current.DispatcherA captured DispatcherQueue (see Dispatcher section)Dispatcher does not exist; use DispatcherQueue.TryEnqueue()
Window.CurrentYour own MainWindow property on AppWindow.Current not supported in Windows App SDK
Clipboard in System.WindowsWindows.ApplicationModel.DataTransfer.ClipboardDifferent API surface entirely
MessageBox.Show()ContentDialog with XamlRoot setNo MessageBox in WinUI
Note on MainWindow

WinUI 3 does not expose a built-in App.MainWindow property. The convention is to create the window in App.OnLaunched, store it in a field, and expose it as a public static property (for example App.MainWindow) so other code can reach it. References to App.MainWindow elsewhere in this article follow that convention.

1:1 Controls

Controls That Map 1:1

Most everyday controls exist in WinUI with the same name and nearly identical behavior: Button, TextBox, TextBlock, ComboBox, ListBox, ListView, StackPanel, Grid, Border, Image, CheckBox, RadioButton, Slider, ProgressBar, ProgressRing, ScrollViewer, Canvas, ContentPresenter, ContentControl, ItemsControl, Popup, ToolTip, PasswordBox, DatePicker.

WinUI-Only Additions Worth Adopting

These have no direct WPF equivalent but are worth introducing during modernization: NavigationView, NumberBox, InfoBar, ToggleSwitch, HyperlinkButton, Expander, TeachingTip, ContentDialog, Flyout, RichEditBox, CalendarView, TimePicker, MediaPlayerElement.

Key Property Differences

WPF Property / ValueWinUI EquivalentContext
Visibility.HiddenNot availableSet Opacity="0" + IsHitTestVisible="False". Using Opacity="0" alone leaves the element clickable.
TextWrapping.WrapWithOverflowTextWrapping.WrapWinUI does not distinguish
MouseLeftButtonDownPointerPressedPointer model replaces mouse model
MouseEnter / MouseLeavePointerEntered / PointerExitedPointer model
PreviewMouseDownPointerPressed (no tunneling)Use AddHandler(..., handledEventsToo: true)
FocusableIsTabStop (and optionally AllowFocusOnInteraction)IsTabStop="False" excludes from tab nav and blocks Focus() calls. Add AllowFocusOnInteraction="False" only when you also need to suppress pointer-interaction focus.
Translation

Controls That Need Translation

WPF ControlWinUI / Uno ReplacementMigration Notes
DataGridCommunity Toolkit DataGrid (7.x) or WinUI.TableViewMicrosoft's current guide points to WinUI.TableView as a modern community option. Toolkit DataGrid still works but is frozen at 7.x. Evaluate both.
RibbonCommandBar / CommandBarFlyoutNo first-party Ribbon. Community Toolkit Labs has an experimental Ribbon.
Menu / MenuItemMenuBar / MenuBarItem / MenuFlyoutItemMenuBar for classic menu, MenuFlyout for context
ContextMenuMenuFlyout via ContextFlyoutAssign to ContextFlyout on any UIElement
ToolBar / ToolBarTrayCommandBar + AppBarButtonReplaces toolbar patterns
StatusBarInfoBar + custom footer layoutNo first-party StatusBar. Use InfoBar for status messages or a footer Grid.
TabControlTabView or NavigationView (Top)TabView for closeable tabs, NavigationView for static
FlowDocumentRichTextBlockPartial replacement only
RichTextBox (editing)RichEditBoxRich text editing
WrapPanelBuilt-in on Uno Platform, or Community ToolkitUno ships WrapPanel natively
UniformGridCommunity ToolkitNot in WinUI by default
DockPanelCommunity ToolkitNot in WinUI by default
GroupBoxExpander or customNo built-in GroupBox
LabelTextBlockUse AccessKey on the target control
MediaElementMediaPlayerElementDifferent API surface
GridSplitterCommunity ToolkitNot in WinUI by default

Version note: DataGrid ships in Windows Community Toolkit 7.x and was removed in 8.x. Pin to 7.x or the Uno-ported 7.x package. For new projects, consider WinUI.TableView as a modern alternative that follows current WinUI 3 guidance.

NuGet Packages You Will Likely Need

PackagePurpose
CommunityToolkit.WinUI.UI.Controls (7.x)DataGrid, WrapPanel, DockPanel, UniformGrid, GridSplitter
Uno.CommunityToolkit.WinUI.*Uno-ported packages for non-Windows targets
CommunityToolkit.MvvmRelayCommand, ObservableObject, source generators
Uno.WinUIUno Platform's WinUI API implementation
Uno.Themes.WinUI.MaterialMaterial Design 3 theme support
Uno.Toolkit.WinUINavigationBar, TabBar, DrawerControl, SafeArea
No Equivalent

Patterns That Do Not Exist in WinUI

These require the most effort during migration because they demand architectural changes, not just find-and-replace.

DataTriggers and Style.Triggers

WinUI has no trigger system. The replacement is VisualStateManager with state triggers.

WPF (Before)
<Style TargetType="Border">
  <Style.Triggers>
    <DataTrigger Binding="{Binding IsActive}" Value="True">
      <Setter Property="Background" Value="Green" />
    </DataTrigger>
  </Style.Triggers>
</Style>
WinUI / Uno (After)
<Border x:Name="MyBorder">
  <VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
      <VisualState x:Name="Active">
        <VisualState.StateTriggers>
          <StateTrigger IsActive="{x:Bind ViewModel.IsActive, Mode=OneWay}" />
        </VisualState.StateTriggers>
        <VisualState.Setters>
          <Setter Target="MyBorder.Background" Value="Green" />
        </VisualState.Setters>
      </VisualState>
    </VisualStateGroup>
  </VisualStateManager.VisualStateGroups>
</Border>

You can also install Microsoft.Xaml.Behaviors.WinUI.Managed for more complex trigger scenarios, including DataTriggerBehavior.

MultiBinding

WinUI does not support MultiBinding. The most direct replacement is function binding with x:Bind:

WinUI / Uno
<TextBlock Text="{x:Bind local:Converters.FormatFullName(ViewModel.FirstName, ViewModel.LastName), Mode=OneWay}" />
C#
public static class Converters
{
    public static string FormatFullName(string first, string last)
        => $"{first} {last}";
}

Alternative: use a computed property in the ViewModel (public string FullName => $"{FirstName} {LastName}") and raise PropertyChanged for it whenever either source changes.

RoutedUICommand

WinUI does not support routed commands. Replace with [RelayCommand] from CommunityToolkit.Mvvm. WinUI 3 also provides StandardUICommand and XamlUICommand for pre-defined platform commands (Cut, Copy, Paste, Delete) with built-in icons and keyboard accelerators.

Adorners

Adorner Use CaseWinUI Replacement
Validation indicatorsTeachingTip, InfoBar, or InputValidation error templates
Resize handlesPopup positioned relative to the target element
Drag previewDragItemsStarting event with custom DragUI
Overlay decorationsCanvas overlay or Popup layer
Watermark / PlaceholderTextBox.PlaceholderText (built-in)

DynamicResource, StaticResource, and ThemeResource

WPFWinUIBehavior
{StaticResource}{StaticResource}Resolved once at load time. Same in both.
{DynamicResource}Not availableUse {ThemeResource} instead.
No equivalent{ThemeResource}Re-evaluated on theme change (Light/Dark).

If your WPF code uses DynamicResource to swap resources at runtime (not for theming), you will need an alternative: binding to a ViewModel property or using the Composition API.

Binding vs. x:Bind

Feature{Binding}{x:Bind}
Compile-time validationNoYes
Default modeOneWayOneTime
Default sourceDataContextPage/UserControl code-behind
Function bindingNoYes
PerformanceReflection-basedCompiled, no reflection

Default mode gotcha: {x:Bind} defaults to OneTime, not OneWay. Add Mode=OneWay or Mode=TwoWay explicitly if you need live updates.

Styles: Always Use BasedOn

In WinUI 3, always use BasedOn when overriding default control styles. Without it, your style replaces the entire default style rather than extending it.

WinUI
<Style TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
  <Setter Property="Background" Value="Red" />
</Style>

RelativeSource AncestorType

WPF's {Binding RelativeSource={RelativeSource AncestorType=...}} has no direct equivalent in WinUI. On Uno Platform, use the Uno Toolkit AncestorSource markup extension.

Resources

Resource Dictionaries and Merged Dictionaries

WinUI / Uno
<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="ms-appx:///Styles/Colors.xaml" />
      <ResourceDictionary Source="ms-appx:///Styles/Controls.xaml" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

Key differences: in WinUI 3 (Windows App SDK), the default Fluent control styles load automatically from the SDK. You do not need to add XamlControlsResources (that is the UWP + WinUI 2 pattern). Resource paths use the ms-appx:/// scheme. Window.Resources does not exist in WinUI; place window-level resources on the root layout container or on a Page.

Uno Platform Theming

Material Theme
<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <MaterialTheme xmlns="using:Uno.Themes" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

Uno Platform supports lightweight styling, which lets you override specific theme resources (colors, corner radii, typography) without replacing entire control templates. Significantly more maintainable than WPF's approach of copying and modifying full control templates.

Dispatcher

Dispatcher: Fire-and-Forget and Awaitable

DispatcherQueue.TryEnqueue is the WinUI replacement for Dispatcher.Invoke and BeginInvoke. It is fire-and-forget with no synchronous Invoke equivalent.

To reach the UI thread's DispatcherQueue from a background thread, capture it on the UI thread first. Inside a DependencyObject (Page, UserControl), use this.DispatcherQueue. In App.xaml.cs, capture DispatcherQueue.GetForCurrentThread() at startup and expose it through a static property.

Fire-and-Forget
App.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
    // UI work
});
Awaitable
var tcs = new TaskCompletionSource<bool>(
    TaskCreationOptions.RunContinuationsAsynchronously);

if (!App.MainWindow.DispatcherQueue.TryEnqueue(() =>
{
    try { /* UI work */ tcs.TrySetResult(true); }
    catch (Exception ex) { tcs.TrySetException(ex); }
}))
{
    tcs.TrySetException(new InvalidOperationException(
        "Failed to enqueue work."));
}

await tcs.Task;

The Community Toolkit also ships a DispatcherQueue.EnqueueAsync extension method that handles this wrapping for you.

Find & Replace

Complete Find-and-Replace Reference

XAML Attribute Replacements

FindReplace WithContext
ContextMenu=ContextFlyout=On any UIElement
{DynamicResource }{ThemeResource }Theme-change support
{x:Static }{x:Bind }Static member references
Visibility="Hidden"Opacity="0" + IsHitTestVisible="False"Preserve layout; without IsHitTestVisible the element remains clickable
MouseLeftButtonDownPointerPressedEvents
MouseLeftButtonUpPointerReleasedEvents
MouseEnterPointerEnteredEvents
MouseLeavePointerExitedEvents
MouseMovePointerMovedEvents
MouseWheelPointerWheelChangedEvents
MouseDoubleClickDoubleTappedEvents
Focusable="False"IsTabStop="False"Add AllowFocusOnInteraction="False" only if you also need to suppress pointer-interaction focus
TextWrapping="WrapWithOverflow"TextWrapping="Wrap"TextBlock, TextBox
InputBindingsKeyboardAcceleratorsKeyboard shortcuts

Code-Behind Replacements

FindReplace WithNotes
using System.Windows;using Microsoft.UI.Xaml;Root types
using System.Windows.Controls;using Microsoft.UI.Xaml.Controls;Controls
using System.Windows.Media;using Microsoft.UI.Xaml.Media;Media
using System.Windows.Data;using Microsoft.UI.Xaml.Data;Data binding
using System.Windows.Input;using Microsoft.UI.Xaml.Input;Input
Dispatcher.Invoke(DispatcherQueue.TryEnqueue(Threading
Application.Current.DispatcherA captured DispatcherQueueSee Dispatcher section
CaptureMouse()CapturePointer(e.Pointer)Inside pointer event handler
ReleaseMouseCapture()ReleasePointerCaptures()Releases all
Mouse.GetPosition(element)e.GetCurrentPoint(element).PositionInside pointer event handler
MouseEventArgsPointerRoutedEventArgsEvent handlers
RoutedUICommandRelayCommandCommunityToolkit.Mvvm
AI Prompt

AI Prompt Template for Automated XAML Translation

Copy the prompt template into your AI coding assistant. It encodes every rule from this article so the agent can perform the mechanical translation in one pass. The full prompt covers namespace rules, resource rules, control replacements (including the WinUI.TableView option for DataGrid), property replacements (with the nuanced Focusable mapping), event replacements, trigger replacements, and binding upgrades.

After Running the Prompt

Review: trigger translations (verify VisualStateManager groups reflect your original logic), DataGrid columns (Community Toolkit column types may differ), custom controls (third-party WPF libraries need manual replacement), and resource dictionary paths (verify ms-appx:/// paths resolve correctly).

FAQ

FAQ

Do I need to rewrite all my XAML from scratch?

No. The majority of WPF XAML (layout panels, core controls, basic styles) transfers with namespace changes and minor property fixes. The heavy lifting is in triggers, MultiBinding, and controls that do not exist in WinUI.

Can I use {Binding} in WinUI, or must I switch to {x:Bind}?

{Binding} still works in WinUI. You are not forced to switch. However, {x:Bind} provides compile-time validation, better performance, and function binding (which replaces MultiBinding). For new or migrated code, {x:Bind} is the recommended choice.

What replaces Visibility.Hidden?

WinUI only has Visible and Collapsed. To keep invisible-but-layout-occupying behavior, set Opacity="0" while keeping Visibility="Visible", and also set IsHitTestVisible="False" so the element is not clickable. If the control would otherwise receive focus from pointer interaction and you want to block that too, add AllowFocusOnInteraction="False".

Do I need to add XamlControlsResources to my WinUI 3 App.xaml?

Usually no. In a WinUI 3 (Windows App SDK) project, the default Fluent control styles load automatically from the SDK. XamlControlsResources is primarily the UWP + WinUI 2 pattern. If you include it (for example, sharing dictionaries with a WinUI 2 codebase), add it as the first merged dictionary so it does not override your custom styles.

How do I migrate WPF's Dispatcher pattern?

WinUI 3 has no built-in App.MainWindow; the convention is to capture your window in App.OnLaunched and expose it as a public static property. Replace Dispatcher.Invoke(...) with DispatcherQueue.TryEnqueue(...). For awaitable dispatch, wrap with a TaskCompletionSource or use the Community Toolkit EnqueueAsync extension.

Which Community Toolkit version ships DataGrid?

DataGrid is in Windows Community Toolkit 7.x and was removed in 8.x. Pin to 7.x or the Uno-ported 7.x package. Microsoft's current WPF-to-WinUI 3 guidance also points to WinUI.TableView as a community-maintained alternative worth evaluating.

Is there an automated migration tool from Microsoft?

There is no automated WPF-to-WinUI migration tool from Microsoft as of 2026. The .NET Upgrade Assistant handles .NET Framework to .NET upgrades but does not translate WPF XAML to WinUI XAML.

Does Uno Platform add extra controls beyond WinUI?

Yes. The Uno Toolkit (Uno.Toolkit.WinUI) includes NavigationBar, TabBar, DrawerControl, SafeArea, and more. The Community Toolkit controls also work across all Uno Platform targets via the Uno-ported packages.