Desktop UI

Контроли в Avalonia: відмінності від WPF

Детальний порівняльний огляд стандартних контролів Avalonia та WPF: що повністю збігається, що відрізняється синтаксисом, що є в Avalonia але відсутнє у WPF — і навпаки. Практичний гід для тих, хто знає WPF і переходить на Avalonia.

Контроли в Avalonia: відмінності від WPF

Якщо ви вивчали попередні чотири статті Блоку 4 — ви вже знаєте Button, TextBox, CheckBox, ComboBox, DatePicker, GroupBox, TabControl та ще десятки контролів. Вся ця бібліотека описана через WPF як основний фрейм. Тепер час розібратись: що з усього цього доступне в Avalonia, і де є відмінності?

Хороша новина: переважна більшість контролів повністю сумісна. Ті ж назви, ті ж властивості, той самий XAML-синтаксис. Різниця між WPF і Avalonia у сфері контролів — це переважно деталі: окремі властивості мають іншу назву, деякі контроли відсутні або замінені кращими альтернативами, а деякі — навпаки, є в Avalonia але відсутні у WPF.

Ця стаття — ваш практичний чеклист переносу знань. Вона не дублює зміст Блоку 4, а доповнює його: там описано "як", тут — "що змінюється в Avalonia".

Передумова: ця стаття передбачає знання контролів WPF на рівні Блоку 4. Якщо відповідна тема ще не вивчалась — спочатку читайте основну статтю, потім повертайтесь сюди.

Загальна таблиця сумісності контролів

Перш за все — великий зведений огляд, аби ви одразу знали, на що чекати в кожному розділі.

Контрол WPFAvaloniaСтатусГоловна відмінність
ButtonButton✅ ПовнаCornerRadius вбудований
RepeatButtonRepeatButton✅ ПовнаБез змін
ToggleButtonToggleButton✅ ПовнаБез змін
ImageImage✅ ПовнаІнший синтаксис URI
ProgressBarProgressBar✅ ПовнаБез змін
SliderSlider✅ ПовнаБез змін
ToolTipToolTip✅ ПовнаToolTipServiceToolTip.*
PopupPopup✅ ПовнаМенше Placement-режимів
TextBlockTextBlock✅ ПовнаPlaceholderText є
LabelLabel⚠️ ОбмеженаНемає AccessKey через _
TextBoxTextBox✅ ПовнаPlaceholderText вбудований
PasswordBoxTextBox (маскований)⚠️ ЗаміненоНемає окремого PasswordBox
RichTextBox❌ Відсутній🔴 ВідсутнійЗамінено сторонніми бібліотеками
FlowDocument❌ Відсутній🔴 ВідсутнійWPF-специфічний
CheckBoxCheckBox✅ ПовнаБез змін
RadioButtonRadioButton✅ ПовнаБез змін
ComboBoxComboBox✅ ПовнаIsEditable підтримується
ListBoxListBox✅ ПовнаБез змін
DatePickerDatePicker⚠️ ЧастковаBlackoutDates відсутній
CalendarCalendar⚠️ ЧастковаМенше режимів SelectionMode
GroupBoxGroupBox✅ ПовнаБез змін
ExpanderExpander✅ ПовнаБез змін
TabControlTabControl✅ ПовнаБез змін
StatusBarStatusBar✅ ПовнаБез змін
ToolTipServiceToolTip (attached)⚠️ Інший синтаксисБез окремого класу Service

Кнопки: Button, RepeatButton, ToggleButton

Що повністю збігається

Button, RepeatButton та ToggleButton в Avalonia є — повний набір з тими ж властивостями та поведінкою. IsDefault, IsCancel, Click, IsChecked, Delay/Interval, GroupName — усе на місці. Синтаксис XAML ідентичний:

<!-- Цей XAML однаково працює у WPF і Avalonia -->
<StackPanel Spacing="8">
  <Button Content="Зберегти" IsDefault="True" Click="Save_Click"/>
  <Button Content="Скасувати" IsCancel="True"/>
  <RepeatButton Content="+" Delay="500" Interval="100"/>
  <ToggleButton Content="Жирний" x:Name="boldToggle"/>
</StackPanel>

Головна різниця: CornerRadius вбудований

У WPF кнопки мають прямі кути за замовчуванням. Щоб зробити заокруглені кути — потрібен кастомний Style або ControlTemplate. У Avalonia клас Button успадковує від TemplatedControl, що вже включає властивість CornerRadius. Це означає:

