WPF Layouts
Layout is a fundamental building block used when writing any WPF, no matter whether it's a web based or an application. Using the layout controls in WPF allows developers/designers to create very complex arrangements of pages/controls. Without layout, we probably couldn't achieve anything, apart from a mess.
Within WPF, Microsoft has provided a few Layout controls for developers/designers to use.
- Canvas
- StackPanel
- WrapPanel
- DockPanel
- Grid
The Canvas control, is one of the easier layout controls to use. It is a simple X/Y position container. Where each of the contained (children) controls must specify the following four properties in order to be positioned within the parent Canvas control:
- Canvas.Left
- Canvas.Right
- Canvas.Top
- Canvas.Bottom
What else do we need to know about a Canvas control and its children. Well actually that's almost it, the only other thing to consider is that if the Canvas control is a simple X/Y position container, what's to stop two child controls, overlapping, and which child control should be on top. Well that's all taken care of by another dependency/attached property of the Canvas control. This is called the Canvas.ZIndex property, and this indicates which control should be on top. Basically the higher the Canvas.ZIndex value is, the more on top the control that declares this dependency/attached property will be. If no Canvas.ZIndex is declared for any of the children controls, the Canvas.ZIndex will be set to the order in which the children are added to the Canvas control.
With these four properties in place, the control will be positioned using these values within the parent Canvas control. These are not normal properties that you used in .NET 2.0 land. These are dependency/attached properties
|
So how does this look in code? Well in XAML, it is as follows:
<Window x:Class="CanvasDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Canvas Demo" Height="640" Width="480">
<Canvas Margin="0,0,0,0" Background="White">
<Rectangle Fill="SeaGreen"
Stroke="SeaGreen"
Width="145"
Height="126"
Canvas.Left="124" Canvas.Top="122" />
<Ellipse Fill="CadetBlue"
Stroke="CadetBlue"
Width="121" Height="100"
Panel.ZIndex="1"
Canvas.Left="195" Canvas.Top="191" />
</Canvas>
</Window>
|
|
The StackPanel control is also very easy to use. It simply stacks its contents, vertically or horizontally, using a single property, called Orientation.The StackPanel lays out child elements by stacking them one after the other. Elements are "stacked" in the order they appear in the Xaml file (document order in XML terms). Items can either be stacked vertically (the default) or horizontally.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/
presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WPF_Tour_Beginners_Layout.StackPanelDEMO"
x:Name="Window"
Title="StackPanelDEMO"
WindowStartupLocation="CenterScreen"
Width="640" Height="480">
<StackPanel Margin="0,0,0,0" Background="White"
Orientation="Vertical">
<Button Content="Im Top of Stack"/>
<Button Content="Im Bottom Of Stack"/>
</StackPanel>
</Window>
|
|
A WrapPanel control is used to arrange child controls to arrange vertically or horizontally. The wrap panel lays out items from left to right. When a row of items has filled the horizontal space available to them the panel wraps the next item around onto the next line (in a similar way to how text is layed out).
<Window x:Class="CanvasDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/
presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WrapPanel Demo" Height="640" Width="480">
<WrapPanel Margin="0,0,0,0" Background="White">
<Ellipse Width="100" Height="100" Fill="Red" />
<Ellipse Width="80" Height="80" Fill="Orange" />
<Ellipse Width="60" Height="60" Fill="Yellow" />
<Ellipse Width="40" Height="40" Fill="Green" />
<Ellipse Width="20" Height="20" Fill="Blue" />
</WrapPanel>
</Window>
|
|
The DockPanel control is one of the most useful layout controls. It is the one that we would probably use as the base layout control that any new Window uses. Basically with a DockPanel control, we can achieve the sort of layout that has been the main layout for most applications we have ever seen. We can basically get a menu docked to the top, then a left/right main content area, and a status strip at the bottom. This is all thanks to a couple of properties on the DockPanel control. Basically we can control the docking of any of our child controls that is within a parent DockPanel control by the use of the following dependency/attached property.
DockPanel.Dock property may be set to Left/Right/Top or Bottom. There is one further property exposed as a normal CLR property on the DockPanel control which is called LastChildFill which when set to true will make the last child control that was added to the DockPanel control, fill the remaining available space. This will override any DockPanel.Dock property that the child control may have already set.
<Window x:Class="CanvasDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/
2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/
2006/xaml"
Title="DockPanel Demo" Height="640"
Width="480">
<DockPanel Width="Auto" Height="Auto"
LastChildFill="True" >
<Rectangle Fill="CornflowerBlue"
Stroke="CornflowerBlue"
Height="20" DockPanel.Dock="Top" />
<Rectangle Fill="Aqua" Stroke="Aqua"
Height="40" DockPanel.Dock="Top" />
<Rectangle Fill="Orange"
Stroke="Orange" />
</DockPanel>
</Window>
|
|
The Grid control, is by far, the most sophisticated WPF layout control there is. It is sort of like an HTML table control, where you can specify rows and columns, and have cells that span multiple rows, or cells that span multiple columns. There is also a strange syntax which may be used for the Width/Height of Columns and Rows, which is known as the Star "*" notation, which is exposed through the use of the GridLength class. Think of this as being like a percentage of what's left divider. For example I could have some markup such as:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
Where I have declared three Grid ColumnDefinition controls, where the first ColumnDefinition gets a fixed width of 60 pixels, and the remaining space is divided between the last two ColumnDefinition controls, where the last one gets thrice as much as the second last one. This is the same principle for RowDefinition.
In order for child controls of a Grid control to tell the WPF layout system which cell they belong to, we simply use the following dependency/attached properties, which use a 0 based index.
- Grid.Column
- Grid.Row
And to specify how many rows or columns a cell should occupy, we simply use the following dependency/attached properties, which starts at 1.
- Grid.ColumnSpan
- Grid.RowSpan
By clever usage of a Grid control, you should almost be able to mimic any of the other layout controls. Let's see an example of the Grid control. The following application shows a Grid control with 3 Columns and 1 Row, where there are two children. The first child occupies Column 1, and the second child occupies Columns 2-3 as its Grid.ColumnSpan is set to 2.
<Window x:Class="CanvasDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/
2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/
2006/xaml"
Title="Grid Demo" Height="640" Width="480">
<Grid Width="Auto" Height="Auto" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Rectangle Fill="Bisque" Grid.Column="0"
Grid.Row="0" />
<Rectangle Fill="DarkMagenta" Grid.Column="1"
Grid.ColumnSpan="2"/>
</Grid>
</Window>
|
|
