Goal
NumericUpDown, MaskedTextBox, AutoCompleteBox, ColorPicker, TreeView, TabControl, and SplitView.Why this matters
Prerequisites
dotnet new avalonia.mvvm -o ControlsShowcase
cd ControlsShowcase
We will extend Views/MainWindow.axaml with multiple sections backed by MainWindowViewModel.
| Scenario | Key controls | Highlights | Source snapshot |
|---|---|---|---|
| Text & numeric input | TextBox, MaskedTextBox, NumericUpDown, DatePicker |
Validation-friendly inputs with watermarks, masks, spinner buttons, culture-aware dates | TextBox.cs, MaskedTextBox, NumericUpDown, DatePicker |
| Toggles & commands | ToggleSwitch, CheckBox, RadioButton, Button |
MVVM-friendly toggles and grouped options with automation peers | ToggleSwitch.cs |
| Lists & selection | ListBox, TreeView, SelectionModel, ItemsRepeater |
Single/multi-select, hierarchical data, virtualization | SelectionModel, TreeView |
| Navigation surfaces | TabControl, SplitView, Expander, TransitioningContentControl |
Tabbed pages, collapsible panes, animated transitions | SplitView, TransitioningContentControl |
| Search & pickers | AutoCompleteBox, ComboBox, ColorPicker, FilePicker dialogs |
Suggest-as-you-type, palette pickers, storage providers | AutoCompleteBox, ColorPicker |
| Command surfaces | SplitButton, Menu, ContextMenu, Toolbar |
Primary/secondary actions, keyboard shortcuts, flyouts | SplitButton, Menu |
| Refresh & feedback | RefreshContainer, RefreshVisualizer, WindowNotificationManager, StatusBar, NotificationCard |
Pull-to-refresh gestures, toast notifications, status indicators | RefreshContainer, WindowNotificationManager |
Use this table as a map while exploring ControlCatalog; each section below dives into exemplars from these categories.
<StackPanel Spacing="16">
<TextBlock Classes="h1" Text="Customer profile"/>
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto" RowSpacing="8" ColumnSpacing="12">
<TextBlock Text="Name:"/>
<TextBox Grid.Column="1" Text="{Binding Customer.Name}" Watermark="Full name"/>
<TextBlock Grid.Row="1" Text="Email:"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Customer.Email}"/>
<TextBlock Grid.Row="2" Text="Phone:"/>
<MaskedTextBox Grid.Row="2" Grid.Column="1" Mask="(000) 000-0000" Value="{Binding Customer.Phone}"/>
</Grid>
<StackPanel Orientation="Horizontal" Spacing="12">
<NumericUpDown Width="120" Minimum="0" Maximum="20" Value="{Binding Customer.Seats}" Header="Seats"/>
<DatePicker SelectedDate="{Binding Customer.RenewalDate}" Header="Renewal"/>
</StackPanel>
</StackPanel>
Notes:
MaskedTextBox lives in Avalonia.Controls (see MaskedTextBox.cs) and enforces input patterns.NumericUpDown (from NumericUpDown.cs) provides spinner buttons and numeric formatting.AutomationProperties.Name or HelpText on inputs so screen readers identify the fields correctly.<GroupBox Header="Plan options" Padding="12">
<StackPanel Spacing="8">
<ToggleSwitch Header="Enable auto-renew" IsChecked="{Binding Customer.AutoRenew}"/>
<StackPanel Orientation="Horizontal" Spacing="12">
<CheckBox Content="Include analytics" IsChecked="{Binding Customer.IncludeAnalytics}"/>
<CheckBox Content="Priority support" IsChecked="{Binding Customer.IncludeSupport}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="12">
<RadioButton GroupName="Plan" Content="Starter" IsChecked="{Binding Customer.IsStarter}"/>
<RadioButton GroupName="Plan" Content="Growth" IsChecked="{Binding Customer.IsGrowth}"/>
<RadioButton GroupName="Plan" Content="Enterprise" IsChecked="{Binding Customer.IsEnterprise}"/>
</StackPanel>
<Button Content="Save" HorizontalAlignment="Left" Command="{Binding SaveCommand}"/>
</StackPanel>
</GroupBox>
ToggleSwitch gives a Fluent-styled toggle. Implementation: ToggleSwitch.cs.GroupName or IsChecked bindings.<GroupBox Header="Teams" Padding="12">
<ListBox Items="{Binding Teams}" SelectedItem="{Binding SelectedTeam}" Height="160">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Spacing="12">
<Ellipse Width="24" Height="24" Fill="{Binding Color}"/>
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</GroupBox>
ListBox supports selection out of the box. For custom selection logic, use SelectionModel (see SelectionModel.cs).ListBox.SelectionMode="Multiple" for multi-select.Large lists should virtualize. Use ListBox with the default VirtualizingStackPanel or switch panels:
<ListBox Items="{Binding ManyItems}" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.CacheLength="2"/>
Controls for virtualization: VirtualizingStackPanel.cs.
TreeView<TreeView Items="{Binding Departments}" SelectedItems="{Binding SelectedDepartments}">
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Teams}">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold"/>
<TreeDataTemplate.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" Margin="24,0,0,0"/>
</DataTemplate>
</TreeDataTemplate.ItemTemplate>
</TreeDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
TreeView uses TreeDataTemplate to describe hierarchical data. Each template can reference a property (Teams) for child items.TreeView.cs.TabControl, SplitView, Expander)<TabControl SelectedIndex="{Binding SelectedTab}">
<TabItem Header="Overview">
<TextBlock Text="Overview content" Margin="12"/>
</TabItem>
<TabItem Header="Reports">
<TextBlock Text="Reports content" Margin="12"/>
</TabItem>
<TabItem Header="Settings">
<TextBlock Text="Settings content" Margin="12"/>
</TabItem>
</TabControl>
<SplitView DisplayMode="CompactInline"
IsPaneOpen="{Binding IsPaneOpen}"
OpenPaneLength="240" CompactPaneLength="56">
<SplitView.Pane>
<NavigationViewContent/>
</SplitView.Pane>
<SplitView.Content>
<Frame Content="{Binding ActivePage}"/>
</SplitView.Content>
</SplitView>
<Expander Header="Advanced filters" IsExpanded="False">
<StackPanel Margin="12" Spacing="8">
<ComboBox Items="{Binding FilterSets}" SelectedItem="{Binding SelectedFilter}"/>
<CheckBox Content="Include archived" IsChecked="{Binding IncludeArchived}"/>
</StackPanel>
</Expander>
TabControl enables tabbed navigation. Tab headers are content--you can template them via TabControl.ItemTemplate.SplitView (from SplitView.cs) provides collapsible navigation, useful for sidebars.Expander collapses/expands content. Implementation: Expander.cs.<StackPanel Spacing="12">
<SplitButton Content="Export" Command="{Binding ExportAllCommand}">
<SplitButton.Flyout>
<MenuFlyout>
<MenuItem Header="Export CSV" Command="{Binding ExportCsvCommand}"/>
<MenuItem Header="Export JSON" Command="{Binding ExportJsonCommand}"/>
<MenuItem Header="Export PDF" Command="{Binding ExportPdfCommand}"/>
</MenuFlyout>
</SplitButton.Flyout>
</SplitButton>
<Menu>
<MenuItem Header="File">
<MenuItem Header="New" Command="{Binding NewCommand}"/>
<MenuItem Header="Open..." Command="{Binding OpenCommand}"/>
<Separator/>
<MenuItem Header="Exit" Command="{Binding ExitCommand}"/>
</MenuItem>
<MenuItem Header="Help" Command="{Binding ShowHelpCommand}"/>
</Menu>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Copy" Command="{Binding CopyCommand}" HotKey="Ctrl+C"/>
<Button Content="Paste" Command="{Binding PasteCommand}" HotKey="Ctrl+V"/>
</StackPanel>
</StackPanel>
Notes:
SplitButton exposes a primary command and a flyout for secondary options. Automation peers surface both the button and flyout; see SplitButton.cs.Menu/ContextMenu support keyboard navigation and AutomationProperties.AcceleratorKey so shortcuts are announced to assistive tech. Implementation: Menu.cs.MenuFlyout, Popup, FlyoutBase). Use FlyoutBase.ShowAttachedFlyout to open context actions from command handlers.<StackPanel Spacing="12">
<AutoCompleteBox Width="240"
Items="{Binding Suggestions}"
Text="{Binding Query, Mode=TwoWay}">
<AutoCompleteBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="{Binding Icon}"/>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</DataTemplate>
</AutoCompleteBox.ItemTemplate>
</AutoCompleteBox>
<ColorPicker SelectedColor="{Binding ThemeColor}"/>
<Button Content="Choose files" Command="{Binding OpenFilesCommand}"/>
</StackPanel>
AutoCompleteBox helps with large suggestion lists. Source: AutoCompleteBox.cs.ColorPicker shows palettes, sliders, and input fields (see ColorPicker.cs).IStorageProvider (Chapter 16).<Window xmlns:ptr="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
xmlns:notifications="clr-namespace:Avalonia.Controls.Notifications;assembly=Avalonia.Controls"
...>
<Grid>
<ptr:RefreshContainer RefreshRequested="OnRefreshRequested">
<ptr:RefreshContainer.Visualizer>
<ptr:RefreshVisualizer Orientation="TopToBottom"
Content="Pull to refresh"/>
</ptr:RefreshContainer.Visualizer>
<ScrollViewer>
<ItemsControl Items="{Binding Orders}"/>
</ScrollViewer>
</ptr:RefreshContainer>
</Grid>
</Window>
private async void OnRefreshRequested(object? sender, RefreshRequestedEventArgs e)
{
using var deferral = e.GetDeferral();
await ViewModel.ReloadAsync();
}
RefreshContainer + RefreshVisualizer implement pull-to-refresh on any scrollable surface. Source: RefreshContainer.var notifications = new WindowNotificationManager(this)
{
Position = NotificationPosition.TopRight,
MaxItems = 3
};
notifications.Show(new Notification("Update available", "Restart to apply updates.", NotificationType.Success));
WindowNotificationManager displays toast notifications layered over the current window; combine with inline NotificationCard or InfoBar for longer-lived messages. Sources: WindowNotificationManager, NotificationCard.AutomationProperties.LiveSetting="Polite" so assistive technologies announce them.<StatusBar>
<StatusBarItem>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Ready"/>
<ProgressBar Width="120" IsIndeterminate="{Binding IsBusy}"/>
</StackPanel>
</StatusBarItem>
<StatusBarItem HorizontalAlignment="Right">
<TextBlock Text="v1.2.0"/>
</StatusBarItem>
</StatusBar>
StatusBar hosts persistent indicators (connection status, progress). Implementation: StatusBar.Use classes (Classes="primary") or pseudo-classes (:pointerover, :pressed, :checked) to style stateful controls:
<Button Content="Primary" Classes="primary"/>
<Style Selector="Button.primary">
<Setter Property="Background" Value="{DynamicResource AccentBrush}"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style Selector="Button.primary:pointerover">
<Setter Property="Background" Value="{DynamicResource AccentBrush2}"/>
</Style>
Styles live in App.axaml or separate resource dictionaries. Control templates are defined under src/Avalonia.Themes.Fluent. Inspect Button.xaml, ListBox.xaml, etc., to understand structure and visual states.
dotnet run --project samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj.Source tab to jump to relevant XAML or C# files.src/Avalonia.Controls/TextBox.cs.VirtualizingStackPanel.cs.SplitView.cs and TabControl templates.SplitButton, and a collapsible filter panel. Bind every control to a view model.AutoCompleteBox that filters as you type. Use DevTools to inspect the generated ListBox inside the control and verify automation names.ListBox with a TreeView for hierarchical data; add an Expander per root item.RefreshContainer around a scrollable list and implement the RefreshRequested deferal pattern. Provide a fallback refresh button for keyboard users.WindowNotificationManager, show a toast when the refresh completes, and style inline NotificationCard messages for success and error states.WrapPanel for an ItemsRepeater (Chapter 14) to prepare for virtualization scenarios.src/Avalonia.Controlssrc/Avalonia.Controls.ColorPicker, src/Avalonia.Controls.NumericUpDown, src/Avalonia.Controls.AutoCompleteBoxsrc/Avalonia.Controls/SplitButton, src/Avalonia.Controls/SplitViewsrc/Avalonia.Controls/PullToRefresh, src/Avalonia.Controls/Notificationssrc/Avalonia.Controls/Selectionsrc/Avalonia.Themes.Fluent/ControlsListBox items and enable virtualization for large datasets?ToggleSwitch?SelectionModel play for advanced selection scenarios?What's next