Reference WPF Migration
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 or alternative controls.
  • WPF patterns like DataTriggers, MultiBinding, Adorners, and DynamicResource have no direct WinUI equivalent and require architectural rework.
  • This article includes a ready-to-use AI prompt template that automates the mechanical parts of 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.

Namespaces

Namespace Mapping Table

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.DocumentsLimitedRichTextBlock + Paragraph
System.Windows.MarkupMicrosoft.UI.Xaml.MarkupXAML parsing, markup extensions
System.Windows.AutomationMicrosoft.UI.Xaml.AutomationAccessibility / UI Automation
System.Windows.InteropMicrosoft.UI.Xaml.HostingInterop / XAML Islands
System.Windows.ThreadingMicrosoft.UI.DispatchingDispatcher becomes DispatcherQueue

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 Platform
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.DispatcherApp.Window.DispatcherQueueDispatcher does not exist; use DispatcherQueue.TryEnqueue()
Window.CurrentCustom App.Window staticNot supported in Windows App SDK
Clipboard in System.WindowsWindows.ApplicationModel.DataTransfer.ClipboardDifferent API surface
MessageBox.Show()ContentDialog with XamlRootNo MessageBox in WinUI
1:1 Controls

Controls That Map 1:1

Most everyday controls exist in WinUI with the same name and nearly identical behavior. Key property differences to watch:

WPF Property/ValueWinUI EquivalentContext
Visibility.HiddenNot availableWinUI only has Visible and Collapsed. Use Opacity="0" for invisible-but-layout-occupying.
TextWrapping.WrapWithOverflowTextWrapping.WrapWinUI does not distinguish the two
MouseLeftButtonDownPointerPressedWinUI uses pointer events, not mouse-specific
MouseEnter / MouseLeavePointerEntered / PointerExitedPointer model replaces mouse model
PreviewMouseDownPointerPressedWinUI has no tunneling/preview events
FocusableIsTabStopDifferent property name, same behavior
Replacements

Controls That Need Translation

These WPF controls have no direct counterpart. Each requires a different control, a third-party library, or a Community Toolkit package.

WPF ControlWinUI / Uno ReplacementNotes
DataGridCommunity Toolkit DataGridSimilar API, not identical
RibbonCommandBar or NavigationViewNo Ribbon in WinUI
Menu / MenuItemMenuBar / MenuBarItem / MenuFlyoutMenuBar for classic menu, MenuFlyout for context
ContextMenuMenuFlyoutAssign to ContextFlyout property
ToolBar / ToolBarTrayCommandBarCommandBar + AppBarButton items
StatusBarCustom Grid/StackPanel or InfoBarNo StatusBar control
TabControlTabView or NavigationView with top modeTabView for closeable tabs, NavigationView for static
TreeViewTreeViewAvailable natively; data binding model differs
DocumentViewerWebView2Render PDFs/XPS inside WebView2
FlowDocumentRichTextBlockPartial replacement only
RichTextBoxRichEditBoxRich text editing
WrapPanelCommunity Toolkit WrapPanelNot in WinUI by default
UniformGridCommunity Toolkit UniformGridNot in WinUI by default
DockPanelCommunity Toolkit DockPanelNot in WinUI by default
GroupBoxExpander or custom HeaderedContentControlNo GroupBox in WinUI
LabelTextBlockWPF Label is a ContentControl; use TextBlock + AccessKey

NuGet Packages You Will Likely Need

PackagePurpose
CommunityToolkit.WinUI.UI.ControlsDataGrid, WrapPanel, DockPanel, UniformGrid
CommunityToolkit.MvvmRelayCommand, ObservableObject, source generators
Uno.Themes.WinUIMaterial, Cupertino, or Fluent theme support
Uno.Toolkit.WinUIAdditional cross-platform controls and helpers
No Equivalent

Patterns That Do Not Exist in WinUI

