Skip to main content
Avalonia UI is built on a modular, layered architecture that provides a robust foundation for cross-platform desktop applications. This guide explores the framework’s core components and how they work together.

Architectural Overview

Avalonia’s architecture consists of several key layers:
┌─────────────────────────────────────┐
│     Application Layer               │
│  (Your App, Views, ViewModels)      │
├─────────────────────────────────────┤
│     Controls & Markup               │
│  (UI Components, XAML)              │
├─────────────────────────────────────┤
│     Core Framework                  │
│  (Styling, Data Binding, Layout)    │
├─────────────────────────────────────┤
│     Platform Abstraction            │
│  (Rendering, Input, Windowing)      │
└─────────────────────────────────────┘

Core Components

Application Class

The Application class is the entry point and central coordinator for Avalonia applications. It manages:
  • Global Resources: Application-wide resource dictionaries
  • Global Styles: Styles that apply to all windows
  • Data Templates: Templates for rendering data objects
  • Service Registration: Dependency injection and service locator pattern
  • Lifecycle Management: Application startup and shutdown
using Avalonia.Controls;
using Avalonia.Styling;

public class Application : AvaloniaObject, 
    IDataContextProvider, 
    IGlobalDataTemplates, 
    IGlobalStyles, 
    IThemeVariantHost
{
    // Global data templates for custom data rendering
    public DataTemplates DataTemplates { get; }
    
    // Global styles applied to all windows
    public Styles Styles { get; }
    
    // Global resource dictionary
    public IResourceDictionary Resources { get; set; }
    
    // Application lifetime manager
    public IApplicationLifetime? ApplicationLifetime { get; set; }
    
    // Theme variant management (Light/Dark)
    public ThemeVariant? RequestedThemeVariant { get; set; }
    public ThemeVariant ActualThemeVariant { get; }
    
    // Service registration
    public virtual void RegisterServices() { }
    
    // XAML initialization
    public virtual void Initialize() { }
}
The Application.Current static property provides global access to the current application instance from anywhere in your code.

AppBuilder Pattern

Avalonia uses a fluent builder pattern to configure platform-specific services:
Program.cs
using Avalonia;
using System;

class Program
{
    [STAThread]
    public static void Main(string[] args) => BuildAvaloniaApp()
        .StartWithClassicDesktopLifetime(args);

    public static AppBuilder BuildAvaloniaApp()
        => AppBuilder.Configure<App>()
            .UsePlatformDetect()      // Auto-detect platform
            .WithInterFont()          // Use Inter font
            .LogToTrace();            // Enable logging
}
Key AppBuilder Responsibilities:
Initializes core platform services like asset loading, reflection helpers, and runtime utilities.
builder.UseStandardRuntimePlatformSubsystem();
Configures platform-specific windowing (Win32, X11, Cocoa, etc.).
builder.UsePlatformDetect(); // Auto-selects appropriate platform
Sets up the rendering backend (typically Skia).
builder.UseSkia(); // Use Skia for rendering
Configures text rendering and shaping.
builder.UseHarfBuzz(); // Use HarfBuzz for text shaping

Service Locator Pattern

Avalonia uses AvaloniaLocator for dependency injection and service resolution:
Service Registration (from Application.cs)
public virtual void RegisterServices()
{
    AvaloniaSynchronizationContext.InstallIfNeeded();
    InputManager = new InputManager();

    AvaloniaLocator.CurrentMutable
        .Bind<IAccessKeyHandler>().ToTransient<AccessKeyHandler>()
        .Bind<IGlobalDataTemplates>().ToConstant(this)
        .Bind<IGlobalStyles>().ToConstant(this)
        .Bind<IInputManager>().ToConstant(InputManager)
        .Bind<IToolTipService>().ToConstant(new ToolTipService(InputManager))
        .Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>()
        .Bind<IDragDropDevice>().ToConstant(DragDropDevice.Instance);
}
You can access services using AvaloniaLocator.Current.GetService<TService>() or extend the service registration in your own Application.RegisterServices() override.

Component Hierarchy

Object Model

Avalonia’s object model follows this inheritance chain:
AvaloniaObject (Property System)

StyledElement (Styling Support)

Visual (Rendering & Visual Tree)

Layoutable (Layout System)

Control (Events & Templating)

Specific Controls (Button, TextBox, etc.)

Key Base Classes

AvaloniaObject

Foundation for the property system. Provides styled and direct properties with change notifications.

StyledElement

Adds styling capabilities, including style application and resource lookups.

Visual

Manages the visual tree, hit testing, transformations, and rendering.

Layoutable

Implements the layout system with measure and arrange passes.

Platform Abstraction

Avalonia abstracts platform-specific functionality through interfaces:
  • IPlatformSettings: Platform-specific settings (theme, accent colors)
  • IWindowingPlatform: Window creation and management
  • IRenderTarget: Rendering surface abstraction
  • IClipboard: Clipboard operations
  • IStorageProvider: File system access
Accessing Platform Services
// Get platform settings
var settings = Application.Current?.PlatformSettings;
if (settings != null)
{
    var colorValues = settings.GetColorValues();
    var themeVariant = colorValues.ThemeVariant;
}

Threading Model

Avalonia is single-threaded by design. All UI operations must occur on the UI thread.
The framework uses Dispatcher for thread marshalling:
Thread Marshalling
using Avalonia.Threading;

// Execute on UI thread
await Dispatcher.UIThread.InvokeAsync(() =>
{
    // Update UI here
    myControl.Text = "Updated from background thread";
});

// Check if on UI thread
if (Dispatcher.UIThread.CheckAccess())
{
    // Already on UI thread
}
else
{
    // Marshal to UI thread
    Dispatcher.UIThread.Post(() => { /* UI work */ });
}

Feature Discovery

Avalonia provides optional feature discovery through IOptionalFeatureProvider:
Feature Detection
var platformSettings = Application.Current?.TryGetFeature<IPlatformSettings>();
if (platformSettings != null)
{
    // Platform settings available
}
Currently supported features:
  • IPlatformSettings - Platform-specific settings
  • IActivatableLifetime - Application activation events

Best Practices

1

Initialize in order

Follow the proper initialization sequence: configure AppBuilder → register services → initialize application → set up lifetime.
2

Use the locator sparingly

Prefer dependency injection over service locator pattern when possible. Use AvaloniaLocator for framework-level services.
3

Respect the threading model

Always update UI from the UI thread. Use Dispatcher.UIThread for marshalling from background threads.
4

Leverage feature detection

Use TryGetFeature<T>() to gracefully handle platform differences and optional functionality.

Build docs developers (and LLMs) love