Primary WinForms APIs:
Panel, FlowLayoutPanel, TableLayoutPanelControl.Dock, Control.AnchorPrimary Avalonia APIs:
Grid, StackPanel, WrapPanel, DockPanel, RelativePanelGrid.RowDefinitions, Grid.ColumnDefinitionsGrid.IsSharedSizeScope, SharedSizeGroup| WinForms | Avalonia |
|---|---|
Panel |
Border + Grid or StackPanel |
FlowLayoutPanel |
WrapPanel (wrapping) or StackPanel (single axis) |
TableLayoutPanel |
Grid with explicit rows/columns |
AutoScroll container |
ScrollViewer |
| WinForms idiom | Avalonia idiom |
|---|---|
DockStyle.Top |
DockPanel.Dock="Top" |
DockStyle.Fill |
star-sized Grid cell or last child of DockPanel |
AnchorStyles.Right |
HorizontalAlignment="Right" |
AnchorStyles.Bottom | Right |
place in bottom row + HorizontalAlignment="Right" |
WinForms C# (TableLayoutPanel + FlowLayoutPanel):
var table = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = 2,
RowCount = 2
};
table.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 180));
table.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
var flow = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.LeftToRight };
flow.Controls.Add(new Button { Text = "Save" });
flow.Controls.Add(new Button { Text = "Cancel" });
table.Controls.Add(new Label { Text = "Name" }, 0, 0);
table.Controls.Add(new TextBox(), 1, 0);
table.Controls.Add(flow, 1, 1);
Avalonia XAML:
<Grid xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.ViewModels"
x:DataType="vm:FormLayoutViewModel"
RowDefinitions="Auto,Auto"
ColumnDefinitions="180,*"
RowSpacing="8"
ColumnSpacing="12">
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Text="Name" />
<TextBox Grid.Row="0" Grid.Column="1" />
<WrapPanel Grid.Row="1" Grid.Column="1" Spacing="8" Orientation="Horizontal">
<Button Content="Save" Command="{CompiledBinding SaveCommand}" />
<Button Content="Cancel" Command="{CompiledBinding CancelCommand}" />
</WrapPanel>
</Grid>
Avalonia C#:
using Avalonia.Controls;
var grid = new Grid
{
RowDefinitions = RowDefinitions.Parse("Auto,Auto"),
ColumnDefinitions = ColumnDefinitions.Parse("180,*"),
RowSpacing = 8,
ColumnSpacing = 12
};
grid.Children.Add(new TextBlock { Text = "Name", VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center });
var nameBox = new TextBox();
Grid.SetColumn(nameBox, 1);
grid.Children.Add(nameBox);
var actions = new WrapPanel { Spacing = 8, Orientation = Avalonia.Layout.Orientation.Horizontal };
actions.Children.Add(new Button { Content = "Save", Command = viewModel.SaveCommand });
actions.Children.Add(new Button { Content = "Cancel", Command = viewModel.CancelCommand });
Grid.SetRow(actions, 1);
Grid.SetColumn(actions, 1);
grid.Children.Add(actions);
For table-like forms with aligned header/body columns, use shared-size groups:
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="LabelCol" />
<ColumnDefinition SharedSizeGroup="ValueCol" />
</Grid.ColumnDefinitions>
</Grid>
This pattern is the closest replacement for complex designer-driven TableLayoutPanel setups.
WrapPanel instead of StackPanel.Grid.IsSharedSizeScope and matching SharedSizeGroup names.