WinUI / UWP
WinUI 3 and UWP are Microsoft's modern XAML frameworks, but they only target Windows. If your application needs to reach macOS, Linux, mobile, or the web, that is a hard ceiling. Avalonia uses a similar XAML model, supports the same MVVM patterns, and runs everywhere .NET runs.
If you already know WinUI or UWP, you are closer to Avalonia than you might think. The XAML dialect, data binding system, and control model are all familiar. The differences are mostly in styling, naming, and a few controls that work differently.
The Avalonia team has hands-on experience migrating WinUI and UWP applications to Avalonia. If you would like expert guidance, this is a service we provide. See Avalonia Services for more information.
Key differences
Styling
WinUI uses VisualStateManager with visual states and storyboards to handle control appearance changes. Avalonia replaces this entirely with CSS-like selectors and pseudo-classes.
WinUI (VisualStateManager):
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="RootBorder.Background" Value="{ThemeResource ButtonBackgroundPointerOver}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Avalonia (pseudo-classes):
<Style Selector="Button:pointerover /template/ Border#RootBorder">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
</Style>
Avalonia's approach is more concise and composable. For a full guide on how styling works, see Styles.
XAML namespace
| WinUI / UWP | Avalonia |
|---|---|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | xmlns="https://github.com/avaloniaui" |
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" | xmlns:controls="using:Avalonia.Controls" (usually not needed, default namespace covers most controls) |
clr-namespace: or using: for custom types | using: (preferred) or clr-namespace: |
Data binding
The core binding syntax is the same. WinUI's x:Bind (compiled bindings) has an equivalent in Avalonia:
| WinUI / UWP | Avalonia | Notes |
|---|---|---|
{Binding Path} | {Binding Path} | Same |
{x:Bind ViewModel.Name} | {Binding Name} with x:DataType | Avalonia uses x:CompileBindings and x:DataType for compiled bindings |
{Binding ElementName=myControl, Path=Text} | {Binding #myControl.Text} | #name shorthand |
{Binding RelativeSource={RelativeSource Self}} | {Binding $self.Property} | |
x:DefaultBindMode | x:CompileBindings="True" |
Controls
Most WinUI controls have direct equivalents in Avalonia. The main differences are in naming and a few controls that require separate packages.
| WinUI / UWP | Avalonia | Notes |
|---|---|---|
NavigationView | No direct equivalent | Use SplitView with a ListBox or a third-party control |
InfoBar | No direct equivalent | Use a styled Border with content |
TeachingTip | No direct equivalent | Use Popup or Flyout |
PersonPicture | No direct equivalent | Compose with Ellipse and Image |
RatingControl | No direct equivalent | Use a third-party control |
NumberBox | NumericUpDown | Different name |
Pivot | TabControl | |
PivotItem | TabItem | |
CalendarView | Calendar | |
CalendarDatePicker | CalendarDatePicker | Same |
CommandBar | Menu or ToolBar | |
ContentDialog | Dialog Window | Avalonia uses windows for dialogs |
MenuBar | Menu | |
MenuFlyout | ContextMenu | |
FlipView | Carousel | |
ProgressRing | No direct built-in equivalent | Use a third-party control or custom animation |
SplitView | SplitView | Same |
TreeView | TreeView | Same |
ListView / GridView | ListBox | Use ListBox with ItemTemplate and WrapPanel for grid layout |
Page / Frame | NavigationPage / ContentPage | See NavigationPage |
Navigation
Avalonia provides NavigationPage, a stack-based navigation system similar to WinUI's Frame and Page model. It supports pushing and popping pages with animated transitions, a built-in navigation bar with a back button, and modal presentation.
<NavigationPage xmlns="https://github.com/avaloniaui">
<ContentPage Header="Home">
<StackPanel Margin="16" Spacing="8">
<TextBlock Text="Home Page" FontSize="24" />
<Button Content="Go to Details" Click="OnGoToDetails" />
</StackPanel>
</ContentPage>
</NavigationPage>
// Push a new page onto the stack
await Navigation.PushAsync(new DetailsPage());
// Pop back to the previous page
await Navigation.PopAsync();
For applications that prefer a lighter approach, you can also handle navigation through view model composition by swapping the content of a ContentControl based on application state:
<ContentControl Content="{Binding CurrentPage}" />
Avalonia resolves the correct view automatically if you register data templates for each view model type. This approach works well for applications that do not need a navigation bar or animated page transitions.
For full details on NavigationPage, see NavigationPage.
Resources and theming
| WinUI / UWP | Avalonia | Notes |
|---|---|---|
ThemeResource | DynamicResource | Avalonia uses DynamicResource for theme-aware values |
StaticResource | StaticResource | Same |
ResourceDictionary.ThemeDictionaries | ResourceDictionary.ThemeDictionaries | Same concept |
ElementTheme.Light / .Dark | RequestedThemeVariant | |
AcrylicBrush | ExperimentalAcrylicBorder | Different API |
File structure
| WinUI / UWP | Avalonia |
|---|---|
.xaml extension | .axaml extension |
App.xaml | App.axaml |
MainWindow.xaml | MainWindow.axaml |
.xaml.cs code-behind | .axaml.cs code-behind |
Package.appxmanifest | No equivalent (standard .NET project) |
Threading
| WinUI / UWP | Avalonia |
|---|---|
DispatcherQueue.TryEnqueue() | Dispatcher.UIThread.Post() |
DispatcherQueue.GetForCurrentThread() | Dispatcher.UIThread |
CoreDispatcher.RunAsync() | Dispatcher.UIThread.InvokeAsync() |
What you gain
Moving from WinUI to Avalonia is not only about cross-platform. There are a few areas where Avalonia offers more than WinUI does today:
- CSS-like styling: Selectors, style classes, and pseudo-classes give you more control over styling with less verbosity than
VisualStateManager. - Compiled bindings with better tooling:
x:DataTypeandx:CompileBindingsprovide compile-time validation of binding paths across the entire project. - No MSIX/packaging requirement: Avalonia applications are standard .NET executables. No app manifest, no packaging pipeline, no store requirement.
- Linux and macOS as first-class targets: Not an afterthought or a compatibility layer.
See also
- Get Started with Avalonia: Create your first Avalonia application.
- Styles: How Avalonia's CSS-like styling works.
- Data Binding Syntax: Avalonia binding syntax reference.
- Controls Reference: Full Avalonia controls documentation.