Panels Overview
Panel
elements are components that control the rendering of elements - their size and dimensions, their position, and the arrangement of their child content. Avalonia UI provides a number of predefined Panel
elements as well as the ability to construct custom Panel
elements.
The Panel Class
Panel
is the base class for all elements that provide layout support in Avalonia. Derived Panel
elements are used to position and arrange elements in XAML and code.
Avalonia includes a comprehensive suite of derived panel implementations that enable many complex layouts. These derived classes expose properties and methods that enable most standard UI scenarios. Developers who are unable to find a child arrangement behavior that meets their needs can create new layouts by overriding the ArrangeOverride
and MeasureOverride
methods. For more information on custom layout behaviors, see Create a Custom Panel.
Panel Common Members
All Panel
elements support the base sizing and positioning properties defined by Control
, including Height
, Width
, HorizontalAlignment
, VerticalAlignment
and Margin
. For additional information on positioning properties defined by Control
, see Alignment, Margins, and Padding Overview.
Panel
exposes additional properties that are of critical importance in understanding and using layout. The Background
property is used to fill the area between the boundaries of a derived panel element with a Brush
. Children
represents the child collection of elements that the Panel
is comprised of.
Attached Properties
Derived panel elements make extensive use of attached properties. An attached property is a specialized form of dependency property that does not have the conventional common language runtime (CLR) property "wrapper". Attached properties have a specialized syntax in XAML, which can be seen in several of the examples that follow.
One purpose of an attached property is to allow child elements to store unique values of a property that is actually defined by a parent element. An application of this functionality is having child elements inform the parent how they wish to be presented in the UI, which is extremely useful for application layout.
User Interface Panels
There are several panel classes available in Avalonia that are optimized to support UI scenarios: Panel
, Canvas
, DockPanel
, Grid
, StackPanel
, WrapPanel
and RelativePanel
. These panel elements are easy to use, versatile, and extensible enough for most applications.
Canvas
The Canvas
element enables positioning of content according to absolute x- and y- coordinates. Elements can be drawn in a unique location; or, if elements occupy the same coordinates, the order in which they appear in markup determines the order in which the elements are drawn.
Canvas
provides the most flexible layout support of any Panel
. Height and Width properties are used to define the area of the canvas, and elements inside are assigned absolute coordinates relative to the area of the parent Canvas
. Four attached properties, Canvas.Left
, Canvas.Top
, Canvas.Right
and Canvas.Bottom
, allow fine control of object placement within a Canvas
, allowing the developer to position and arrange elements precisely on the screen.
ClipToBounds Within a Canvas
Canvas
can position child elements at any position on the screen, even at coordinates that are outside of its own defined Height
and Width
. Furthermore, Canvas
is not affected by the size of its children. As a result, it is possible for a child element to overdraw other elements outside the bounding rectangle of the parent Canvas
. The default behavior of a Canvas
is to allow children to be drawn outside the bounds of the parent Canvas
. If this behavior is undesirable, the ClipToBounds
property can be set to true
. This causes Canvas
to clip to its own size. Canvas
is the only layout element that allows children to be drawn outside its bounds.
Defining and Using a Canvas
A Canvas
can be instantiated simply by using XAML or code. The following example demonstrates how to use Canvas
to absolutely position content. This code produces three 100-pixel squares. The first square is red, and its top-left (x, y) position is specified as (0, 0). The second square is green, and its top-left position is (100, 100), just below and to the right of the first square. The third square is blue, and its top-left position is (50, 50), thus encompassing the lower-right quadrant of the first square and the upper-left quadrant of the second. Because the third square is laid out last, it appears to be on top of the other two squares—that is, the overlapping portions assume the color of the third box.
- XAML
- C#
<Canvas Height="400" Width="400">
<Canvas Height="100" Width="100" Top="0" Left="0" Background="Red"/>
<Canvas Height="100" Width="100" Top="100" Left="100" Background="Green"/>
<Canvas Height="100" Width="100" Top="50" Left="50" Background="Blue"/>
</Canvas>
// Create the Canvas
myParentCanvas = new Canvas();
myParentCanvas.Width = 400;
myParentCanvas.Height = 400;
// Define child Canvas elements
myCanvas1 = new Canvas();
myCanvas1.Background = Brushes.Red;
myCanvas1.Height = 100;
myCanvas1.Width = 100;
Canvas.SetTop(myCanvas1, 0);
Canvas.SetLeft(myCanvas1, 0);
myCanvas2 = new Canvas();
myCanvas2.Background = Brushes.Green;
myCanvas2.Height = 100;
myCanvas2.Width = 100;
Canvas.SetTop(myCanvas2, 100);
Canvas.SetLeft(myCanvas2, 100);
myCanvas3 = new Canvas();
myCanvas3.Background = Brushes.Blue;
myCanvas3.Height = 100;
myCanvas3.Width = 100;
Canvas.SetTop(myCanvas3, 50);
Canvas.SetLeft(myCanvas3, 50);
// Add child elements to the Canvas' Children collection
myParentCanvas.Children.Add(myCanvas1);
myParentCanvas.Children.Add(myCanvas2);
myParentCanvas.Children.Add(myCanvas3);
DockPanel
The DockPanel
element uses the DockPanel.Dock
attached property as set in child content elements to position content along the edges of a container. When DockPanel.Dock
is set to Top
or Bottom
, it positions child elements above or below each other. When DockPanel.Dock
is set to Left
or Right
, it positions child elements to the left or right of each other. The LastChildFill
property determines the position of the final element added as a child of a DockPanel
.
You can use DockPanel
to position a group of related controls, such as a set of buttons. Alternately, you can use it to create a "paned" UI.
Sizing to Content
If its Height
and Width
properties are not specified, DockPanel
sizes to its content. The size can increase or decrease to accommodate the size of its child elements. However, when these properties are specified and there is no longer room for the next specified child element, DockPanel
does not display that child element or subsequent child elements and does not measure subsequent child elements.
LastChildFill
By default, the last child of a DockPanel
element will "fill" the remaining, unallocated space. If this behavior is not desired, set the LastChildFill
property to false
.
Defining and Using a DockPanel
The following example demonstrates how to partition space using a DockPanel
. Five Border
elements are added as children of a parent DockPanel
. Each uses a different positioning property of a DockPanel
to partition space. The final element "fills" the remaining, unallocated space.
- XAML
- C#
<DockPanel LastChildFill="True">
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="SkyBlue" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Top">
<TextBlock Foreground="Black">Dock = "Top"</TextBlock>
</Border>
<Border Height="25" Background="LemonChiffon" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Bottom">
<TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
</Border>
<Border Width="200" Background="PaleGreen" BorderBrush="Black" BorderThickness="1" DockPanel.Dock="Left">
<TextBlock Foreground="Black">Dock = "Left"</TextBlock>
</Border>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<TextBlock Foreground="Black">This content will "Fill" the remaining space</TextBlock>
</Border>
</DockPanel>
// Create the DockPanel
DockPanel myDockPanel = new DockPanel();
myDockPanel.LastChildFill = true;
// Define the child content
Border myBorder1 = new Border();
myBorder1.Height = 25;
myBorder1.Background = Brushes.SkyBlue;
myBorder1.BorderBrush = Brushes.Black;
myBorder1.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder1, Dock.Top);
TextBlock myTextBlock1 = new TextBlock();
myTextBlock1.Foreground = Brushes.Black;
myTextBlock1.Text = "Dock = Top";
myBorder1.Child = myTextBlock1;
Border myBorder2 = new Border();
myBorder2.Height = 25;
myBorder2.Background = Brushes.SkyBlue;
myBorder2.BorderBrush = Brushes.Black;
myBorder2.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder2, Dock.Top);
TextBlock myTextBlock2 = new TextBlock();
myTextBlock2.Foreground = Brushes.Black;
myTextBlock2.Text = "Dock = Top";
myBorder2.Child = myTextBlock2;
Border myBorder3 = new Border();
myBorder3.Height = 25;
myBorder3.Background = Brushes.LemonChiffon;
myBorder3.BorderBrush = Brushes.Black;
myBorder3.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder3, Dock.Bottom);
TextBlock myTextBlock3 = new TextBlock();
myTextBlock3.Foreground = Brushes.Black;
myTextBlock3.Text = "Dock = Bottom";
myBorder3.Child = myTextBlock3;
Border myBorder4 = new Border();
myBorder4.Width = 200;
myBorder4.Background = Brushes.PaleGreen;
myBorder4.BorderBrush = Brushes.Black;
myBorder4.BorderThickness = new Thickness(1);
DockPanel.SetDock(myBorder4, Dock.Left);
TextBlock myTextBlock4 = new TextBlock();
myTextBlock4.Foreground = Brushes.Black;
myTextBlock4.Text = "Dock = Left";
myBorder4.Child = myTextBlock4;
Border myBorder5 = new Border();
myBorder5.Background = Brushes.White;
myBorder5.BorderBrush = Brushes.Black;
myBorder5.BorderThickness = new Thickness(1);
TextBlock myTextBlock5 = new TextBlock();
myTextBlock5.Foreground = Brushes.Black;
myTextBlock5.Text = "This content will Fill the remaining space";
myBorder5.Child = myTextBlock5;
// Add child elements to the DockPanel Children collection
myDockPanel.Children.Add(myBorder1);
myDockPanel.Children.Add(myBorder2);
myDockPanel.Children.Add(myBorder3);
myDockPanel.Children.Add(myBorder4);
myDockPanel.Children.Add(myBorder5);