<!-- WPF: CornerRadius вимагає окремого стилю або ControlTemplate -->
<Button Content="Підтвердити">
  <Button.Style>
    <Style TargetType="Button">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <Border CornerRadius="8" Background="{TemplateBinding Background}"
                    Padding="{TemplateBinding Padding}">
              <ContentPresenter HorizontalAlignment="Center"
                                VerticalAlignment="Center"/>
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Button.Style>
</Button>
<!-- Avalonia: CornerRadius — вбудована властивість кнопки -->
<Button Content="Підтвердити" CornerRadius="8"/>

Це одне з найпомітніших зручних покращень Avalonia. Ви побачите CornerRadius і на TextBox, ComboBox, та інших контролах — без жодного стилю.

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...

Синтаксис CornerRadius

CornerRadius у Avalonia приймає 1 або 4 значення (як Thickness): "8" — всі кути однакові; "8,8,0,0" — верхній лівий, верхній правий, нижній правий, нижній лівий.


Image: інший формат URI для ресурсів

Pack URI (WPF) → avares:// (Avalonia)

У WPF зображення з ресурсів проєкту адресуються через Pack URI:

<!-- WPF: Pack URI -->
<Image Source="pack://application:,,,/Assets/logo.png"/>

<!-- WPF: скорочений відносний запис (тільки всередині тієї ж збірки) -->
<Image Source="/Assets/logo.png"/>

В Avalonia Pack URI не підтримується. Замість нього — схема avares:// (Avalonia Resources), де після avares:// вказується назва збірки, потім шлях до файлу всередині неї:

<!-- Avalonia: avares:// URI -->
<Image Source="avares://MyApp/Assets/logo.png"/>

де MyApp — це <AssemblyName> вашого проєкту з .csproj. Переконайтесь, що файл зображення у .csproj помічений як AvaloniaResource:

<!-- .csproj — Build Action для Avalonia -->
<ItemGroup>
  <AvaloniaResource Include="Assets\**"/>
</ItemGroup>

У WPF аналог — <Resource Include="Assets\**"/>. Назва Build Action відрізняється, але принцип той самий: файл упаковується у збірку.

Bitmap з коду

У WPF BitmapImage з Pack URI:

// WPF
var uri = new Uri("pack://application:,,,/Assets/logo.png");
var bitmap = new BitmapImage(uri);
image.Source = bitmap;

В Avalonia — Bitmap або IBitmap через AssetLoader:

// Avalonia
var uri = new Uri("avares://MyApp/Assets/logo.png");
var bitmap = new Bitmap(AssetLoader.Open(uri));
image.Source = bitmap;

AssetLoader — статичний клас Avalonia (Avalonia.Platform.AssetLoader), що відкриває потоки до ресурсів. Він замінює WPF-підхід через Application.GetResourceStream.

Властивість Stretch: без змін

Усі чотири режими Stretch (None, Fill, Uniform, UniformToFill) і властивість ClipToBounds в Avalonia ідентичні WPF. XAML-код для Image з будь-яким Stretch переноситься без змін — необхідно лише змінити URI.

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...


ToolTip: ToolTipService → прямі attached properties

WPF: клас ToolTipService

У WPF затримки та розташування ToolTip регулюються через статичний клас ToolTipService з attached properties:

<!-- WPF: ToolTipService для налаштування поведінки -->
<Button Content="Зберегти"
        ToolTip="Ctrl+S"
        ToolTipService.InitialShowDelay="200"
        ToolTipService.ShowDuration="8000"
        ToolTipService.Placement="Bottom"/>

Avalonia: ToolTip.* attached properties

В Avalonia немає окремого класу ToolTipService. Замість нього — attached properties безпосередньо на класі ToolTip:

<!-- Avalonia: ToolTip.* замість ToolTipService.* -->
<Button Content="Зберегти"
        ToolTip.Tip="Ctrl+S"
        ToolTip.ShowDelay="200"
        ToolTip.Placement="Bottom"/>

Зверніть: замість ToolTip="..." (скорочений запис WPF) — ToolTip.Tip="...". У Avalonia скорочений запис ToolTip="..." теж підтримується для простого рядка.

Таблиця відповідностей:

