У попередній статті ви створили свій перший WPF-застосунок. Ви написали XAML-розмітку, додали обробник кліку у code-behind та побачили перше вікно на екрані. Це великий крок.
Але є одна деталь: ваш WPF-застосунок запуститься лише на Windows. Якщо колега з macOS спробує запустити ваш .exe — він побачить помилку. Якщо розгорнути на Linux-сервері з GUI — нічого не вийде.
Ось тут на сцену виходить Avalonia.
.axaml — розширення файлів розмітки в Avalonia (аналог .xaml). Program.cs — точка входу в Avalonia-застосунок (аналог App.xaml у WPF). DevTools — вбудований інспектор Avalonia UI (аналог Snoop, але з коробки). Companion-стаття — супутня стаття після WPF-уроку, що показує відмінності Avalonia.Ось що дивовижно: якщо ви знаєте WPF — ви вже знаєте 80% Avalonia. Та сама декларативна XAML-розмітка, той самий принцип Data Binding, той самий підхід MVVM, ті ж назви контролів — Button, TextBlock, TextBox, StackPanel, Grid.
Різниця в одному: WPF рендерить через DirectX і живе лише на Windows. Avalonia рендерить через Skia — ту саму бібліотеку, яку використовує Flutter від Google — і запускається де завгодно.
Ось конкретний список де може працювати Avalonia-застосунок:
Desktop
Mobile & Web
Embedded
Один і той самий C# код, одна і та сама XAML-розмітка — і він запускається на всьому цьому. Без змін. Це і є сила Avalonia.
Щоб зрозуміти Avalonia, треба спочатку зрозуміти, чому WPF не є кросплатформним. Це питання архітектурне.
WPF рендерить через DirectX — графічний API Microsoft, що існує виключно на Windows. Міст між WPF і DirectX — це нативна бібліотека milcore.dll, що написана на C++ і інтегрована в Windows. Без неї WPF не може намалювати жодного пікселя.
Крім того, WPF залежить від Windows Message Loop — механізму повідомлень Windows (WM_PAINT, WM_KEYDOWN, WM_MOUSEDOWN тощо). Це означає прив'язку до Win32 API.
Всі ці залежності роблять перенесення WPF на інші ОС практично неможливим без повного переписування ядра.
Avalonia використовує принципово інший підхід: абстрагує рендеринг через SkiaSharp — .NET-обгортку над бібліотекою Skia від Google.
Ось як це виглядає архітектурно:
Avalonia самостійно малює весь UI через Skia — від пікселів кнопки до тексту у TextBox. Системні контроли ОС вона не використовує. Це навіть перевага: UI виглядає однаково на всіх платформах, бо всі пікселі малюються одним рушієм.
Єдине, що бере від платформи Avalonia — вікно (нативне вікно ОС для отримання подій введення та відображення) та нативні файлові діалоги (на macOS виглядають по-маківськи, на Windows — по-вінівськи).
Skia — 2D-графічна бібліотека від Google, написана на C++. Вона рендерить текст, криві Безьє, градієнти, тіні, прямокутники — все, що потрібно для UI. Skia використовується у:
Тобто коли ви запускаєте Chrome — ваш браузер малює пікселі тією самою бібліотекою, що і Avalonia-застосунок. Перевірена мільярдами пристроїв технологія.
Перш ніж писати код, корисно мати загальну картину: що спільного, що різного.
| Концепція | WPF | Avalonia |
|---|---|---|
| Мова розмітки | XAML | XAML (.axaml) |
| Data Binding | {Binding Path=Name} | {Binding Path=Name} |
| Команди | ICommand | ICommand |
| MVVM | Класичний MVVM | Класичний MVVM + ReactiveUI |
| Панелі | StackPanel, Grid, DockPanel | ✅ Ті самі |
| Контроли | Button, TextBox, ComboBox... | ✅ Ті самі назви |
| Ресурси | ResourceDictionary | ResourceDictionary |
| Стилі | Style з Setter | Style з Setter |
| DataTemplate | ✅ Є | ✅ Є |
| ControlTemplate | ✅ Є | ✅ Є |
Цей список — причина, чому кажуть: "знаєш WPF — знаєш Avalonia". Більшість коду, яку ви пишете у WPF, можна перенести в Avalonia з мінімальними змінами.
| Аспект | WPF | Avalonia |
|---|---|---|
| Платформа | Windows only | Windows, macOS, Linux, iOS, Android, WASM |
| Рендеринг | DirectX | Skia (SkiaSharp) |
| Розширення файлів | .xaml, .xaml.cs | .axaml, .axaml.cs |
| Точка входу | App.xaml з StartupUri | Program.cs з BuildAvaloniaApp() |
| Стилізація | XAML-стилі, Triggers | XAML-стилі + CSS-like селектори, Pseudo-classes |
| Скомпільовані Binding | ❌ (тільки Reflection) | ✅ x:CompileBindings |
| DevTools | Snoop (зовнішній) | ✅ Вбудовані DevTools (F12) |
| Open-source | Частково (CoreWPF) | ✅ Повністю (MIT) |
| MVVM-фреймворк | MVVM Toolkit (Microsoft) | ReactiveUI (рекомендований) |
| Triggers | DataTrigger, Trigger | ❌ → Pseudo-classes, Behaviors |
27a, Compiled Bindings у 17a, ReactiveUI у 25a тощо.На відміну від WPF, шаблони Avalonia не включені в .NET SDK за замовчуванням. Їх потрібно встановити окремо.
dotnet new install Avalonia.Templates
Після виконання цієї команди у вас з'являться нові шаблони для dotnet new. Перевірте:
dotnet new list | grep avalonia
Для комфортної розробки встановіть розширення з підтримкою .axaml файлів:
Або через командний рядок:
# Avalonia Extension for VS 2022
# Встановлюється через Marketplace:
# https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio2022
Rider має вбудовану підтримку Avalonia починаючи з версії 2023.x. Встановіть плагін для повноцінного синтаксису:
Тепер створимо проєкт. Зверніть увагу: є два основних шаблони, і важливо розуміти різницю між ними.
dotnet new avalonia.app -n MyAvaloniaApp # Базовий — без MVVM
dotnet new avalonia.mvvm -n MyAvaloniaApp # З MVVM та ReactiveUI
avalonia.app — мінімальний шаблон. Структура схожа на WPF: є App.axaml, MainWindow.axaml, MainWindow.axaml.cs. Для наших цілей знайомства — ідеальний вибір.
avalonia.mvvm — шаблон з інтегрованим ReactiveUI, ViewModels, ViewLocator. Значно складніша структура. Для вивчення MVVM у Avalonia — але ще не зараз.
Для цієї статті використовуємо avalonia.app:
dotnet new avalonia.app -n MyAvaloniaApp
cd MyAvaloniaApp
dotnet run
Вікно відкривається. Текст "Welcome to Avalonia!" — перший Avalonia-застосунок готовий.
Порівняємо структуру WPF-проєкту та Avalonia-проєкту. Вони схожі, але є важливі відмінності.
MyWpfApp/
├── App.xaml ← Application + StartupUri
├── App.xaml.cs ← partial class App : Application
├── MainWindow.xaml ← Розмітка вікна (XAML)
├── MainWindow.xaml.cs ← Code-behind (partial class)
├── MyWpfApp.csproj ← <UseWPF>true</UseWPF>
└── AssemblyInfo.cs
MyAvaloniaApp/
├── App.axaml ← Application (без StartupUri!)
├── App.axaml.cs ← partial class App : Application
├── MainWindow.axaml ← Розмітка вікна (.axaml!)
├── MainWindow.axaml.cs ← Code-behind (partial class)
├── Program.cs ← 🆕 Точка входу (немає у WPF!)
├── MyAvaloniaApp.csproj ← Інші NuGet-пакети
└── app.manifest ← (якщо Windows target)
Відразу помітно кілька відмінностей. Розберемо кожну детально.
.axaml замість .xamlПерше, що кидається в очі — всі XAML-файли мають розширення .axaml замість .xaml. Чому?
Причина суто практична: у проєкті, де одночасно встановлений і WPF, і Avalonia (або де розробник використовує Visual Studio), .xaml файли автоматично асоціюються з WPF XAML Designer. Це спричиняло конфлікти — дизайнер WPF намагався відкрити Avalonia XAML і падав з помилками.
Розширення .axaml (Avalonia XAML) вирішує цю проблему: інструменти не плутаються, який дизайнер використовувати.
.xaml файли — синтаксис абсолютно однаковий. Розширення .axaml — це конвенція, а не технічна вимога. Але рекомендується завжди використовувати .axaml для Avalonia-проєктів, щоб уникнути плутанини.Program.cs — нова точка входуУ WPF точка входу прихована всередині WPF-інфраструктури. Ви ніколи не бачите Main() — він генерується автоматично на основі App.xaml.
В Avalonia є явний файл Program.cs з методом Main():
using Avalonia;
using System;
namespace MyAvaloniaApp;
class Program
{
// Точка входу - явна!
[STAThread]
public static void Main(string[] args)
=> BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
// Конфігурація Avalonia
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect() // Автоматично обирає платформу
.WithInterFont() // Підключає шрифт Inter
.LogToTrace(); // Логування у Trace output
}
Розберемо кожен рядок методу BuildAvaloniaApp():
AppBuilder.Configure<App>() — починає конфігурацію застосунку, вказує клас App як кореневий.
.UsePlatformDetect() — ключовий рядок кросплатформності. Avalonia автоматично визначає поточну ОС і налаштовує відповідний backend: Win32 на Windows, Cocoa на macOS, GTK на Linux. Ви можете вказати платформу явно: .UseWin32() або .UseX11() — але UsePlatformDetect() обирає правильне автоматично.
.WithInterFont() — підключає шрифт Inter — стандартний шрифт Avalonia для Fluent Theme. Без нього UI буде використовувати системний шрифт.
.LogToTrace() — включає логування Avalonia у System.Diagnostics.Trace. Дуже корисно при дебагу Binding-помилок — вони з'являться у вікні Output замість мовчазного ігнорування.
.StartWithClassicDesktopLifetime(args) — запускає звичайний desktop lifecycle: відкриває головне вікно, запускає message loop, завершується коли закрити останнє вікно. Аналог поведінки WPF за замовчуванням.
Program.cs — це перевага, а не ускладнення. У WPF для кастомної ініціалізації (наприклад, DI-контейнера) доводиться перевизначати OnStartup() в App.xaml.cs і боротися з StartupUri. В Avalonia логіка ініціалізації природно розміщується в Main() або в BuildAvaloniaApp().App.axaml без StartupUriПорівняємо App.xaml (WPF) та App.axaml (Avalonia):
<Application x:Class="MyWpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyAvaloniaApp.App"
xmlns:local="using:MyAvaloniaApp"
RequestedThemeVariant="Default">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
Відразу видно кілька ключових відмінностей:
xmlns="https://github.com/avaloniaui" замість http://schemas.microsoft.com/winfx/2006/xaml/presentation. Це головний namespace Avalonia — всі контроли Avalonia живуть тут.
xmlns:x залишається тим самим — http://schemas.microsoft.com/winfx/2006/xaml. Спеціальні директиви XAML (x:Class, x:Name, x:Type) є частиною стандарту XAML, не WPF-специфічні.
Немає StartupUri — тому що в Avalonia стартове вікно задається в App.axaml.cs через OnFrameworkInitializationCompleted().
RequestedThemeVariant="Default" — задає тему (Light/Dark/Default). WPF не має вбудованого Light/Dark за замовчуванням.
<Application.Styles><FluentTheme/></Application.Styles> — Avalonia явно підключає тему. У WPF тема вибирається системою автоматично (Aero у Windows 7, Aero2 у Windows 10 тощо). В Avalonia ви самі обираєте: FluentTheme (Windows 11-стиль), SimpleTheme (мінімалістична), або кастомна.
App.axaml.cs і OnFrameworkInitializationCompletedusing Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace MyAvaloniaApp;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this); // Завантажує App.axaml
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Ось тут задається стартове вікно!
desktop.MainWindow = new MainWindow();
}
base.OnFrameworkInitializationCompleted();
}
}
Де у WPF StartupUri="MainWindow.xaml" автоматично створює та показує вікно, тут ми явно пишемо desktop.MainWindow = new MainWindow(). Це надає більше гнучкості: можна передати параметри у конструктор, встановити DataContext, показати splash-screen перш ніж відкрити головне вікно.
Перевірка ApplicationLifetime is IClassicDesktopStyleApplicationLifetime — тому що Avalonia підтримує різні lifecycle-режими: desktop, single view (мобіль), browser (WASM). Ця перевірка гарантує, що ми у desktop-режимі.
MainWindow.axamlВідкрийте MainWindow.axaml. Ось що ви побачите:
<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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="MyAvaloniaApp.MainWindow"
Title="MyAvaloniaApp">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Welcome to Avalonia!" />
</StackPanel>
</Window>
Якщо порівняти з WPF MainWindow.xaml — різниця мінімальна:
| Елемент | WPF | Avalonia |
|---|---|---|
| Namespace | http://schemas.microsoft.com/winfx/2006/xaml/presentation | https://github.com/avaloniaui |
x:Class | MyWpfApp.MainWindow | MyAvaloniaApp.MainWindow |
xmlns:x | ✅ Той самий | ✅ Той самий |
xmlns:d, xmlns:mc | ✅ Ті самі | ✅ Ті самі |
d:DesignWidth/Height | ✅ Є | ✅ Є |
Title, Width, Height | ✅ Ті самі | ✅ Ті самі |
| Вміст (StackPanel, TextBlock) | ✅ Синтаксис ідентичний | ✅ Синтаксис ідентичний |
Зовнішньо — практично те саме. Єдина помітна відмінність — namespace URI.
Давайте подивимося на повне side-by-side порівняння найважливіших файлів:
.csproj<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework> <!-- Без -windows! -->
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.2.x" />
<PackageReference Include="Avalonia.Desktop" Version="11.2.x" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.x" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.x" />
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.x" />
</ItemGroup>
</Project>
Ключова відмінність у .csproj:
net8.0-windows (Windows only) + <UseWPF>true</UseWPF>net8.0 (без суфікса!) + NuGet-пакетиВідсутність -windows суфікса — це і є кросплатформність. Той самий проєкт збирається на будь-якій ОС де є .NET SDK.
| Аспект | WPF | Avalonia |
|---|---|---|
| Файл | (прихований, генерований) | Program.cs |
| Метод | (автогенерований Main()) | Явний public static Main() |
| Стартове вікно | StartupUri="MainWindow.xaml" | desktop.MainWindow = new MainWindow() |
| Конфігурація | OnStartup() в App.xaml.cs | BuildAvaloniaApp() в Program.cs |
| Файл | WPF | Avalonia |
|---|---|---|
| XAML namespace | http://schemas.microsoft.com/winfx/2006/xaml/presentation | https://github.com/avaloniaui |
| x: namespace | http://schemas.microsoft.com/winfx/2006/xaml | ✅ Той самий |
| Клас розширення | .xaml, .xaml.cs | .axaml, .axaml.cs |
| Import namespace | xmlns:local="clr-namespace:MyApp" | xmlns:local="using:MyApp" |
Рядок xmlns:local="using:MyApp" замість xmlns:local="clr-namespace:MyApp" — дрібниця, але корисна деталь. Хоча Avalonia підтримує обидва формати, скорочений using: є рекомендованим.
Щоб побачити наскільки подібний код — ось наш застосунок з привітанням з попередньої статті, переписаний на Avalonia.
Зміни мінімальні:
<Window x:Class="MyWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Мій перший WPF"
Width="450" Height="320"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="24">
<TextBlock Text="Введіть своє ім'я:"
FontSize="14"/>
<TextBox x:Name="nameInput"
FontSize="14"
Padding="8,4"/>
<Button Content="Привітати"
Width="150"
HorizontalAlignment="Left"
Click="GreetButton_Click"/>
<TextBlock x:Name="resultText"
FontSize="18"
FontWeight="Bold"
TextWrapping="Wrap"/>
</StackPanel>
</Window>
<Window x:Class="MyAvaloniaApp.MainWindow"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Мій перший Avalonia"
Width="450" Height="320"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="24" Spacing="12">
<TextBlock Text="Введіть своє ім'я:"
FontSize="14"/>
<TextBox x:Name="nameInput"
FontSize="14"
Padding="8,4"/>
<Button Content="Привітати"
Width="150"
HorizontalAlignment="Left"
Click="GreetButton_Click"/>
<TextBlock x:Name="resultText"
FontSize="18"
FontWeight="Bold"
TextWrapping="Wrap"/>
</StackPanel>
</Window>
Різниця лише у двох рядках:
xmlns="https://github.com/avaloniaui" замість довгого WPF namespaceSpacing="12" — зручна властивість StackPanel в Avalonia для відступів між елементами (у WPF аналога немає — треба Margin на кожному елементі)Code-behind MainWindow.axaml.cs — ідентичний до WPF:
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace MyAvaloniaApp;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void GreetButton_Click(object sender, RoutedEventArgs e)
{
var name = nameInput.Text?.Trim() ?? "";
if (string.IsNullOrEmpty(name))
{
resultText.Text = "⚠️ Будь ласка, введіть ім'я!";
return;
}
resultText.Text = $"Привіт, {name}! 👋 Це Avalonia!";
}
}
Єдина відмінність: using Avalonia.Controls; замість using System.Windows;. Все інше — те саме.
Ось як це виглядає у превьюері:
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="24" Spacing="12">
<TextBlock Text="Введіть своє ім'я:"
FontSize="14"/>
<TextBox FontSize="14"
Padding="8,4"
Text="Оленка"/>
<Button Content="Привітати"
Width="150"
HorizontalAlignment="Left"
Command="{Binding ShowMessageCommand}"
CommandParameter="Привіт, Оленко! 👋 Це Avalonia!"/>
<TextBlock Text="Привіт, Оленко! 👋 Це Avalonia!"
FontSize="18"
FontWeight="Bold"
TextWrapping="Wrap"/>
</StackPanel>
Найбільша перевага Avalonia — той самий код запускається скрізь. Ось як це виглядає на практиці.
# Windows (з будь-якої ОС, де є .NET SDK)
dotnet run
# Або явна публікація для Windows
dotnet publish -r win-x64 --self-contained
# Публікація для macOS
dotnet publish -r osx-x64 --self-contained
dotnet publish -r osx-arm64 --self-contained # Apple Silicon
# Публікація для Linux
dotnet publish -r linux-x64 --self-contained
dotnet publish -r linux-arm64 --self-contained
Ключ — --self-contained: упаковує .NET Runtime усередину збірки. Кінцевий користувач не потребує встановленого .NET.
Оскільки Avalonia сам малює всі пікселі через Skia (а не використовує системні контроли), UI виглядає практично однаково на всіх платформах. Fluent Theme дає Windows 11-стилістику незалежно від ОС.
| Елемент | Windows WPF | Avalonia (Windows) | Avalonia (macOS) | Avalonia (Linux) |
|---|---|---|---|---|
| Вигляд кнопок | Aero (системний) | Fluent | Fluent | Fluent |
| Шрифт | Segoe UI | Inter (або Segoe) | Inter | Inter |
| Скролбар | Windows-стиль | Fluent | Fluent | Fluent |
| Заголовок вікна | Windows-стиль | Системний (!) | Системний (!) | Системний (!) |
Важливий нюанс: заголовок вікна (Title Bar — синя смуга з кнопками X, _, □) — це завжди системний, бо Avalonia використовує нативне вікно ОС. На macOS це буде macOS-стиль з червоно-жовто-зеленими кнопками. На GNOME Linux — GNOME-style. Але вміст вікна (все що всередині) — Avalonia рисує сама.
Якщо у вас Windows, але хочете побачити Avalonia на Linux без окремої машини:
# 1. Встановити WSL2 з Ubuntu
wsl --install
# 2. У WSL встановити .NET та X11 бібліотеки
sudo apt update
sudo apt install dotnet-sdk-8.0
sudo apt install libx11-dev libxrandr-dev # X11 бібліотеки
# 3. Встановити X11-сервер для Windows (VcXsrv або WSLg)
# WSLg вбудований у Windows 11 — просто запускайте
# 4. Запустити ваш Avalonia-проєкт у WSL
cd /mnt/c/Users/YourName/MyAvaloniaApp
dotnet run
Якщо у вас Windows 11 з WSLg — GTK-вікно з Avalonia-застосунком просто відкриється, ніби ви на Linux.
Одна з найкорисніших можливостей Avalonia, якої немає у WPF з коробки — вбудовані DevTools.
У WPF для інспекції Visual Tree та властивостей елементів потрібно встановити сторонній інструмент Snoop або використовувати вбудований Live Visual Tree у Visual Studio (але лише під час Debug сесії).
Avalonia DevTools — це аналог Snoop, але:
DevTools підключені у шаблоні за замовчуванням через пакет Avalonia.Diagnostics:
<!-- MyAvaloniaApp.csproj -->
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.x" />
// Program.cs
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
#if DEBUG
.UseAvaloniaDevTools(); // Вмикає F12 у Debug-режимі
#endif
Зверніть на #if DEBUG — DevTools вмикаються лише у Debug-збірці. У Release-версії для кінцевих користувачів вони відсутні.
Натисніть F12 у запущеному Avalonia-застосунку — відкриється нове вікно DevTools з кількома вкладками:
Вкладка "Logical Tree" — показує ієрархію елементів так, як ви їх написали у XAML. Button — окремий елемент, без внутрішньої деталізації.
Вкладка "Visual Tree" — показує повну ієрархію з усіма внутрішніми елементами. Один Button у Visual Tree — це Button → TemplatedControl → ContentPresenter → TextBlock. Дозволяє побачити, як Control Template розбиває контрол на примітиви.
Вкладка "Properties" — при натисканні на елемент у дереві — показує всі його властивості з поточними значеннями та джерелом (Local, Style, Inherited тощо).
Вкладка "Console" — інтерактивна REPL-консоль для виконання LINQ-запитів до Visual Tree прямо під час роботи. Наприклад: tree.FindDescendantOfType<Button>().
Вкладка "Events" — показує список зареєстрованих обробників подій для вибраного елемента.
Зберемо все разом у повний покроковий прохід.
dotnet new install Avalonia.Templates
Виконати один раз. Після цього шаблони доступні назавжди.
dotnet new avalonia.app -n MyFirstAvalonia
cd MyFirstAvalonia
Відкрийте папку та знайдіть ключові файли:
Program.cs — точка входу з BuildAvaloniaApp()App.axaml + App.axaml.cs — застосунок зі стилямиMainWindow.axaml + MainWindow.axaml.cs — головне вікноЗамініть вміст вікна на:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyFirstAvalonia.MainWindow"
Title="Мій перший Avalonia"
Width="450" Height="280"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="24" Spacing="14" VerticalAlignment="Center">
<TextBlock Text="Привіт від Avalonia! 🚀"
FontSize="28"
FontWeight="Bold"
HorizontalAlignment="Center"/>
<TextBlock Text="Цей застосунок запуститься на Windows, macOS та Linux"
FontSize="13"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Opacity="0.7"/>
<Button Content="Показати платформу"
HorizontalAlignment="Center"
Width="200"
Click="ShowPlatform_Click"/>
<TextBlock x:Name="platformText"
HorizontalAlignment="Center"
FontSize="15"
FontWeight="SemiBold"/>
</StackPanel>
</Window>
using Avalonia.Controls;
using Avalonia.Interactivity;
using System.Runtime.InteropServices;
namespace MyFirstAvalonia;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ShowPlatform_Click(object sender, RoutedEventArgs e)
{
var os = RuntimeInformation.OSDescription;
var arch = RuntimeInformation.ProcessArchitecture;
platformText.Text = $"🖥️ {os} ({arch})";
}
}
dotnet run
Відкриється вікно. Натисніть кнопку — побачите назву вашої ОС та архітектуру. На Windows: Microsoft Windows 10.0.22621 (X64). На macOS: Darwin 23.x.x (Arm64). На Linux: Linux 6.x.x (X64).
Поки застосунок запущений — натисніть F12. Дослідіть Logical Tree та Visual Tree вашого застосунку. Клікніть на Button у дереві — подивіться на список властивостей та Applied Styles.
Рендеринг
Структура проєкту
.axaml замість .xamlProgram.cs з Main()BuildAvaloniaApp() замість StartupUriOnFrameworkInitializationCompleted() для стартового вікнаXAML: мінімум змін
xmlns="https://github.com/avaloniaui" замість microsoft URIxmlns:local="using:MyApp" — скорочений синтаксисSpacing у StackPanel — зручний бонусDevTools з коробки
Завдання: Встановіть шаблони Avalonia та створіть перший застосунок командою dotnet new avalonia.app. Запустіть його та переконайтеся, що вікно відкрилося.
Потім:
Title вікна на "Мій Avalonia"$"Версія .NET: {Environment.Version}" нижчеПеревірка: Вікно відкрилося, всі три TextBlock відображаються, версія .NET показується динамічно.
Що треба знати: dotnet new install Avalonia.Templates, dotnet new avalonia.app, x:Name, TextBlock.Text, Environment.Version.
Завдання: Відкрийте поряд ваш WPF-проєкт (зі статті 03) та новий Avalonia-проєкт. Виконайте порівняльний аналіз:
.csproj файли — знайдіть і запишіть усі відмінності між ними у форматі таблиці.App.xaml (WPF) з App.axaml (Avalonia) — знайдіть 5 відмінностей.Перевірка: Avalonia-версія запускається і поводиться так само як WPF-версія. Ваша таблиця відмінностей містить не менше 5 рядків.
Що треба знати: Відмінності у namespace, .axaml vs .xaml, Program.cs, різниця у using (Avalonia.Controls vs System.Windows).
Завдання: Створіть Avalonia-застосунок "System Info" з наступним функціоналом:
Інтерфейс: Grid з мітками та значеннями у два стовпці.
Кнопка "Зібрати інформацію" при натисканні заповнює поля:
RuntimeInformation.OSDescriptionRuntimeInformation.ProcessArchitectureEnvironment.VersionEnvironment.MachineNameEnvironment.ProcessorCountEnvironment.TickCount64 / 1000 (секунди)Вимоги до UI:
Label) зліва — вирівняні по правому краюTextBlock) справа — вирівняні по лівому краюRowDefinitions з "Auto" + Height="10" для пустих рядків між секціямиДодатково: Опублікуйте застосунок для Windows та Linux:
dotnet publish -r win-x64 --self-contained -o ./publish/win
dotnet publish -r linux-x64 --self-contained -o ./publish/linux
Порівняйте розміри папок.
Що треба знати: Grid з RowDefinitions/ColumnDefinitions, RuntimeInformation, Environment, dotnet publish, Grid.Row/Column.
Перший WPF-проєкт — від нуля до вікна
Створення першого WPF-застосунку. Структура файлів, App.xaml, MainWindow.xaml, code-behind, partial classes, Hot Reload та перші кроки у GUI.
XAML: декларативний інтерфейс
Розбираємо XAML як мову: зв'язок з C#-об'єктами, синтаксис XML, Property Element Syntax, Content Property, Type Converters та x:Name.