--- uid: Uno.Development.WPFWinUIEquivalents --- # WPF to WinUI XAML Equivalents Reference This reference provides a comprehensive mapping of WPF namespaces, controls, XAML syntax, events, and patterns to their WinUI 3 / Uno Platform equivalents. Use it as a lookup when migrating WPF applications. > [!TIP] > For architectural migration guidance (MVVM, navigation, data access), see [Migrating WPF Apps to Web](wpf-migration.md). ## Namespace Mapping | 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` | `Microsoft.UI.Xaml.Media.Media3D` (partial equivalent) | Supports 3D transforms/projection (for example `CompositeTransform3D`, `Matrix3D`, `PerspectiveTransform3D`), but not WPF-style `Viewport3D` / 3D scene graph 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` | ### XAML Declaration Syntax | WPF | WinUI | |---|---| | `xmlns:local="clr-namespace:MyApp"` | `xmlns:local="using:MyApp"` | | `xmlns:local="clr-namespace:MyApp;assembly=MyLib"` | `xmlns:local="using:MyApp"` (assembly inferred) | ## Control Mappings ### Controls That Transfer Directly These controls exist in both WPF and WinUI and typically require only a namespace change: Button, TextBox, TextBlock, CheckBox, RadioButton, ComboBox, ListBox, ListView, Grid, StackPanel, Border, ScrollViewer, Canvas, Image, Slider, ProgressBar, ToolTip/ToolTipService, Expander, TreeView. ### WinUI-Only Additions You May Want to Adopt The following controls do not have direct equivalents in WPF but are often valuable to introduce when modernizing your UI with WinUI / Uno Platform: NavigationView, NumberBox, InfoBar, ProgressRing, ToggleSwitch, HyperlinkButton, GridView. ### Controls Requiring Replacement | WPF Control | WinUI / Uno Replacement | Notes | |---|---|---| | `DataGrid` | Community Toolkit `DataGrid` | Similar API, not identical. In WinUI 3 (Windows App SDK), use `CommunityToolkit.WinUI.UI.Controls`; for Uno Platform non-Windows targets, use the Uno-ported toolkit packages (`Uno.CommunityToolkit.WinUI.*`). | | `Ribbon` | `CommandBar` or `NavigationView` | No Ribbon in WinUI | | `Menu` / `MenuItem` | `MenuBar` / `MenuBarItem` / `MenuFlyoutItem` | `MenuBar` for top-level menus; `MenuFlyout` for context menus | | `ContextMenu` | `MenuFlyout` via `ContextFlyout` property | Assign to `ContextFlyout` on any `UIElement` | | `ToolBar` / `ToolBarTray` | `CommandBar` + `AppBarButton` | | | `StatusBar` | Custom `Grid` / `StackPanel` or `InfoBar` | No StatusBar control in WinUI | | `TabControl` | `TabView` or `NavigationView` (Top mode) | `TabView` supports closable tabs | | `DocumentViewer` | `WebView2` | Can display PDFs in WebView2; XPS requires conversion or a dedicated/third-party viewer | | `FlowDocument` | `RichTextBlock` | Partial replacement only | | `RichTextBox` | `RichEditBox` | Rich text editing | | `WrapPanel` | `WrapPanel` (built-in on Uno Platform) or Community Toolkit `WrapPanel` | Built-in on Uno Platform; otherwise see package guidance below. | | `UniformGrid` | Community Toolkit `UniformGrid` | Not in WinUI by default; see package guidance below. | | `DockPanel` | Community Toolkit `DockPanel` | Not in WinUI by default; see package guidance below. | | `GroupBox` | `Expander` or a custom `UserControl`/templated `ContentControl` | No built-in GroupBox in WinUI; use a custom header + border presentation when needed | | `Label` | `TextBlock` | Use `TextBlock` for the visual label; for WPF `Label.Target`-style association, use `AutomationProperties.LabeledBy` on the labeled control. `AccessKey` can be added separately for keyboard access. | | `MediaElement` | `MediaPlayerElement` | Different API surface | | `Window` (standalone) | `Window` | Window host; content is typically a `Page`/root `UIElement`. Use `ContentDialog` for modal windows. | | `GridSplitter` | Community Toolkit `GridSplitter` | See package guidance below. | | `Calendar` | `CalendarView` | Similar functionality with updated API | | `ListBox` | `ListBox` or `ListView` | `ListBox` exists in WinUI/Uno; prefer `ListView` when you need richer built-in list item presentation or interaction features | Package guidance for Community Toolkit controls in this table: in WinUI 3 (Windows App SDK), use `CommunityToolkit.WinUI.UI.Controls`; for Uno Platform non-Windows targets, install the matching Uno package for the control you use, such as `Uno.CommunityToolkit.WinUI.UI.Controls` for controls like `DockPanel` and `GridSplitter`, or `Uno.CommunityToolkit.WinUI.UI.Controls.DataGrid` for `DataGrid`. See [Uno Community Toolkit packages](uno-community-toolkit.md) for the authoritative package list and version guidance. ### Useful NuGet Packages | Package | Purpose | |---|---| | `CommunityToolkit.WinUI.UI.Controls` | DataGrid, WrapPanel, DockPanel, UniformGrid. Note: `DataGrid` and some related controls are available in Windows Community Toolkit 7.x; they were removed from 8.x. | | `CommunityToolkit.Mvvm` | RelayCommand, ObservableObject, source generators | | `Uno.Material.WinUI`, `Uno.Cupertino.WinUI`, `Uno.Simple.WinUI` | Material, Cupertino, or simple theme support | | `Uno.Toolkit.WinUI` | Additional cross-platform controls and helpers | ## Property and Value Mappings | WPF Property / Value | WinUI Equivalent | Context | |---|---|---| | `Visibility.Hidden` | Not available | Use `Opacity="0"` together with `IsHitTestVisible="False"` (and, for focusable controls, `IsTabStop="False"`) to be invisible, non-interactive, but still layout-occupying. | | `TextWrapping.WrapWithOverflow` | `TextWrapping.Wrap` | WinUI does not distinguish | | `Focusable` | `IsTabStop` and, when preventing interaction focus, `AllowFocusOnInteraction` | `IsTabStop` controls keyboard tab navigation; to also prevent focus via pointer interaction in WinUI/Uno, typically use `AllowFocusOnInteraction="False"` as well (and `IsTabStop="False"` where applicable). | ## Event Mappings ### Pointer Events (Replacing Mouse Events) | WPF Event | WinUI Event | Args Type | |---|---|---| | `MouseLeftButtonDown` | `PointerPressed` | `PointerRoutedEventArgs` | | `MouseLeftButtonUp` | `PointerReleased` | `PointerRoutedEventArgs` | | `MouseMove` | `PointerMoved` | `PointerRoutedEventArgs` | | `MouseEnter` | `PointerEntered` | `PointerRoutedEventArgs` | | `MouseLeave` | `PointerExited` | `PointerRoutedEventArgs` | | `MouseWheel` | `PointerWheelChanged` | `PointerRoutedEventArgs` | | `MouseDoubleClick` | `DoubleTapped` | `DoubleTappedRoutedEventArgs` | | `PreviewMouseDown` | `PointerPressed` | No direct WPF-style tunneling/preview pointer event in WinUI | > [!NOTE] > WinUI does not provide WPF-style `PreviewMouse*` tunneling events for pointer/mouse input. If you need to listen for a bubbling event even after a child marks it handled, use `AddHandler` with `handledEventsToo: true`. This does not reproduce WPF-style preview ordering (parent before child). ### Keyboard Events | WPF Event | WinUI Event | Args Type | |---|---|---| | `KeyDown` | `KeyDown` | `KeyRoutedEventArgs` | | `KeyUp` | `KeyUp` | `KeyRoutedEventArgs` | | `PreviewKeyDown` | `Uno only (WASM/SKIA): PreviewKeyDown` | `KeyRoutedEventArgs` | | `PreviewKeyUp` | `Uno only (WASM/SKIA): PreviewKeyUp` | `KeyRoutedEventArgs` | > [!NOTE] > Standard WinUI 3 does not expose WPF-style preview keyboard events. On Uno, `PreviewKeyDown` and `PreviewKeyUp` are available only on some targets (for example, WASM/SKIA), so treat them as platform-specific rather than general WinUI equivalents. When you need a cross-target or WinUI 3-compatible alternative, use `KeyDown` and `KeyUp`, and validate event ordering on your target platforms when the distinction matters. ### Mouse Capture | WPF | WinUI | Notes | |---|---|---| | `element.CaptureMouse()` | `element.CapturePointer(e.Pointer)` | Typically used inside a pointer event where `e.Pointer` is available | | `element.ReleaseMouseCapture()` | `element.ReleasePointerCaptures()` | General equivalent when you do not have the original `Pointer`; if you need to release a specific pointer later, store it and call `element.ReleasePointerCapture(pointer)` | | `Mouse.GetPosition(element)` | `e.GetCurrentPoint(element).Position` | Use within pointer event handling | ## XAML Syntax Translations ### Resource and Binding Markup | WPF | WinUI | Notes | |---|---|---| | `{StaticResource Key}` | `{StaticResource Key}` | Identical - resolved once at load | | `{DynamicResource Key}` | `{ThemeResource Key}` | Re-evaluated on theme changes (Light/Dark) | | `{x:Static ns:Type.Member}` | `{x:Bind ns:Type.Member}` | Common option for static member references; enums/values can often use direct `ns:Type.Member` or literals | | `{Binding Path=X}` | `{x:Bind ViewModel.X, Mode=OneWay}` | See [binding comparison](#binding-technology-comparison) below | | `{Binding RelativeSource={RelativeSource AncestorType=...}}` | Uno Toolkit `AncestorSource` | See [Ancestor/ItemsControl binding](https://github.com/unoplatform/uno.toolkit.ui/blob/main/doc/helpers/ancestor-itemscontrol-binding.md) | ### Binding Technology Comparison | Feature | `{Binding}` | `{x:Bind}` | |---|---|---| | Compile-time validation | No | Yes | | Default mode | Depends on target property metadata (often OneWay; some are TwoWay) | **OneTime** | | Default source | DataContext | Page / UserControl code-behind | | Function binding | No | Yes | | Performance | Reflection-based | Compiled, no reflection | | MultiBinding | Not in WinUI | Use function binding | > [!IMPORTANT] > `{x:Bind}` defaults to **OneTime**, not OneWay. Always specify `Mode=OneWay` for properties that should update. ## Patterns Without Direct WinUI Equivalents ### Style.Triggers and DataTriggers WinUI does not support `Style.Triggers`, `DataTrigger`, `EventTrigger`, or `MultiDataTrigger`. Replace with `VisualStateManager`: **WPF:** ```xml ``` **WinUI equivalent:** ```xml ``` ### MultiBinding WinUI does not support `MultiBinding`. Use `x:Bind` with function binding: ```xml ``` ```csharp public static class Converters { public static string FormatFullName(string first, string last) => $"{first} {last}"; } ``` ### RoutedUICommand Replace `RoutedUICommand` and `CommandBinding` with `ICommand` implementations. Using CommunityToolkit.Mvvm: ```csharp [RelayCommand(CanExecute = nameof(CanSave))] private void Save() { /* save logic */ } private bool CanSave() => IsDirty; ``` WinUI 3 also offers `StandardUICommand` and `XamlUICommand` for predefined operations (Cut, Copy, Paste) with built-in icons and keyboard accelerators. ### Adorners WinUI does not have an Adorner layer. Use these alternatives: | Adorner Use Case | WinUI Replacement | |---|---| | Validation indicators | `TeachingTip`, `InfoBar`, or input validation 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) | ## Resource Dictionaries ```xml ``` Key differences from WPF: - `XamlControlsResources` must be the **first** merged dictionary to provide default styles. Omitting it leaves 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 root layout containers or `Page`. ### Implicit Styles and BasedOn Always use `BasedOn` when overriding default control styles. Without it, your style **replaces** the entire default style rather than extending it: ```xml ``` ## Common API Replacements | WPF Code | WinUI Replacement | Notes | |---|---|---| | `Application.Current.Dispatcher.Invoke(...)` | `App.MainWindow.DispatcherQueue.TryEnqueue(...)` | Fire-and-forget; no synchronous `Invoke`. See awaitable example below. | | `Application.Current.MainWindow` | `App.MainWindow` (captured at startup) | Use the app's main window reference in WinUI/Uno. | | `Clipboard` (System.Windows) | `Windows.ApplicationModel.DataTransfer.Clipboard` | Different API surface | | `MessageBox.Show()` | `ContentDialog` with `XamlRoot` | No MessageBox in WinUI | For awaitable dispatch, wrap `DispatcherQueue.TryEnqueue(...)` with a `TaskCompletionSource`: ```csharp var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); if (!App.MainWindow.DispatcherQueue.TryEnqueue(() => { try { /* work */ tcs.TrySetResult(true); } catch (Exception ex) { tcs.TrySetException(ex); } })) { tcs.TrySetException(new InvalidOperationException("Failed to enqueue work on the DispatcherQueue.")); } await tcs.Task; ``` ## Find-and-Replace Quick Reference ### XAML Attribute Replacements | Find | Replace With | Notes | |---|---|---| | `ContextMenu=` | `ContextFlyout=` | | | `{DynamicResource` | `{ThemeResource` | | | `{x:Static` | `{x:Bind` | | | `Visibility="Hidden"` (layout-preserving) | `Opacity="0"` with `IsHitTestVisible="False"` | Keeps layout space; combine with `IsTabStop="False"` for focusable controls | | `Visibility="Hidden"` (remove from layout) | `Visibility="Collapsed"` | Collapses space like WPF `Visibility="Collapsed"` | | `MouseLeftButtonDown` | `PointerPressed` | | | `MouseLeftButtonUp` | `PointerReleased` | | | `MouseEnter` | `PointerEntered` | | | `MouseLeave` | `PointerExited` | | | `MouseMove` | `PointerMoved` | | | `MouseWheel` | `PointerWheelChanged` | | | `Focusable="True"` | `IsTabStop="True"` | | | `TextWrapping="WrapWithOverflow"` | `TextWrapping="Wrap"` | | | `MediaElement` | `MediaPlayerElement` | | | `InputBindings` | `KeyboardAccelerators` | | | `KeyBinding` | `KeyboardAccelerator` | | ### 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 Use this prompt with an AI coding assistant to automate the mechanical translation of WPF XAML files: ````text You are a WPF-to-WinUI XAML migration assistant. Translate the following WPF XAML file to WinUI 3 XAML compatible with Uno Platform. Apply ALL of the following rules: NAMESPACE RULES: - Keep the default xmlns as-is - Replace clr-namespace references with "using:" syntax - Replace System.Windows.* with Microsoft.UI.Xaml.* RESOURCE RULES: - Replace {DynamicResource X} with {ThemeResource X} - Replace {x:Static X} with {x:Bind X} - Keep {StaticResource X} as-is CONTROL REPLACEMENTS: - Menu/MenuItem -> MenuBar/MenuBarItem/MenuFlyoutItem - ContextMenu -> ContextFlyout with MenuFlyout - ToolBar -> CommandBar with AppBarButton - StatusBar -> Grid at bottom of layout - TabControl -> TabView or NavigationView (Top mode) - DataGrid -> CommunityToolkit DataGrid - Label -> TextBlock - MediaElement -> MediaPlayerElement PROPERTY REPLACEMENTS: - Visibility="Hidden" -> WinUI has no direct `Hidden` state; when layout must be preserved, use `Opacity="0"` with `Visibility="Visible"` and also set `IsHitTestVisible="False"`; for focusable controls also set `IsTabStop="False"` and `AllowFocusOnInteraction="False"` so the element is not invisible-but-interactive; use `Visibility="Collapsed"` only when removing the element from layout is acceptable - TextWrapping="WrapWithOverflow" -> TextWrapping="Wrap" - Focusable -> IsTabStop EVENT REPLACEMENTS: - Mouse* events -> Pointer* equivalents - Remove Preview* tunneling events TRIGGER REPLACEMENTS: - Remove Style.Triggers, DataTrigger, EventTrigger - Create VisualStateManager.VisualStateGroups with StateTrigger BINDING UPGRADES: - Convert {Binding Path=X} to {x:Bind ViewModel.X, Mode=OneWay} - Replace MultiBinding with x:Bind function binding OUTPUT: Complete translated XAML with a list of manual follow-up items. WPF XAML to translate: ```xml ``` ```` ## 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 keep using {Binding} or must I switch to {x:Bind}?** `{Binding}` still works and is not mandatory to replace. However, `{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`. For invisible-but-layout-occupying behavior, set `Opacity="0"` while keeping `Visibility="Visible"`, and also set `IsHitTestVisible="False"`. If the control can receive focus, also set `IsTabStop="False"` and `AllowFocusOnInteraction="False"` so it does not remain invisible but interactive. **How do I handle preview/tunneling events?** WinUI 3 does not generally provide WPF-style preview/tunneling events. In Uno Platform, some preview keyboard events such as `PreviewKeyDown` and `PreviewKeyUp` are available on specific targets only, so they should not be treated as a general WinUI 3 migration equivalent. For cross-target and WinUI 3-compatible code, use `KeyDown`/`KeyUp` instead. WPF-style preview mouse/pointer events such as `PreviewMouseDown` do not generally have direct equivalents; use the corresponding bubbling event (for example, `PointerPressed`) and, if you need to observe events that were already marked handled, register with `AddHandler(..., handledEventsToo: true)`. **How do I migrate the Dispatcher pattern?** Replace `Application.Current.Dispatcher.Invoke(...)` with `App.MainWindow.DispatcherQueue.TryEnqueue(...)`. The `DispatcherQueue` API is asynchronous by default and has no synchronous `Invoke` method. **Does Uno Platform add controls beyond WinUI?** Yes. The [Uno Toolkit](xref:Toolkit.GettingStarted) includes NavigationBar, TabBar, DrawerControl, SafeArea, and more. The [Community Toolkit](uno-community-toolkit.md) controls (DataGrid, WrapPanel, DockPanel) also work across all Uno Platform targets.