TextBlock, Label, TextBox, PasswordBox, RichTextBox, FlowDocument, Run, Inline, TextWrapping, TextTrimming, AcceptsReturn, SecureString, PasswordChar, Selection, Paragraph, AccessKey, Adorner.Текст — це найфундаментальніший елемент будь-якого застосунку. Майже кожен екран містить підписи, поля введення, повідомлення, форматований вміст. Але якщо у WinForms для всіх цих завдань часто використовувався один і той самий Label або TextBox, то WPF пропонує спеціалізований набір контролів, кожен з яких є оптимальним для конкретного сценарію.
Розуміння того, який контрол для якої задачі призначений, є однією з основ ефективного проєктування WPF-інтерфейсів. Помилковий вибір тут — не просто естетична проблема: використання TextBox там, де достатньо TextBlock, додає зайве навантаження на систему; використання Label замість TextBlock без потреби — це надлишкова складність. Кожен контрол несе у собі певний набір функцій та відповідних витрат.
У цій статті ми розглянемо п'ять ключових текстових контролів WPF:
TextBlock
Bold, Italic, Hyperlink). Найбільш використовуваний текстовий контрол.Label
ContentControl з підтримкою AccessKey (підкреслена буква-скорочення) та прив'язки до контролу через Target. Для простого тексту — надлишковий, але незамінний для доступних форм.TextBox
PasswordBox
SecureString (а не у звичайному string) — фундаментальне рішення безпеки.RichTextBox
FlowDocument. Підтримує параграфи, жирний/курсивний текст, зображення всередині тексту. Специфічний для WPF.Початківці в WPF нерідко ставлять питання: "Я бачу TextBlock і Label — вони виглядають однаково. Чому існують обидва?" Це логічне запитання, і відповідь на нього розкриває кілька важливих принципів платформи.
Різниця між TextBlock та Label — не стилістична, а архітектурна:
| Аспект | TextBlock | Label |
|---|---|---|
| Базовий клас | FrameworkElement | ContentControl |
| Може містити вміст | Тільки текст (Inlines) | Будь-який UIElement |
| Підтримка фокусу | ❌ Ні | ✅ Так (але не отримує ввід) |
AccessKey (_) | ❌ Ні | ✅ Так |
Властивість Target | ❌ Ні | ✅ Так |
| Вага (memory/CPU) | Легкий | Важчий (ContentControl overhead) |
| Типовий use case | Будь-який теxт для відображення | Підписи у формах із клавіатурним скороченням |
TextBlock — це не контрол у повному розумінні слова (він не успадковує від Control), а FrameworkElement. Це означає, що він не має VisualState-машини, не може отримати фокус клавіатури, не генерує події введення. Він просто відображає текст максимально ефективно.
Саме завдяки цьому TextBlock є найпоширенішим текстовим елементом у будь-якому WPF-застосунку — він з'являється скрізь: у DataTemplate-ах списків, у кнопках (всередині Content), у ToolTip-ах, у заголовках. Ніколи не використовуйте Label там, де потрібно просто відобразити текст — це надлишковий вибір.
Label успадковує від ContentControl, що надає йому дві суттєві здатності, яких немає у TextBlock:
AccessKey — підкреслена буква у тексті підпису, яка дозволяє активувати пов'язаний контрол натисканням Alt + ця літера. Щоб визначити AccessKey, поставте символ підкреслення _ перед відповідною буквою у рядку Content:
<!-- "_І" означає Alt+І активує пов'язаний TextBox -->
<Label Content="_Ім'я:" Target="{Binding ElementName=nameTextBox}"/>
<TextBox x:Name="nameTextBox"/>
Target — властивість типу UIElement, що вказує, який контрол отримає фокус при спрацюванні AccessKey. Це ключовий механізм доступності (accessibility) для користувачів, що керують застосунком лише з клавіатури.
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="12"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<!-- Label з AccessKey: Alt+І переводить фокус на nameBox -->
<Label Grid.Row="0" Grid.Column="0"
Content="_Ім'я:"
Target="{Binding ElementName=nameBox}"
VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1"
x:Name="nameBox" Padding="6,4"/>
<!-- Label з AccessKey: Alt+Е переводить фокус на emailBox -->
<Label Grid.Row="2" Grid.Column="0"
Content="_Email:"
Target="{Binding ElementName=emailBox}"
VerticalAlignment="Center"/>
<TextBox Grid.Row="2" Grid.Column="1"
x:Name="emailBox" Padding="6,4"/>
<!-- TextBlock: просто текст без AccessKey -->
<TextBlock Grid.Row="4" Grid.Column="0"
Text="Примітка:"
Foreground="Gray"
VerticalAlignment="Center"/>
<TextBlock Grid.Row="4" Grid.Column="1"
Text="TextBlock не підтримує AccessKey"
Foreground="Gray" FontSize="11"
VerticalAlignment="Center"/>
</Grid>
Label + Target для кожного поля введення. Це дозволяє користувачам зі скрин-рідерами та клавіатурній навігації правильно ідентифікувати поля. У простих формах без вимог до accessibility — достатньо TextBlock.Незважаючи на зовнішню простоту, TextBlock має набір важливих властивостей, без знання яких важко побудувати правильний текстовий інтерфейс.
Найкритичніші — TextWrapping та TextTrimming. Вони відповідають за те, що відбувається з текстом, коли він не вміщується у відведений простір.
TextWrapping визначає, чи переноситься текст на новий рядок:
TextBlock автоматично розраховує висоту, щоб відобразити весь вміст. Найпоширеніший у листах опису, підказках, блоках із довільним текстом.Wrap, де довге слово просто обрізається; тут воно відображається цілком, навіть якщо простір закінчився.TextTrimming визначає, що робити з текстом, що не вміщується (актуально лише при NoWrap):
| Значення | Поведінка |
|---|---|
None | Текст просто обрізається (без символів) |
CharacterEllipsis | Обрізається на межі довільного символу, додається ... |
WordEllipsis | Обрізається на межі цілого слова, додається ... |
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="16" MaxWidth="300">
<TextBlock Text="TextWrapping = NoWrap (за замовчуванням):"
Foreground="Gray" FontSize="11"/>
<Border BorderBrush="#444" BorderThickness="1" Padding="8">
<TextBlock Text="Це довгий рядок без переносу — він виходить за межі контейнера"
TextWrapping="NoWrap"/>
</Border>
<TextBlock Text="TextWrapping = Wrap:" Foreground="Gray" FontSize="11"/>
<Border BorderBrush="#444" BorderThickness="1" Padding="8">
<TextBlock Text="Це довгий рядок з увімкненим переносом — WPF автоматично розбиває текст на рядки за потреби"
TextWrapping="Wrap"/>
</Border>
<TextBlock Text="TextTrimming = WordEllipsis (NoWrap):"
Foreground="Gray" FontSize="11"/>
<Border BorderBrush="#444" BorderThickness="1" Padding="8">
<TextBlock Text="Це довгий рядок, що обрізається з трьома крапками на відповідному слові"
TextWrapping="NoWrap"
TextTrimming="WordEllipsis"/>
</Border>
</StackPanel>
Одна з прихованих суперсил TextBlock — підтримка Inline-елементів: фрагментів тексту з різним форматуванням, що розміщуються всередині одного TextBlock як дочірні елементи колекції Inlines. Це дозволяє реалізувати форматований текст (жирний, курсивний, гіперпосилання, змішані стилі) без RichTextBox.
Найважливіші класи:
FontWeight, FontStyle, Foreground, FontSize застосовуються лише до цього фрагменту.<Bold>текст</Bold> рівнозначно <Run FontWeight="Bold">текст</Run>. Можна вкладати: <Bold><Italic>жирний курсив</Italic></Bold>.NavigateUri та подію RequestNavigate. Для відкриття у браузері потрібен обробник RequestNavigate з викликом Process.Start.TextBlock. Аналог тегу <br/> у HTML.Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="16">
<TextBlock TextWrapping="Wrap" FontSize="14">
<Run>Звичайний текст, </Run>
<Bold>жирний текст, </Bold>
<Italic>курсивний текст, </Italic>
<Underline>підкреслений текст</Underline>
<Run> і знов звичайний.</Run>
</TextBlock>
<TextBlock TextWrapping="Wrap">
<Run Foreground="#6366F1" FontWeight="Bold">WPF</Run>
<Run> — це потужна платформа. Навчіться використовувати </Run>
<Run Foreground="#10B981" FontStyle="Italic">Inline-елементи</Run>
<Run> для форматування тексту без </Run>
<Bold>RichTextBox</Bold>
<Run>.</Run>
</TextBlock>
<TextBlock TextWrapping="Wrap">
<Bold>Увага!</Bold>
<LineBreak/>
<Run Foreground="Gray" FontSize="12">Цей рядок — після примусового переносу через </Run>
<Run Foreground="#F59E0B" FontSize="12">LineBreak</Run>
<Run Foreground="Gray" FontSize="12">.</Run>
</TextBlock>
</StackPanel>
TextBlock — чисто декларативне рішення. Воно підходить для статичного форматованого тексту (підписи, повідомлення, довідка). Якщо форматування потрібно змінювати динамічно (редактор, де користувач вибирає жирний через кнопку) — використовуйте RichTextBox.TextBox — найуніверсальніший контрол введення у WPF. Він успадковує від TextBoxBase, який, у свою чергу, успадковує від Control. Це означає, що TextBox — це повноцінний контрол зі всіма наслідками: він може отримувати фокус, реагує на клавіатуру та мишу, підтримує теми і стилі, має VisualState-машину (Normal, MouseOver, Focused, Disabled).
Ключові можливості, які відрізняють WPF-TextBox від WinForms-аналога, включають:
SelectionStart, SelectionLength, SelectedText.Text у двосторонньому режимі (Two-Way Binding) — основа для форм у MVVM.SpellCheck.IsEnabled="True".myTextBox.Text = "Текст";.true — клавіша Enter додає новий рядок (перетворює TextBox на багаторядковий). Якщо false (за замовчуванням) — Enter передає фокус до кнопки з IsDefault="True".true — клавіша Tab вставляє символ табуляції. Якщо false (за замовчуванням) — Tab переміщує фокус на наступний контрол.0 (за замовчуванням) — без обмежень. Обмеження відбувається на рівні введення — користувач просто не зможе надрукувати більше.true — текст не можна редагувати, але можна виділяти і копіювати. Відрізняється від IsEnabled="False": readonly поле залишається візуально активним і дозволяє читання.TextBlock. Для багаторядкового TextBox встановлюйте TextWrapping="Wrap", щоб рядки автоматично переносились.Disabled (за замовчуванням), Auto (з'являється при потребі), Visible (завжди видима), Hidden (прихована, але прокрутка працює).Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="16">
<TextBlock Text="Однорядковий TextBox (за замовчуванням):"
Foreground="Gray" FontSize="13"/>
<TextBox Padding="8,6"
PlaceholderText="Введіть ваше ім'я..."
MaxLength="50"/>
<TextBlock Text="Багаторядковий TextBox (AcceptsReturn=True):"
Foreground="Gray" FontSize="13"/>
<TextBox AcceptsReturn="True"
AcceptsTab="True"
TextWrapping="Wrap"
Height="100"
Padding="8,6"
VerticalScrollBarVisibility="Auto"
PlaceholderText="Введіть опис (Enter — новий рядок, Tab — відступ)..."/>
<TextBlock Text="IsReadOnly=True (виділення дозволено):"
Foreground="Gray" FontSize="13"/>
<TextBox Text="Цей текст не можна редагувати, але можна скопіювати"
IsReadOnly="True"
Padding="8,6"
Foreground="Gray"/>
</StackPanel>
PlaceholderText — властивість, яка є у Avalonia, але відсутня у стандартному WPF. У реальному WPF placeholder-текст реалізовується або через стиль (Style + Trigger на Text == ""), або через Adorner-шар у code-behind. Ми розглянемо code-behind підхід нижче.Щоразу, коли вміст TextBox змінюється, спрацьовує подія TextChanged. Її обробник отримує аргумент TextChangedEventArgs, що містить колекцію Changes — список конкретних змін (вставлення, видалення) з позиціями. Для більшості задач достатньо просто читати myTextBox.Text всередині обробника:
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="8">
<TextBlock Text="Введіть повідомлення:" Foreground="Gray" FontSize="13"/>
<TextBox x:Name="messageBox"
AcceptsReturn="True"
TextWrapping="Wrap"
Height="80"
MaxLength="200"
Padding="8,6"
VerticalScrollBarVisibility="Auto"
TextChanged="MessageBox_TextChanged"/>
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBlock x:Name="charCountLabel"
Text="0"
FontWeight="Bold"
Foreground="#6366F1"/>
<TextBlock Text="/ 200 символів" Foreground="Gray" FontSize="12"/>
</StackPanel>
</StackPanel>
private void MessageBox_TextChanged(object sender, TextChangedEventArgs e)
{
// Оновлюємо лічильник символів у реальному часі
charCountLabel.Text = messageBox.Text.Length.ToString();
// Змінюємо колір при наближенні до ліміту
charCountLabel.Foreground = messageBox.Text.Length >= 180
? new SolidColorBrush(Colors.OrangeRed)
: new SolidColorBrush(Color.FromRgb(99, 102, 241)); // #6366F1
}
У стандартному WPF немає вбудованої властивості PlaceholderText. Один із найпростіших способів реалізувати підказку-заповнювач без стилів — підписатись на події GotFocus та LostFocus:
private const string PlaceholderText = "Введіть ваше ім'я...";
private void SearchBox_Loaded(object sender, RoutedEventArgs e)
{
searchBox.Text = PlaceholderText;
searchBox.Foreground = Brushes.Gray;
}
private void SearchBox_GotFocus(object sender, RoutedEventArgs e)
{
if (searchBox.Text == PlaceholderText)
{
searchBox.Text = "";
searchBox.Foreground = Brushes.White; // або SystemColors.ControlTextBrush
}
}
private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrWhiteSpace(searchBox.Text))
{
searchBox.Text = PlaceholderText;
searchBox.Foreground = Brushes.Gray;
}
}
TextBox прив'язаний до моделі через Binding, значення placeholder-тексту потрапить у модель при втраті фокусу без введення. Для правильного placeholder у реальних застосунках використовуйте підхід через Style + Trigger (Блок 8) або Adorner-шар. Поки — code-behind достатній для навчання.Це питання задає кожен, хто вперше стикається з PasswordBox. Здавалося б — TextBox має Text, PasswordBox — ні. Чому? Відповідь лежить у площині безпеки.
Звичайний string у .NET — незмінний (immutable) об'єкт, що зберігається у купі (heap). Управління пам'яттю у .NET здійснює збирач сміття (GC), і GC не гарантує, коли саме пам'ять, де зберігався рядок із паролем, буде очищена або перезаписана. Це означає, що пароль може "жити" у пам'яті ще довго після того, як ви закінчили з ним роботу — і теоретично бути прочитаним при дампі пам'яті або через уразливість.
PasswordBox зберігає пароль у SecureString — спеціальному класі, що:
Dispose()).string. Зручна, але менш безпечна — використовуйте лише для простих сценаріїв без вимог до безпеки (не для production-авторизації).SecureString. Повинен передаватись у функції, що приймають SecureString (наприклад, NetworkCredential), і очищатись після використання через Dispose().● (U+25CF). Можна змінити, наприклад, на * для класичного вигляду.0 — без обмежень.Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="16" MaxWidth="320">
<TextBlock Text="Введіть пароль:" Foreground="Gray" FontSize="13"/>
<PasswordBox x:Name="passwordInput"
MaxLength="64"
PasswordChar="●"
Padding="8,6"
PasswordChanged="PasswordInput_Changed"/>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Довжина:" Foreground="Gray"/>
<TextBlock x:Name="pwdLengthLabel" Text="0" FontWeight="Bold"/>
<TextBlock x:Name="pwdStrengthLabel"
Text="(занадто короткий)"
Foreground="#F59E0B" FontSize="12"/>
</StackPanel>
<PasswordBox PasswordChar="*"
Padding="8,6"
PlaceholderText="Символ * замість ●"/>
</StackPanel>
private void PasswordInput_Changed(object sender, RoutedEventArgs e)
{
int length = passwordInput.Password.Length;
pwdLengthLabel.Text = length.ToString();
if (length == 0)
{
pwdStrengthLabel.Text = "(не введено)";
pwdStrengthLabel.Foreground = Brushes.Gray;
}
else if (length < 8)
{
pwdStrengthLabel.Text = "⚠ Занадто короткий";
pwdStrengthLabel.Foreground = new SolidColorBrush(Colors.OrangeRed);
}
else if (length < 12)
{
pwdStrengthLabel.Text = "✓ Задовільний";
pwdStrengthLabel.Foreground = new SolidColorBrush(Colors.Orange);
}
else
{
pwdStrengthLabel.Text = "✓✓ Надійний";
pwdStrengthLabel.Foreground = new SolidColorBrush(Colors.LimeGreen);
}
}
PasswordBox.Password у production-коді для реальної авторизації. Це повертає звичайний string, що залишається у пам'яті. Для авторизації передавайте SecurePassword у відповідні API (NetworkCredential, функції Windows DPAPI або зашифровані канали зв'язку). Якщо ваш застосунок сам хешує пароль для бази — використовуйте маршал-копіювання SecureString у char[], хешуйте і одразу очищайте масив.RichTextBox — найважчий із текстових контролів. Він надає повноцінний редактор форматованого тексту на основі FlowDocument — WPF-специфічного формату представлення документів. Якщо TextBox із AcceptsReturn="True" — це "блокнот", то RichTextBox — це "Word".
Сценарії, де RichTextBox є правильним вибором:
Сценарії, де RichTextBox надмірний:
TextBox.TextBlock з Inline-елементами.RichTextBox разом із FlowDocument є специфічними для WPF і не мають прямого аналога в Avalonia. Якщо ваш проєкт вимагає кросплатформності — розгляньте сторонні альтернативи (наприклад, AvalonEdit для Avalonia) або обмежтесь стандартним TextBox. Превью нижче виконується в Avalonia і може не підтримувати всі елементи FlowDocument.FlowDocument — це ієрархічна модель документа, яка описує текст як послідовність блоків (Block). Найпоширеніший блок — Paragraph. Всередині Paragraph розміщуються Inline-елементи (Run, Bold, Italic, Hyperlink). У XAML вміст RichTextBox описується так:
<RichTextBox>
<FlowDocument>
<Paragraph>
<Run>Перший параграф зі </Run>
<Bold>жирним</Bold>
<Run> та </Run>
<Italic>курсивним</Italic>
<Run> текстом.</Run>
</Paragraph>
<Paragraph>
Другий параграф — щоразу новий відступ.
</Paragraph>
</FlowDocument>
</RichTextBox>
Loading Avalonia WebAssembly...
Downloading .NET runtime (10MB)...
<StackPanel Margin="20" Spacing="12">
<TextBlock Text="RichTextBox із початковим форматованим вмістом:"
Foreground="Gray" FontSize="13"/>
<RichTextBox Height="140" Padding="8">
<FlowDocument>
<Paragraph FontSize="16" FontWeight="Bold">
Заголовок документа
</Paragraph>
<Paragraph>
<Run>Це перший параграф. Тут є </Run>
<Bold>жирний текст</Bold>
<Run>, є </Run>
<Italic>курсивний текст</Italic>
<Run> та </Run>
<Underline>підкреслений текст</Underline>
<Run>.</Run>
</Paragraph>
<Paragraph Foreground="Gray" FontSize="12">
Другий параграф — менший шрифт, сірий колір. RichTextBox підтримує
редагування цього вмісту без будь-якого коду.
</Paragraph>
</FlowDocument>
</RichTextBox>
</StackPanel>
Щоб додати до RichTextBox кнопки форматування (жирний, курсив, розмір шрифту), використовується метод Selection.ApplyPropertyValue(). Selection — це об'єкт типу TextSelection, що представляє поточне виділення у RichTextBox:
// Зробити виділений текст жирним
private void BoldButton_Click(object sender, RoutedEventArgs e)
{
// Читаємо поточний стан виділення
object currentWeight = richEditor.Selection.GetPropertyValue(
TextElement.FontWeightProperty
);
// Перемикаємо між Bold і Normal
FontWeight newWeight = (currentWeight is FontWeight fw && fw == FontWeights.Bold)
? FontWeights.Normal
: FontWeights.Bold;
richEditor.Selection.ApplyPropertyValue(
TextElement.FontWeightProperty,
newWeight
);
richEditor.Focus(); // Повертаємо фокус до редактора
}
// Змінити розмір шрифту виділення
private void FontSizeCombo_SelectionChanged(object sender, ...)
{
if (fontSizeCombo.SelectedItem is string sizeStr
&& double.TryParse(sizeStr, out double size))
{
richEditor.Selection.ApplyPropertyValue(
TextElement.FontSizeProperty,
size
);
}
}
Метод ApplyPropertyValue приймає будь-яку DependencyProperty з простору TextElement, Paragraph, Inline — тобто будь-яке форматування, яке підтримує модель документа. Це робить RichTextBox надзвичайно гнучким, але й складнішим у роботі порівняно зі звичайними контролами.
Ціль: Закріпити різницю між Label та TextBlock, розуміння AccessKey.
Завдання: Реалізуйте просту форму з двома полями — "Ім'я" та "Email". Для кожного поля — Label з AccessKey (наприклад, _Ім'я: і _Email:), прив'язаний через Target до відповідного TextBox. Нижче — кнопка "Надіслати" (IsDefault="True").
Що перевірити:
І — фокус переходить на поле "Ім'я".E — фокус переходить на поле "Email".Ціль: Практика TextBox з AcceptsReturn, TextChanged та MaxLength.
Завдання: Реалізуйте мінімалістичний текстовий редактор:
TextBox (AcceptsReturn="True", AcceptsTab="True", TextWrapping="Wrap", VerticalScrollBarVisibility="Auto").TextBox.Text.Length, Text.Split('\n').Length).MaxLength="500"), лічильник стає помаранчовим при > 450.Clipboard.SetText(textBox.Text).Ціль: Практика PasswordBox, PasswordChanged, валідації у code-behind.
Завдання: Реалізуйте форму реєстрації з полями "Логін", "Пароль", "Підтвердження пароля":
TextBox для логіну з MaxLength="30" та лічильником символів.PasswordBox для пароля з індикатором надійності (< 8 символів — слабкий, 8–12 — задовільний, > 12 — надійний).PasswordBox для підтвердження паролю. При PasswordChanged — перевірка збігу з першим (якщо не збігається — TextBlock з "Паролі не збігаються" у червоному).IsDefault="True") — активна лише якщо логін непорожній, пароль ≥ 8 символів, паролі збігаються. Якщо умови не виконані — кнопка IsEnabled="False".MessageBox.Show("Успішно!").У цій статті ми розглянули п'ять текстових контролів WPF і розібрались, коли який з них є правильним вибором.
TextBlock vs Label — не просто стилістична різниця: TextBlock є легковісним FrameworkElement без фокусу і підходить для будь-якого відображення тексту; Label — повноцінний ContentControl із підтримкою AccessKey і Target, незамінний для доступних форм. Використовуйте Label лише там, де потрібні ці можливості.
TextBlock з Inline-елементами — потужний спосіб отримати форматований текст без RichTextBox. Bold, Italic, Hyperlink, Run, LineBreak — цілий набір Inline-класів для оформлення статичного тексту. TextWrapping і TextTrimming контролюють поведінку при переповненні.
TextBox — основний контрол введення із широким набором опцій: AcceptsReturn (багаторядковий), MaxLength, IsReadOnly, TextChanged. Placeholder-текст у стандартному WPF реалізується через GotFocus/LostFocus або Style + Trigger.
PasswordBox зберігає пароль у SecureString — принципове архітектурне рішення безпеки. Властивість Password зручна, але менш безпечна; для production-коду — SecurePassword. PasswordChar дозволяє змінити символ маскування.
RichTextBox + FlowDocument — повноцінний редактор форматованого тексту. Вміст описується через Paragraph + Inline-елементи. Форматування виділення змінюється через Selection.ApplyPropertyValue(). Специфічний для WPF — не має прямого аналога в Avalonia.
У наступній статті ми розглянемо контроли вибору — CheckBox, RadioButton, ComboBox, ListBox. Ці контроли будуються поверх вже вивчених (ToggleButton, ItemsControl) і вводять нову концепцію — вибір з набору варіантів, що є фундаментом для зв'язування з колекціями даних.
Контроли в Avalonia: відмінності від WPF
Детальний порівняльний огляд стандартних контролів Avalonia та WPF: що повністю збігається, що відрізняється синтаксисом, що є в Avalonia але відсутнє у WPF — і навпаки. Практичний гід для тих, хто знає WPF і переходить на Avalonia.
Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker
Вивчаємо контроли WPF, що дозволяють обирати значення з набору варіантів — від простих прапорців і перемикачів до випадаючих списків, видимих переліків та вибору дати. Детальний розбір властивостей, подій і типових сценаріїв застосування.