These WPF features 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
<Style TargetType="Border">
  <Style.Triggers>
    <DataTrigger Binding="{Binding IsActive}" Value="True">
      <Setter Property="Background" Value="Green" />
    </DataTrigger>
  </Style.Triggers>
</Style>
WinUI / Uno Platform
<Border>
  <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>

MultiBinding

WinUI does not support MultiBinding. Use x:Bind with a function (most direct replacement), a computed ViewModel property, or multiple simple bindings.

WinUI / Uno Platform
<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}";
}

RoutedUICommand

WinUI does not support routed commands. Use the standard ICommand pattern with RelayCommand from CommunityToolkit.Mvvm.

WinUI / Uno Platform
// Using CommunityToolkit.Mvvm
[RelayCommand(CanExecute = nameof(CanSave))]
private void Save() { /* save logic */ }

private bool CanSave() => IsDirty;

WinUI 3 also provides StandardUICommand and XamlUICommand for pre-defined platform commands (Cut, Copy, Paste, Delete) with built-in icons and keyboard accelerators.

Adorners

WPF's AdornerLayer has no WinUI equivalent. Replacements depend on the use case:

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

Styles, Resources, and Templates

DynamicResource, StaticResource, and ThemeResource

This is one of the most common sources of migration bugs.

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

Implicit Styles

Important

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>

Binding vs. x:Bind

Feature{Binding}{x:Bind}
Compile-time validationNoYes
Default modeOneWayOneTime
Default sourceDataContextPage/UserControl code-behind
Function bindingNoYes
PerformanceReflection-basedCompiled, no reflection
MultiBindingNo (not in WinUI)Use function binding

If you use {x:Bind}, remember that its default mode is OneTime, not OneWay. Add Mode=OneWay or Mode=TwoWay explicitly if you need live updates.

Resource Dictionaries

WinUI / Uno Platform
<Application.Resources>
  <ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
      <!-- Required: default Fluent styles -->
      <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
      <!-- Your custom resources -->
      <ResourceDictionary Source="ms-appx:///Styles/Colors.xaml" />
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

XamlControlsResources must be the first merged dictionary. It provides the default Fluent styles. Omitting it gives you controls with no visual appearance. Resource paths use ms-appx:/// protocol instead of relative paths. Window.Resources does not exist in WinUI; place window-level resources on the root layout container or on a Page.

Find & Replace

Complete Find-and-Replace Reference

XAML Attribute Replacements

