Every cross-platform target requires some XAML rework. The right question is not "which is drop-in" (none are, fully). The right question is: for the patterns my codebase actually uses, how much survives a search-and-replace, and where do I need to think?
WPF XAML migrates most cleanly to the WinUI 3 / Microsoft.UI.Xaml surface used by Uno Platform: namespace and binding changes are mechanical, layout panels and standard controls map directly, and MVVM patterns transfer unchanged. No cross-platform XAML target is fully drop-in for WPF; the size and shape of the deltas vary by target.
This guide covers four pattern groups, in order of how much rework they typically require: namespaces (mechanical), layout and controls (mechanical with edge cases), bindings and resources (mostly mechanical with semantic differences), and templates and advanced controls (manual).
Namespaces and Root Elements
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp.Controls"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Controls"The default and x: namespaces are identical. The local-namespace prefix changes from clr-namespace: to using:. Mechanical search-and-replace handles every case.
| WPF | WinUI 3 / Uno Platform |
|---|---|
<Window> | <Page> (windows are an app-shell concept) |
<UserControl> | <UserControl> (same) |
<Application> | <Application> (same shape, different startup wiring) |
Window to Page is an architectural decision, not a mechanical swap. Cross-platform apps think in pages with navigation, not in floating windows. WinUI 3 supports multiple windows on Windows; mobile and WASM targets do not.
Layout Panels and Standard Controls
The standard layout and control surface maps directly. The XAML you wrote in WPF works in Uno Platform with namespace updates only.
| Pattern | WPF | WinUI / Uno |
|---|---|---|
| Grid layout | <Grid><Grid.RowDefinitions>...</Grid> | Same |
| StackPanel | <StackPanel Orientation="Vertical"> | Same |
| Border | <Border BorderBrush="Black"> | Same |
| Button | <Button Content="OK" Click="OnOk" /> | Same |
| TextBox | <TextBox Text="{Binding Name}" /> | Same (binding syntax below) |
| TextBlock | <TextBlock Text="Hello" /> | Same |
| ComboBox | <ComboBox ItemsSource="{Binding}" /> | Same |
| ListBox / ListView | Both supported | Both supported; ItemsRepeater recommended for large collections |
| ContentControl | <ContentControl Content="{Binding}" /> | Same |
Property Edge Cases to Verify Per Page
Visibilityenum: WPF hasCollapsed,Hidden,Visible. WinUI 3 has onlyCollapsedandVisible. If you usedHidden, replace with a layout strategy.- Mouse events: WPF
MouseDown/MouseMovebecome WinUIPointerPressed/PointerMovedfor unified pointer input. - Default alignment: Same on both, but verify on
TextBoxspecifically where stretching defaults can differ.
Bindings and Resources
This is the layer where WPF and WinUI 3 diverge most, and where the move pays off long-term. WinUI 3 introduces x:Bind (compile-time, faster, type-checked) alongside the runtime {Binding} you know from WPF.
| WPF | WinUI / Uno | Notes |
|---|---|---|
{Binding Name} | {Binding Name} or {x:Bind ViewModel.Name} | x:Bind is compile-time, faster, more strict |
{Binding Path=Name, Mode=TwoWay} | {Binding Path=Name, Mode=TwoWay} | Same |
{StaticResource Foo} | {StaticResource Foo} | Same |
{DynamicResource Foo} | {ThemeResource Foo} | ThemeResource is theme-aware; narrower semantics |
{Binding RelativeSource={RelativeSource Self}} | {Binding ElementName=this} or x:Bind | Verify per usage |
{Binding ElementName=textBox, Path=Text} | {Binding ElementName=textBox, Path=Text} | Same |
x:Bind in Practice
<TextBox Text="{Binding Path=UserName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" /><TextBox Text="{x:Bind ViewModel.UserName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />1. The path is rooted in the page's code-behind, not its DataContext. So {x:Bind ViewModel.UserName} requires a ViewModel property in the page class. 2. The path is type-checked at compile time. Misspelled names fail the build instead of failing silently at runtime. This is a feature.
Resource Dictionaries and Themes
Resource dictionaries port directly. The structural differences are:
- Theme dictionaries are first-class:
<ResourceDictionary.ThemeDictionaries>withx:Key="Light"/"Dark"keys. - Theme keys differ.
SystemControlForegroundBaseHighBrush(WinUI) vs. WPFSystemColors.ControlTextBrushKey. Map per usage. DynamicResourcebecomesThemeResource.
For theme infrastructure on Uno Platform, the Uno Toolkit provides a Material Design 3 theme out of the box, and the Uno Material package adds full Material theming support.
Styles and ControlTemplates
Styles and templates port with more care. The shape is identical:
<Style TargetType="Button">
<Setter Property="Padding" Value="16,8" />
<Setter Property="Background"
Value="{ThemeResource AccentFillColorDefaultBrush}" />
</Style>Where templates touch internal control parts (PART_ContentPresenter, visual states, control template hooks), expect manual work. WinUI 3 has its own visual-state machine and template parts that differ from WPF. Plan 1 to 3 hours per templated control for the rewrite, with about 50 percent AI-agent coverage.
Where the Mapping Does Not Transfer Cleanly
Be honest about what does not port:
| WPF Feature | Migration Reality |
|---|---|
FlowDocument and rich documents | Limited equivalents; rebuild as needed |
RichTextBox advanced features | WinUI RichEditBox covers core cases; advanced features need rework |
3D (Viewport3D) | Not supported on WinUI 3 / Uno Platform; replace with a different approach |
| Triggers in styles | Replaced by Visual State Manager; rewrite required |
MultiBinding | Supported but with differences; verify per usage |
WindowChrome | Replace with WinUI Window.SystemBackdrop and custom title bar APIs |
These are not blockers but they are not search-and-replace work. Audit your codebase for them before quoting.
Choosing Across Targets on Dialect Proximity
For teams whose primary criterion is WPF XAML proximity, the credible options sit on a spectrum:
| Target | Proximity to WPF XAML |
|---|---|
| Stay on WPF | Identical (you keep the XAML you have) |
| Commercial WPF-API-compatible fork | API-compatible with WPF (vendor-specific; commercial license required) |
| Uno Platform / WinUI 3 | Close: namespaces and bindings change, control surface largely matches |
| Independent cross-platform XAML | Independent dialect with similar concepts; expect a meaningful manual port |
| .NET MAUI | Different (mobile-first lineage from Xamarin Forms) |
There is no universally correct answer. Pick by your codebase content and your team's investment in the WPF surface specifically vs. the broader Microsoft.UI.Xaml direction.
Take one representative WPF page and run it through the mapping above. Most cases finish in under 30 minutes per page with AI-agent assistance grounded in Uno Platform docs. Start a free trial of Uno Platform Studio Pro to get access to the App MCP for runtime verification alongside the Docs MCP.
Subscribe to Our Blog
Subscribe via RSS
Back to Top