XAML (eXtensible Application Markup Language) is a declarative XML-based language used to define user interfaces in Avalonia. This guide covers XAML fundamentals and Avalonia-specific features.
What is XAML?
XAML provides a clear separation between UI definition and application logic:
Declarative : Describe what you want, not how to create it
Type-safe : Compiled to strongly-typed code
Designer-friendly : Visual tools can edit XAML
Readable : Clear structure mirrors the visual hierarchy
XAML Definition
Equivalent C# Code
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Class = "MyApp.MainWindow"
Title = "My Application" >
< StackPanel >
< TextBlock Text = "Hello, Avalonia!" />
< Button Content = "Click Me" />
</ StackPanel >
</ Window >
XAML is much more concise and readable than equivalent C# code for UI definition.
Loading XAML
Avalonia provides the AvaloniaXamlLoader class to load XAML at runtime or use precompiled XAML.
Automatic Loading
By default, XAML is precompiled and loaded automatically:
using Avalonia . Controls ;
using Avalonia . Markup . Xaml ;
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
}
private void InitializeComponent ()
{
AvaloniaXamlLoader . Load ( this );
}
}
The AvaloniaXamlLoader.Load(this) call looks for precompiled XAML. If not found, it throws an exception prompting you to set x:Class and include the file as AvaloniaResource.
Manual XAML Loading
You can load XAML from URIs:
using Avalonia . Markup . Xaml ;
// Load from relative URI
var control = AvaloniaXamlLoader . Load (
new Uri ( "Views/MyView.axaml" , UriKind . Relative ),
baseUri : new Uri ( "avares://MyApp/" ));
// Load from absolute URI
var absoluteControl = AvaloniaXamlLoader . Load (
new Uri ( "avares://MyApp/Views/MyView.axaml" ));
XAML Namespaces
Default Namespace
The default namespace includes all Avalonia controls:
< Window xmlns = "https://github.com/avaloniaui" >
<!-- All built-in controls available -->
< Button Content = "Click" />
</ Window >
XAML Namespace (x:)
The x: namespace provides XAML language features:
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Class = "MyApp.MainWindow"
x:Name = "MainWindowInstance" >
<!-- x: prefix for XAML directives -->
</ Window >
Custom Namespaces
Map CLR namespaces to XML namespaces:
CLR Namespace
External Assembly
Using Directive
< Window xmlns = "https://github.com/avaloniaui"
xmlns:vm = "clr-namespace:MyApp.ViewModels"
xmlns:local = "clr-namespace:MyApp.Views" >
< Window.DataContext >
< vm:MainWindowViewModel />
</ Window.DataContext >
< local:CustomControl />
</ Window >
< Window xmlns = "https://github.com/avaloniaui"
xmlns:controls = "clr-namespace:CustomLib.Controls;assembly=CustomLib" >
< controls:SpecialButton Content = "From Library" />
</ Window >
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm = "using:MyApp.ViewModels" >
<!-- using: is an alternative to clr-namespace: -->
< Window.DataContext >
< vm:MainWindowViewModel />
</ Window.DataContext >
</ Window >
XAML Syntax
Property Element Syntax
Complex properties use element syntax:
< Button >
<!-- Content as property element -->
< Button.Content >
< StackPanel >
< TextBlock Text = "Line 1" />
< TextBlock Text = "Line 2" />
</ StackPanel >
</ Button.Content >
</ Button >
Attached Properties
Properties defined by one class but used on another:
< Grid >
< Grid.RowDefinitions >
< RowDefinition Height = "Auto" />
< RowDefinition Height = "*" />
</ Grid.RowDefinitions >
<!-- Grid.Row is an attached property -->
< TextBlock Grid.Row = "0" Text = "Header" />
< TextBlock Grid.Row = "1" Text = "Content" />
</ Grid >
Markup Extensions
Provide dynamic values using {Extension} syntax:
< TextBlock Text = "{Binding UserName}" />
< TextBlock Text = "{Binding Path=UserName, Mode=TwoWay}" />
< Window.Resources >
< SolidColorBrush x:Key = "AccentBrush" Color = "#007ACC" />
</ Window.Resources >
< Border Background = "{StaticResource AccentBrush}" />
<!-- Updates when resource changes -->
< Border Background = "{DynamicResource ThemeBackgroundBrush}" />
< ControlTemplate TargetType = "Button" >
< Border Background = "{TemplateBinding Background}" >
< ContentPresenter Content = "{TemplateBinding Content}" />
</ Border >
</ ControlTemplate >
XAML Compilation
Avalonia precompiles XAML for performance and trim-safety.
Build Configuration
Ensure XAML files have the correct build action:
< ItemGroup >
< AvaloniaResource Include = "**/*.axaml" />
<!-- Or for specific files -->
< AvaloniaResource Include = "Views/MainWindow.axaml" />
</ ItemGroup >
x:Class Directive
Connects XAML to code-behind:
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Class = "MyApp.Views.MainWindow" >
<!-- ... -->
</ Window >
namespace MyApp . Views ;
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
}
}
The namespace and class name in x:Class must exactly match the code-behind class, or compilation will fail.
Accessing Named Elements
Use x:Name to access elements from code:
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Class = "MyApp.MainWindow" >
< StackPanel >
< TextBox x:Name = "NameInput" />
< Button x:Name = "SubmitButton"
Content = "Submit"
Click = "OnSubmitClick" />
</ StackPanel >
</ Window >
Design-Time Attributes
Provide data for the previewer:
< Window xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm = "using:MyApp.ViewModels"
mc:Ignorable = "d"
d:DesignWidth = "800" d:DesignHeight = "450"
x:DataType = "vm:MainWindowViewModel"
x:CompileBindings = "True" >
< Design.DataContext >
< vm:MainWindowViewModel />
</ Design.DataContext >
<!-- UI Definition -->
</ Window >
d:DesignWidth/Height: Preview size
mc:Ignorable="d": Ignore design-time namespaces at runtime
x:DataType: Enable compiled bindings
Design.DataContext: Design-time data context
Common XAML Patterns
Resource Dictionaries
< Application xmlns = "https://github.com/avaloniaui"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
x:Class = "MyApp.App" >
< Application.Resources >
< ResourceDictionary >
<!-- Inline resources -->
< SolidColorBrush x:Key = "PrimaryBrush" Color = "#007ACC" />
<!-- Merged dictionaries -->
< ResourceDictionary.MergedDictionaries >
< ResourceInclude Source = "/Styles/Colors.axaml" />
< ResourceInclude Source = "/Styles/Buttons.axaml" />
</ ResourceDictionary.MergedDictionaries >
</ ResourceDictionary >
</ Application.Resources >
</ Application >
Styles
< Window.Styles >
< Style Selector = "Button.primary" >
< Setter Property = "Background" Value = "#007ACC" />
< Setter Property = "Foreground" Value = "White" />
< Setter Property = "Padding" Value = "12,6" />
</ Style >
< Style Selector = "Button.primary:pointerover" >
< Setter Property = "Background" Value = "#005A9E" />
</ Style >
</ Window.Styles >
< Button Classes = "primary" Content = "Primary Action" />
Data Templates
< Window.DataTemplates >
< DataTemplate DataType = "vm:PersonViewModel" >
< StackPanel >
< TextBlock Text = "{Binding Name}" FontWeight = "Bold" />
< TextBlock Text = "{Binding Email}" Foreground = "Gray" />
</ StackPanel >
</ DataTemplate >
</ Window.DataTemplates >
< ItemsControl ItemsSource = "{Binding People}" />
Best Practices
Always set x:Class
Required for XAML compilation and code-behind connection.
Use compiled bindings
Set x:DataType and x:CompileBindings="True" for better performance and type safety.
Organize with resource dictionaries
Split large XAML files into themed resource dictionaries.
Leverage design-time attributes
Use d:DesignWidth, Design.DataContext for better previewer experience.
Prefer XAML for UI, C# for logic
Keep event handlers and business logic in code, structure in XAML.