FindReplace WithContext
ContextMenu=ContextFlyout=On any UIElement
{DynamicResource{ThemeResourceTheme-responsive references
{x:Static{x:BindStatic member references
Visibility="Hidden"Visibility="Collapsed"Or use Opacity="0" for layout
MouseLeftButtonDownPointerPressedEvent handlers
MouseLeftButtonUpPointerReleasedEvent handlers
MouseEnterPointerEnteredEvent handlers
MouseLeavePointerExitedEvent handlers
MouseMovePointerMovedEvent handlers
MouseWheelPointerWheelChangedEvent handlers
Focusable="True"IsTabStop="True"Focus behavior
TextWrapping="WrapWithOverflow"TextWrapping="Wrap"TextBlock, TextBox
MediaElementMediaPlayerElementMedia playback

Code-Behind Replacements

FindReplace With
using System.Windows;using Microsoft.UI.Xaml;
using System.Windows.Controls;using Microsoft.UI.Xaml.Controls;
using System.Windows.Media;using Microsoft.UI.Xaml.Media;
using System.Windows.Data;using Microsoft.UI.Xaml.Data;
using System.Windows.Input;using Microsoft.UI.Xaml.Input;
Dispatcher.Invoke(DispatcherQueue.TryEnqueue(
MouseEventArgsPointerRoutedEventArgs
KeyEventArgsKeyRoutedEventArgs
RoutedUICommandRelayCommand (CommunityToolkit.Mvvm)
CommandBindingRemove; bind ICommand directly
AI Prompt

AI Prompt Template for Automated XAML Translation

Copy the following prompt and paste it into your AI coding assistant. Replace the placeholder with your actual WPF XAML file content. The prompt encodes every rule from this article so the agent can perform the mechanical translation in one pass.

Prompt
You are a WPF-to-WinUI XAML migration assistant. Translate the following WPF XAML file to WinUI 3 XAML that is compatible with Uno Platform.

Apply ALL of the following rules:

NAMESPACE RULES:
- The default xmlns stays: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- Remove any clr-namespace references to System.Windows.* and replace with equivalent Microsoft.UI.Xaml.* or "using:" syntax
- Replace xmlns:local="clr-namespace:MyApp" with xmlns:local="using:MyApp"

RESOURCE RULES:
- Replace all {DynamicResource X} with {ThemeResource X}
- Replace {x:Static X} with {x:Bind X}
- Keep {StaticResource X} as-is

CONTROL REPLACEMENTS:
- Replace <Menu> with <MenuBar>, <MenuItem> with <MenuBarItem> or <MenuFlyoutItem>
- Replace ContextMenu with ContextFlyout using <MenuFlyout>
- Replace <ToolBar> / <ToolBarTray> with <CommandBar> and <AppBarButton>
- Replace <StatusBar> with a <Grid> at the bottom of the layout
- Replace <TabControl> with <TabView> or <NavigationView PaneDisplayMode="Top">
- Replace <DataGrid> with Community Toolkit DataGrid (xmlns:ctk="using:CommunityToolkit.WinUI.UI.Controls")
- Replace <Label> with <TextBlock>
- Replace <MediaElement> with <MediaPlayerElement>

PROPERTY REPLACEMENTS:
- Replace Visibility="Hidden" with Visibility="Collapsed"
- Replace TextWrapping="WrapWithOverflow" with TextWrapping="Wrap"
- Replace Focusable="True/False" with IsTabStop="True/False"

EVENT REPLACEMENTS:
- Replace Mouse* events with Pointer* equivalents
- Remove all Preview* tunneling events

TRIGGER REPLACEMENTS:
- Remove all Style.Triggers, DataTrigger, EventTrigger blocks
- Create corresponding VisualStateManager.VisualStateGroups using StateTrigger

BINDING UPGRADES (optional):
- Convert {Binding Path=X} to {x:Bind ViewModel.X, Mode=OneWay} where possible
- For MultiBinding, replace with x:Bind function binding

OUTPUT: Complete translated XAML file with a list of manual follow-up items.

Here is the WPF XAML file to translate:

```xml
[PASTE YOUR WPF XAML HERE]
```

After running this prompt, review carefully. Pay special attention to trigger translations, DataGrid columns, custom third-party controls, and resource dictionary paths.

FAQ

FAQ

Do I need to rewrite all my XAML from scratch?

No. The majority of WPF XAML transfers with namespace changes and minor property fixes. The heavy lifting is in triggers, MultiBinding, and controls that don't exist in WinUI.

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

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

What replaces Visibility.Hidden?

WinUI only has Visible and Collapsed. If you need invisible-but-layout-occupying, set Opacity="0" while keeping Visibility="Visible".

How do I handle preview/tunneling events?

WinUI does not support tunneling events. Replace PreviewMouseDown, PreviewKeyDown, etc. with their bubbling equivalents. If you relied on tunneling to intercept events, restructure using the Handled property or AddHandler with handledEventsToo: true.

How do I migrate the Dispatcher pattern?

Replace Application.Current.Dispatcher.Invoke(...) with App.Window.DispatcherQueue.TryEnqueue(...). The DispatcherQueue API is asynchronous by default and has no synchronous Invoke method.

Is there an automated migration tool from Microsoft?

No automated WPF-to-WinUI migration tool exists as of early 2026. The .NET Upgrade Assistant handles .NET Framework to .NET upgrades but does not translate WPF XAML to WinUI XAML. The AI prompt template above is designed to fill that gap.

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 (DataGrid, WrapPanel, DockPanel) also work across all Uno Platform targets.