WPF (ToolTipService.*)Avalonia (ToolTip.*)
ToolTipService.InitialShowDelayToolTip.ShowDelay
ToolTipService.ShowDuration(немає прямого аналога)
ToolTipService.PlacementToolTip.Placement
ToolTipService.IsEnabledToolTip.IsOpen (програмно)

Складний ToolTip: синтаксис ідентичний

Структурований ToolTip із XAML-вмістом zapisується однаково в обох фреймворках:

<!-- Однаково у WPF і Avalonia -->
<Button Content="⚙ Параметри" Padding="12,8">
  <Button.ToolTip>
    <ToolTip>
      <StackPanel Spacing="6">
        <TextBlock Text="Параметри застосунку" FontWeight="Bold"/>
        <TextBlock Text="Відкриває вікно налаштувань."
                   Foreground="Gray" TextWrapping="Wrap"/>
      </StackPanel>
    </ToolTip>
  </Button.ToolTip>
</Button>

В Avalonia альтернативний (коротший) синтаксис через ToolTip.Tip:

<!-- Avalonia: ToolTip.Tip з вбудованим XAML -->
<Button Content="⚙ Параметри">
  <ToolTip.Tip>
    <StackPanel Spacing="6">
      <TextBlock Text="Параметри застосунку" FontWeight="Bold"/>
      <TextBlock Text="Відкриває вікно налаштувань." Foreground="Gray"/>
    </StackPanel>
  </ToolTip.Tip>
</Button>

TextBox: PlaceholderText та CornerRadius вбудовані

Головні покращення Avalonia

У WPF TextBox — "голий": немає вбудованого placeholder-тексту і немає CornerRadius. В Avalonia TextBox отримав обидва:

ВластивістьWPFAvalonia
PlaceholderText❌ Немає (потрібен code-behind або Style)✅ Вбудована
CornerRadius❌ Тільки через ControlTemplate✅ Вбудована
Text
AcceptsReturn
AcceptsTab
MaxLength
IsReadOnly
TextWrapping
TextChanged
SpellCheck.IsEnabled❌ Немає

PlaceholderText

У WPF, щоб зробити placeholder, потрібно або code-behind (GotFocus/LostFocus), або Style з Trigger. В Avalonia це одна властивість:

<!-- WPF: placeholder через GotFocus/LostFocus у code-behind (обхідний шлях) -->
<TextBox x:Name="searchBox" Foreground="Gray"
         GotFocus="SearchBox_GotFocus"
         LostFocus="SearchBox_LostFocus"/>
<!-- Avalonia: PlaceholderText — нативна властивість -->
<TextBox PlaceholderText="Пошук..." CornerRadius="8" Padding="10,6"/>

Також є PlaceholderForeground для кольору placeholder-тексту:

<TextBox PlaceholderText="Введіть email..."
         PlaceholderForeground="#9CA3AF"
         CornerRadius="6" Padding="10,6"/>

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...

Label та AccessKey: відмінність

У WPF Label підтримує AccessKey через символ _ у рядку Content та властивість Target. В Avalonia AccessKey через _ не підтримується. Label в Avalonia — звичайний ContentControl без особливої логіки AccessKey.

Альтернатива: у Avalonia є власний механізм гарячих клавіш через HotKeyManager або KeyBinding, але це зовсім інший підхід, що виходить за рамки цієї статті.

<!-- WPF: AccessKey через підкреслення -->
<Label Content="_Ім'я:" Target="{Binding ElementName=nameBox}"/>
<TextBox x:Name="nameBox"/>

<!-- Avalonia: Label без AccessKey — просто TextBlock або Label без Target -->
<Label Content="Ім'я:"/>
<TextBox/>
Якщо ваша форма вимагає AccessKey-поведінки в Avalonia — використовуйте KeyBinding на рівні Window або UserControl. Властивість Target у Label в Avalonia присутня, але логіка активації через Alt+Key не вбудована.

PasswordBox: відсутній — замінений через TextBox

Чому PasswordBox відсутній в Avalonia

Avalonia свідомо відмовилася від окремого PasswordBox. Замість нього — звичайний TextBox із властивістю PasswordChar. Це і є механізм маскування:

<!-- WPF: окремий контрол PasswordBox -->
<PasswordBox PasswordChar="●" MaxLength="64"
             PasswordChanged="PasswordBox_Changed"/>
<!-- Avalonia: TextBox з PasswordChar -->
<TextBox PasswordChar="●" MaxLength="64"
         TextChanged="PasswordBox_Changed"/>

