Primary APIs:
Window, TopLevel, Grid, DockPanel, SplitView, TabControlContentControl, TransitioningContentControl, DataTemplatePopup, Flyout, ContextMenu, ToolTip, overlay/adorner layersMenu, MenuItem, NativeMenuBar, TitleBar, tray/notification helpersReference docs:
13-windowing-and-custom-decorations.md25-popups-flyouts-tooltips-and-overlays.md53-menu-controls-contextmenu-and-menuflyout-patterns.md48-toplevel-window-and-runtime-services.md| HTML landmark pattern | Avalonia composition pattern |
|---|---|
<header> |
top row in Grid or top-docked element in DockPanel |
<nav> / side rail |
SplitView pane, left Grid column, or TabControl navigation |
<main> |
primary content ContentControl / TransitioningContentControl |
<aside> |
secondary panel in extra column or pane |
<footer> |
bottom row in Grid |
| Web pattern | Avalonia pattern |
|---|---|
| client router outlet | ContentControl Content="{CompiledBinding CurrentViewModel}" + templates |
| tab navigation | TabControl |
| drawer/sidebar | SplitView |
| breadcrumb toolbar area | DockPanel with command controls |
| Web pattern | Avalonia pattern |
|---|---|
| modal dialog | owned Window/dialog flow |
| popover | Popup/Flyout |
| tooltip | ToolTip.Tip attached property |
| context menu | ContextMenu |
| notification toast | WindowNotificationManager |
ZIndex.Popup/Flyout rather than manual absolute overlays.HTML/CSS:
<div class="app-shell">
<header class="topbar">...</header>
<aside class="sidebar">...</aside>
<main class="main">...</main>
</div>
.app-shell {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: 56px 1fr;
min-height: 100vh;
}
.topbar { grid-column: 1 / span 2; position: sticky; top: 0; z-index: 100; }
.sidebar { grid-row: 2; }
.main { grid-row: 2; overflow: auto; }
Avalonia:
<Grid RowDefinitions="56,*" ColumnDefinitions="260,*">
<Border Grid.Row="0" Grid.ColumnSpan="2" ZIndex="100" Classes="topbar" />
<Border Grid.Row="1" Grid.Column="0" Classes="sidebar" />
<ScrollViewer Grid.Row="1" Grid.Column="1">
<ContentControl Content="{CompiledBinding CurrentPage}" />
</ScrollViewer>
</Grid>
HTML intent:
<div class="shell">
<header class="topbar">...</header>
<aside class="nav">...</aside>
<main class="content">...</main>
</div>
Avalonia XAML:
<Grid RowDefinitions="56,*" ColumnDefinitions="260,*">
<Border Grid.Row="0" Grid.ColumnSpan="2" Classes="topbar" />
<SplitView Grid.Row="1" Grid.Column="0"
DisplayMode="CompactInline"
IsPaneOpen="True"
OpenPaneLength="260"
CompactPaneLength="64">
<SplitView.Pane>
<StackPanel Spacing="6">
<Button Content="Dashboard" />
<Button Content="Reports" />
</StackPanel>
</SplitView.Pane>
</SplitView>
<TransitioningContentControl Grid.Row="1" Grid.Column="1"
Content="{CompiledBinding CurrentPage}" />
</Grid>
Context actions via Flyout:
<Button Content="Actions">
<Button.Flyout>
<MenuFlyout>
<MenuItem Header="Duplicate" Command="{CompiledBinding DuplicateCommand}" />
<MenuItem Header="Archive" Command="{CompiledBinding ArchiveCommand}" />
</MenuFlyout>
</Button.Flyout>
</Button>
using Avalonia.Controls;
var shell = new Grid
{
RowDefinitions = RowDefinitions.Parse("56,*"),
ColumnDefinitions = ColumnDefinitions.Parse("260,*")
};
var topBar = new Border();
Grid.SetRow(topBar, 0);
Grid.SetColumnSpan(topBar, 2);
var splitView = new SplitView
{
DisplayMode = SplitViewDisplayMode.CompactInline,
IsPaneOpen = true,
OpenPaneLength = 260,
CompactPaneLength = 64,
Pane = new StackPanel
{
Spacing = 6,
Children =
{
new Button { Content = "Dashboard" },
new Button { Content = "Reports" }
}
}
};
Grid.SetRow(splitView, 1);
Grid.SetColumn(splitView, 0);
var pageHost = new TransitioningContentControl();
Grid.SetRow(pageHost, 1);
Grid.SetColumn(pageHost, 1);
shell.Children.Add(topBar);
shell.Children.Add(splitView);
shell.Children.Add(pageHost);
var actionsButton = new Button { Content = "Actions" };
actionsButton.Flyout = new MenuFlyout
{
Items =
{
new MenuItem { Header = "Duplicate" },
new MenuItem { Header = "Archive" }
}
};
DataTemplate + compiled bindings).Dispatcher.UIThread.DisplayMode and pane lengths by breakpoint class/state.