- WPF's
System.Windows.*namespaces map toMicrosoft.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.
Namespace Mapping Table
| WPF Namespace | WinUI 3 Namespace | Notes |
|---|---|---|
System.Windows | Microsoft.UI.Xaml | Root namespace |
System.Windows.Controls | Microsoft.UI.Xaml.Controls | Core controls |
System.Windows.Controls.Primitives | Microsoft.UI.Xaml.Controls.Primitives | Low-level primitives |
System.Windows.Media | Microsoft.UI.Xaml.Media | Brushes, transforms |
System.Windows.Media.Animation | Microsoft.UI.Xaml.Media.Animation | Storyboard, animations |
System.Windows.Media.Imaging | Microsoft.UI.Xaml.Media.Imaging | BitmapImage, WriteableBitmap |
System.Windows.Media.Media3D | No equivalent | Use Win2D or Composition APIs |
System.Windows.Shapes | Microsoft.UI.Xaml.Shapes | Rectangle, Ellipse, Path |
System.Windows.Data | Microsoft.UI.Xaml.Data | Binding, IValueConverter |
System.Windows.Input | Microsoft.UI.Xaml.Input | Pointer, keyboard, focus |
System.Windows.Navigation | No direct equivalent | Use Frame.Navigate() |
System.Windows.Documents | Limited | RichTextBlock + Paragraph |
System.Windows.Markup | Microsoft.UI.Xaml.Markup | XAML parsing, markup extensions |
System.Windows.Automation | Microsoft.UI.Xaml.Automation | Accessibility / UI Automation |
System.Windows.Interop | Microsoft.UI.Xaml.Hosting | Interop / XAML Islands |
System.Windows.Threading | Microsoft.UI.Dispatching | Dispatcher becomes DispatcherQueue |
Code-Behind Transformation
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;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 Code | WinUI Replacement | Why It Breaks |
|---|---|---|
Application.Current.Dispatcher | App.Window.DispatcherQueue | Dispatcher does not exist; use DispatcherQueue.TryEnqueue() |
Window.Current | Custom App.Window static | Not supported in Windows App SDK |
Clipboard in System.Windows | Windows.ApplicationModel.DataTransfer.Clipboard | Different API surface |
MessageBox.Show() | ContentDialog with XamlRoot | No MessageBox in WinUI |
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/Value | WinUI Equivalent | Context |
|---|---|---|
Visibility.Hidden | Not available | WinUI only has Visible and Collapsed. Use Opacity="0" for invisible-but-layout-occupying. |
TextWrapping.WrapWithOverflow | TextWrapping.Wrap | WinUI does not distinguish the two |
MouseLeftButtonDown | PointerPressed | WinUI uses pointer events, not mouse-specific |
MouseEnter / MouseLeave | PointerEntered / PointerExited | Pointer model replaces mouse model |
PreviewMouseDown | PointerPressed | WinUI has no tunneling/preview events |
Focusable | IsTabStop | Different property name, same behavior |
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 Control | WinUI / Uno Replacement | Notes |
|---|---|---|
DataGrid | Community Toolkit DataGrid | Similar API, not identical |
Ribbon | CommandBar or NavigationView | No Ribbon in WinUI |
Menu / MenuItem | MenuBar / MenuBarItem / MenuFlyout | MenuBar for classic menu, MenuFlyout for context |
ContextMenu | MenuFlyout | Assign to ContextFlyout property |
ToolBar / ToolBarTray | CommandBar | CommandBar + AppBarButton items |
StatusBar | Custom Grid/StackPanel or InfoBar | No StatusBar control |
TabControl | TabView or NavigationView with top mode | TabView for closeable tabs, NavigationView for static |
TreeView | TreeView | Available natively; data binding model differs |
DocumentViewer | WebView2 | Render PDFs/XPS inside WebView2 |
FlowDocument | RichTextBlock | Partial replacement only |
RichTextBox | RichEditBox | Rich text editing |
WrapPanel | Community Toolkit WrapPanel | Not in WinUI by default |
UniformGrid | Community Toolkit UniformGrid | Not in WinUI by default |
DockPanel | Community Toolkit DockPanel | Not in WinUI by default |
GroupBox | Expander or custom HeaderedContentControl | No GroupBox in WinUI |
Label | TextBlock | WPF Label is a ContentControl; use TextBlock + AccessKey |
NuGet Packages You Will Likely Need
| Package | Purpose |
|---|---|
CommunityToolkit.WinUI.UI.Controls | DataGrid, WrapPanel, DockPanel, UniformGrid |
CommunityToolkit.Mvvm | RelayCommand, ObservableObject, source generators |
Uno.Themes.WinUI | Material, Cupertino, or Fluent theme support |
Uno.Toolkit.WinUI | Additional cross-platform controls and helpers |
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.
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Background" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style><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.
<TextBlock Text="{x:Bind local:Converters.FormatFullName(ViewModel.FirstName, ViewModel.LastName), Mode=OneWay}" />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.
// 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 Case | WinUI Replacement |
|---|---|
| Validation indicators | TeachingTip, InfoBar, or InputValidation templates |
| Resize handles | Popup positioned relative to target |
| Drag preview | DragItemsStarting event with custom DragUI |
| Overlay decorations | Canvas overlay or Popup layer |
| Watermark / Placeholder | TextBox.PlaceholderText (built-in) |
Styles, Resources, and Templates
DynamicResource, StaticResource, and ThemeResource
This is one of the most common sources of migration bugs.
| WPF | WinUI | Behavior |
|---|---|---|
{StaticResource} | {StaticResource} | Resolved once at load time. Same in both. |
{DynamicResource} | Not available | Use {ThemeResource} instead. |
| No equivalent | {ThemeResource} | Resolved at load, re-evaluated on theme changes (Light/Dark). |
Implicit Styles
In WinUI 3, always use BasedOn when overriding default control styles. Without it, your style replaces the entire default style rather than extending it.
<Style TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
<Setter Property="Background" Value="Red" />
</Style>Binding vs. x:Bind
| Feature | {Binding} | {x:Bind} |
|---|---|---|
| Compile-time validation | No | Yes |
| Default mode | OneWay | OneTime |
| Default source | DataContext | Page/UserControl code-behind |
| Function binding | No | Yes |
| Performance | Reflection-based | Compiled, no reflection |
| MultiBinding | No (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
<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.
Complete Find-and-Replace Reference
XAML Attribute Replacements
| Find | Replace With | Context |
|---|---|---|
ContextMenu= | ContextFlyout= | On any UIElement |
{DynamicResource | {ThemeResource | Theme-responsive references |
{x:Static | {x:Bind | Static member references |
Visibility="Hidden" | Visibility="Collapsed" | Or use Opacity="0" for layout |
MouseLeftButtonDown | PointerPressed | Event handlers |
MouseLeftButtonUp | PointerReleased | Event handlers |
MouseEnter | PointerEntered | Event handlers |
MouseLeave | PointerExited | Event handlers |
MouseMove | PointerMoved | Event handlers |
MouseWheel | PointerWheelChanged | Event handlers |
Focusable="True" | IsTabStop="True" | Focus behavior |
TextWrapping="WrapWithOverflow" | TextWrapping="Wrap" | TextBlock, TextBox |
MediaElement | MediaPlayerElement | Media playback |
Code-Behind Replacements
| Find | Replace 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( |
MouseEventArgs | PointerRoutedEventArgs |
KeyEventArgs | KeyRoutedEventArgs |
RoutedUICommand | RelayCommand (CommunityToolkit.Mvvm) |
CommandBinding | Remove; bind ICommand directly |
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.
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
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.
Subscribe to Our Blog
Subscribe via RSS
Back to Top