Ключова різниця — властивість для читання значення:

АспектWPF PasswordBoxAvalonia TextBox з PasswordChar
Читання значенняPasswordBox.Password (string)TextBox.Text (string)
Безпечне зберіганняSecurePassword (SecureString)❌ Немає SecureString
Подія зміниPasswordChangedTextChanged
МаскуванняВбудованеЧерез PasswordChar

Наслідки для безпеки

Відсутність SecureString — суттєва відмінність. WPF PasswordBox зберігає пароль у SecureString (шифрування в пам'яті), Avalonia TextBox — у звичайному string. Для застосунків, де безпека пароля критична, використовуйте криптографічне хешування відразу в TextChanged-обробнику та очищайте Text після:

// Avalonia: читаємо та одразу хешуємо
private void PasswordBox_TextChanged(object? sender, TextChangedEventArgs e)
{
    if (sender is TextBox box)
    {
        string raw = box.Text ?? "";
        // Хешуємо та зберігаємо хеш, а не сам пароль
        _passwordHash = BCrypt.Net.BCrypt.HashPassword(raw);
        UpdateStrengthIndicator(raw.Length);
    }
}

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...


RichTextBox та FlowDocument: відсутні в Avalonia

Що замінює RichTextBox

RichTextBox та FlowDocument — повністю WPF-специфічні компоненти. В Avalonia їх немає. Якщо ваш застосунок потребує редактора форматованого тексту в Avalonia — є кілька шляхів:

1. AvalonEdit — популярна бібліотека редактора коду та тексту, портована для Avalonia:

<!-- NuGet: AvaloniaEdit -->
<avalonEdit:TextEditor SyntaxHighlighting="C#"
                       FontFamily="Consolas" FontSize="13"/>

2. Sᴛарий підхід через SelectableTextBlock — Avalonia має SelectableTextBlock, що дозволяє виділяти та копіювати текст, але не редагувати його. Підходить для read-only відображення.

3. InlineCollection у TextBlock — для статичного форматованого тексту (жирний, курсивний, гіперпосилання) Avalonia підтримує ті ж Inline-класи, що й WPF: Run, Bold, Italic, Underline, Hyperlink, LineBreak. Синтаксис ідентичний і переноситься без змін.

Не намагайтесь перенести RichTextBox + FlowDocument з WPF в Avalonia напряму — ці класи просто відсутні у Avalonia API. Якщо ваш проєкт критично залежить від RichTextBox, розгляньте або залишення WPF, або міграцію на AvaloniaEdit з переписуванням логіки форматування.

CheckBox, RadioButton, ComboBox, ListBox: без змін

Хороша новина: контроли вибору в Avalonia повністю сумісні з WPF. IsChecked, IsThreeState, GroupName, SelectionMode, SelectedItem, SelectedIndex, IsEditable — усі ці властивості присутні і працюють ідентично.

Єдиний нюанс, вже знайомий: ComboBox, ListBox та TextBox в Avalonia мають вбудований CornerRadius:

<!-- Avalonia: ComboBox з CornerRadius -->
<ComboBox CornerRadius="6" SelectedIndex="0">
  <ComboBoxItem Content="🇺🇦 Українська"/>
  <ComboBoxItem Content="🇬🇧 English"/>
</ComboBox>

Все інше — Checked/Unchecked/Indeterminate, SelectionChanged, SelectedItems, Items.Add() — переноситься без змін.


DatePicker та Calendar: часткова підтримка

BlackoutDates відсутній

Найбільша відмінність DatePicker в Avalonia — відсутність BlackoutDates. У WPF цей API дозволяв заблокувати конкретні дати або діапазони (наприклад, вихідні або минулі дати). В Avalonia такого API немає.

Таблиця відмінностей:

ВластивістьWPFAvalonia
SelectedDate
DisplayDateStart
DisplayDateEnd
BlackoutDates❌ Відсутній
SelectedDateChanged✅ (SelectedDateChanged)
FirstDayOfWeek
SelectedDateFormat⚠️ Обмежена

Альтернатива BlackoutDates в Avalonia

Реалізація блокування дат в Avalonia потребує власного підходу — або через кастомний CalendarDayButtonStyle (тема стилізації), або через перехоплення SelectedDateChanged і відхилення невалідних значень:

// Avalonia: відхиляємо вихідні у SelectedDateChanged
private void DatePicker_SelectedDateChanged(object? sender,
    DatePickerSelectedValueChangedEventArgs e)
{
    if (e.NewDate is DateTimeOffset dto)
    {
        var day = dto.DayOfWeek;
        if (day == DayOfWeek.Saturday || day == DayOfWeek.Sunday)
        {
            // Повертаємо попереднє значення
            if (sender is DatePicker dp)
                dp.SelectedDate = e.OldDate;

            // Повідомляємо користувача
            statusText.Text = "Вихідні дні недоступні для вибору.";
        }
    }
}
У Avalonia SelectedDate має тип DateTimeOffset?, а не DateTime? як у WPF. Це важлива відмінність при роботі з датами — DateTimeOffset містить інформацію про часовий пояс. Для конвертації: dto.DateTime або dto.UtcDateTime.

Calendar: SelectionMode обмежений

В Avalonia Calendar підтримує режими Single та Multiple, але SingleRange та MultipleRange відсутні. Якщо потрібен вибір діапазону дат — розгляньте бібліотеки типу Avalonia.Controls.DateTimePicker (від спільноти) або реалізуйте власний.


Контроли тільки в Avalonia (відсутні у WPF)

Avalonia як сучасна платформа містить ряд контролів, яких немає у WPF взагалі. Ось ключові, що стосуються тем цього Блоку:

SplitView: бічна навігаційна панель

SplitView — контрол для "гамбургер-меню" інтерфейсів. Має Pane (бічна панель, що ховається) та Content (основна область). Режими Inline, Overlay, CompactInline, CompactOverlay керують поведінкою при відкритті/закритті.

<!-- Тільки Avalonia -->
<SplitView IsPaneOpen="True" OpenPaneLength="200"
           DisplayMode="CompactInline">
  <SplitView.Pane>
    <StackPanel Spacing="4" Margin="8">
      <Button Content="🏠 Головна" HorizontalAlignment="Stretch"/>
      <Button Content="⚙ Налаштування" HorizontalAlignment="Stretch"/>
    </StackPanel>
  </SplitView.Pane>
  <Grid>
    <TextBlock Text="Основний вміст" HorizontalAlignment="Center"
               VerticalAlignment="Center"/>
  </Grid>
</SplitView>

NumericUpDown: числове поле зі стрілками

NumericUpDown — стандартний контрол Avalonia для введення числових значень зі стрілками вгору/вниз. У WPF аналога немає (все реалізувалось через RepeatButton плюс TextBox).

Value
decimal?
Поточне числове значення. Тип decimal? дозволяє зберігати null (порожнє поле).
Minimum / Maximum
decimal?
Мінімальне та максимальне допустиме значення. null — без обмежень.
Increment
decimal
Крок зміни при натисканні стрілок. За замовчуванням — 1.
FormatString
string
Формат відображення числа: "N2" (два знаки після коми), "F0" (ціле), "P0" (відсотки). Будь-який стандартний формат .NET.
AllowSpin
bool
Дозволяти інкремент/декремент через стрілки. За замовчуванням — true.
IsReadOnly
bool
Режим лише для читання (стрілки теж вимикаються).

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...


AutoCompleteBox: поле з автодоповненням

AutoCompleteBox — один з найбільш затребуваних контролів, якого немає у WPF. Це TextBox з вбудованим dropdown-списком підказок, що фільтруються по введеному тексту. У WPF подібне реалізовувалось вручну через ComboBox з IsEditable="True" + логіка фільтрації в code-behind. В Avalonia — нативний контрол.

ItemsSource
IEnumerable
Колекція варіантів для автодоповнення. Може бути IEnumerable<string> або IEnumerable<T> з вказанням ValueMemberPath.
FilterMode
AutoCompleteFilterMode
Алгоритм фільтрації: StartsWith (рядки, що починаються з введеного), Contains (рядки, що містять введене), StartsWithCaseSensitive, ContainsCaseSensitive, Custom (власна функція фільтрації).
MinimumPrefixLength
int
Мінімальна кількість символів, після яких з'являються підказки. За замовчуванням — 1. 0 — список відкривається одразу при фокусі.
MinimumPopulateDelay
TimeSpan
Затримка перед формуванням списку підказок (для зменшення навантаження при швидкому введенні). Корисно при асинхронному пошуку.
SelectedItem
object?
Обраний елемент зі списку. Відрізняється від Text — можна обрати елемент зі списку (SelectedItem), але Text може містити довільний рядок.

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...

FilterMode="Custom" дозволяє задати власну функцію фільтрації через ItemFilter — callback типу Func<string, object, bool>. Це корисно для нечіткого пошуку (fuzzy search) або фільтрації за кількома полями об'єкта.

TimePicker: вибір часу

TimePicker — нативний контрол для вибору часу доби. У WPF аналога немає. TimePicker показує спінери для годин, хвилин та (опційно) секунд — вертикальні прокручувані стовпці, як у мобільних iOS/Android picker-ах.

SelectedTime
TimeSpan?
Обраний час у вигляді TimeSpan. null — нічого не обрано. TimeSpan у цьому контексті представляє час доби від опівночі: new TimeSpan(14, 30, 0) = 14:30:00.
MinuteIncrement
int
Крок для хвилин. 15 — показує 0, 15, 30, 45. За замовчуванням — 1 (кожна хвилина).
SecondIncrement
int
Крок для секунд (якщо UseSeconds="True").
UseSeconds
bool
Чи показувати спінер секунд. За замовчуванням — false.
ClockIdentifier
string
"12HourClock" або "24HourClock". За замовчуванням визначається локаллю.

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...


ColorPicker та ColorView: вибір кольору

У WPF немає жодного вбудованого контрола для вибору кольору — потрібні сторонні бібліотеки. Avalonia має два рідних контроли:

  • ColorPicker — компактний drop-down (як DatePicker для кольору): у закритому стані показує кольоровий квадрат, при натисканні — розкривається повноцінний picker.
  • ColorView — завжди видимий повноцінний picker (режим Canvas). Містить кольоровий компас (ColorSpectrum), слайдери насиченості/яскравості, HEX-поле та альфа-канал.

Обидва оперують типом Color (Avalonia.Media.Color), ідентичним System.Windows.Media.Color у WPF.

Color
Color
Поточний обраний колір. Двостороння прив'язка для синхронізації з ViewModel.
HsvColor
HsvColor
Той самий колір у HSV-представленні. ColorPicker оперує внутрішньо в HSV для точних слайдерів насиченості/яскравості.
ColorChanged
EventHandler
Подія зміни кольору (аналог SelectionChanged для списків). Аргументи містять OldColor та NewColor.
IsAlphaEnabled
bool
Чи показувати слайдер/поле прозорості (альфа-канал). За замовчуванням — true.

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...


HyperlinkButton: кнопка-гіперпосилання

У WPF гіперпосилання у тексті реалізовується через Hyperlink Inline (всередині TextBlock). Окремої кнопки-гіперпосилання немає. В Avalonia є HyperlinkButton — повноцінний Button, що стилізований під посилання (синій текст, підкреслення, cursor as pointer):

<!-- WPF: тільки через TextBlock + Hyperlink Inline -->
<TextBlock>
  <Hyperlink NavigateUri="https://example.com"
             RequestNavigate="Hyperlink_Navigate">
    Перейти на сайт
  </Hyperlink>
</TextBlock>
<!-- Avalonia: окремий контрол HyperlinkButton -->
<HyperlinkButton Content="Перейти на сайт"
                 NavigateUri="https://example.com"/>

<!-- Або з обробником Click для відкриття у браузері -->
<HyperlinkButton Content="Документація Avalonia"
                 NavigateUri="https://docs.avaloniaui.net"
                 Click="Link_Click"/>

HyperlinkButton автоматично відкриває NavigateUri у браузері за замовчуванням — без жодного коду. Успадковує від Button, тож підтримує Content як довільний XAML.


MaskedTextBox: введення за шаблоном (маскою)

MaskedTextBoxTextBox з прив'язаним шаблоном введення (маскою). У WPF аналог — System.Windows.Controls.MaskedTextBox зі WinForms-обгорткою або стороннє рішення. В Avalonia — нативний.

Символи маски:

СимволДопустимий ввід
0Обов'язкова цифра (0–9)
9Необов'язкова цифра або пробіл
#Цифра, пробіл, + або -
LОбов'язкова літера (a–z, A–Z)
?Необов'язкова літера
&Обов'язковий будь-який символ
AОбов'язкова літера або цифра
aНеобов'язкова літера або цифра
>Усі наступні символи — UPPER
<Усі наступні символи — lower

Loading Avalonia WebAssembly...

Downloading .NET runtime (10MB)...

SelectableTextBlock: текст, що можна виділити

SelectableTextBlock — Avalonia-аналог TextBlock, але з можливістю виділення та копіювання тексту мишею або клавіатурою. У WPF TextBlock не дозволяє виділяти текст.

<!-- WPF: щоб виділяти текст — потрібен IsReadOnly TextBox (некрасиво) -->
<TextBox IsReadOnly="True" Text="Виділи мене" BorderThickness="0"/>

<!-- Avalonia: SelectableTextBlock — виглядає як TextBlock, але виділяється -->
<SelectableTextBlock Text="Серійний номер: SN-2026-ABCD-9999"
                     SelectionBrush="#6366F1"
                     TextWrapping="Wrap"/>

Властивості SelectionStart, SelectionEnd, SelectedText дозволяють читати виділений фрагмент у code-behind. SelectionChanged — подія зміни виділення.

TreeDataGrid: ієрархічна таблиця даних

TreeDataGrid — один з найпотужніших контролів Avalonia. Поєднує TreeView (ієрархія) і DataGrid (таблиця) в одному. У WPF DataGrid і TreeView — окремі контроли без можливості прямого поєднання.

<!-- Тільки Avalonia -->
<TreeDataGrid x:Name="fileTree"
              CanUserResizeColumns="True"
              CanUserSortColumns="True"/>

Налаштовується програматично через HierarchicalTreeDataGridSource<T> у code-behind. Це складніший контрол, детально розглянутий у Блоці 6 (Data Binding та колекції).

NotificationCard та WindowNotificationManager

Avalonia має вбудовану систему сповіщень типу toast — WindowNotificationManager з методом Show(). У WPF для цього потрібні сторонні бібліотеки або власна реалізація.


Підсумок відмінностей

Чотири категорії змін

Зробимо фінальний підсумок усіх відмінностей по чотирьох категоріях:

✅ Повна сумісність (нічого не змінювати):Button, RepeatButton, ToggleButton, ProgressBar, Slider, Popup, CheckBox, RadioButton, ComboBox, ListBox, GroupBox, Expander, TabControl, StatusBar, TextBlock Inline-елементи.

⚠️ Потребує незначних правок:

КонтролЩо змінити
Imagepack://avares://, <Resource><AvaloniaResource>
ToolTipService.*ToolTip.* (напряму на елементі)
TextBoxДодати PlaceholderText (замість code-behind), опційно CornerRadius
DatePickerSelectedDateDateTimeOffset?, BlackoutDates — ручна реалізація
LabelПрибрати _ (AccessKey), прибрати Target

🔴 Потребує замінників:

WPFAvalonia-замінник
PasswordBoxTextBox з PasswordChar="●"
RichTextBox + FlowDocumentAvaloniaEdit (NuGet) або TextBox
Calendar SingleRange/MultipleRangeСтороння бібліотека або кастомна реалізація

🆕 Є тільки в Avalonia (без WPF-аналога):

КонтролПризначення
NumericUpDownЧислове поле зі стрілками і FormatString
AutoCompleteBoxTextBox з dropdown-підказками та FilterMode
TimePickerВибір часу (спінери годин/хвилин/секунд)
ColorPicker / ColorViewВibір кольору з HSV-спектром та HEX-полем
HyperlinkButtonКнопка, що виглядає як HTML-посилання
MaskedTextBoxВведення за маскою (телефон, дата, картка)
SelectableTextBlockTextBlock з можливістю виділення та копіювання
TreeDataGridІєрархічна таблиця (TreeView + DataGrid)
SplitViewБічна навігаційна панель (hamburger-меню)
WindowNotificationManagerToast-сповіщення (вбудовано)
RelativePanelПозиціонування елементів відносно сусідів
ItemsRepeaterЛегковісний список без ListBox-overhead

Загальний висновок

Перехід з WPF на Avalonia у сфері контролів — відносно безболісний. 80% XAML-коду перенесеться без змін або з мінімальними правками (URI та ToolTipService). Справжні проблеми виникають лише в двох точках: відсутність PasswordBox з SecureString (архітектурне рішення безпеки) та відсутність RichTextBox/FlowDocument (потребує сторонньої бібліотеки). Все інше — це зручні покращення: CornerRadius, PlaceholderText, Spacing, NumericUpDown, AutoCompleteBox, TimePicker, ColorPicker — функції, які WPF-розробники зазвичай реалізовували "вручну" або через сторонні бібліотеки.