This article has a corresponding video that can be viewed here.
The WPF and Silverlight platforms have a wide selection of powerful layout controls.
This topic will provide you with an understanding of these layout controls and how to take advantage of the WPF and Silverlight Designer features when working with these controls.
In this topic when the term pixel is used, it refers to a device-independent-pixel. In WPF a pixel is 1/96 of an inch. This MSDN topic covers device-independent-pixels. http://msdn.microsoft.com/en-us/library/bb847924.aspx
WPF layout controls can be logically grouped by base types that determine their behavior.
The Grid control provides a flexible grid area that consists of rows and columns. Flexible row and column sizing options enable the grid to predictably size and resize itself at design time or runtime as its parent control is resized.
Figure 1 Grid Layout
Rows are added to the grid by adding a RowDefinition to the RowDefinitions collection. The grid in Figure 1 above has three rows defined.
Columns are added to the grid by adding a ColumnDefinition to the ColumnDefinitions collection. The grid in Figure 1 has two columns defined.
The Grid row Height and Grid column Width properties are of type GridLength. The GridLength allows for flexible property value assignment.
Figure 2 Auto Sized Column Handle
The numeric values displayed in the Grid control's rail is the actual design time size in pixels of the row or column. This is true for both Fixed size and Star sized rows or columns.
If the Auto Sized Grid is hosted in a Window, the indicated values for height and width may be different at runtime based on the Window chrome.
The Grid control lays out controls based on several attached properties.
See MSDN documentation on Attached Properties here: http://msdn.microsoft.com/en-us/library/ms749011.aspx
Figure 3 Grid Attached Properties
In Figure 3 above the Grid has three rows and two columns defined. The child controls as laid out according to the attached properties.
The WPF Designer operates on rows and columns in a similar manner. Examples and text will not be repeated for row and columns. Where designer behavior differs between rows and columns that information will be provided.
Figure 4 Add Grid Row
The WPF Designer provides two techniques for resizing a row or column.
Figure 5 Maintain Control Size Resize
Dragging the row handle (triangle) enables row resizing without changing the Button size.
Figure 6 Maintain Control Margin Resize
Dragging the row grid line maintains the Button's margins which results in the Button resizing.
Figure 7 Dropping Grid Line on Fixed Sized Control
Figure 7 above displays the results of resizing a column and dropping the grid line on top of a Fixed sized control (control aligned Top & Left). Dragging the column handle resulted in the Button control maintaining its size. This was accomplished by spanning the Button across two columns.
Figure 8 Dropping Grid Line on Fixed Sized Control
Figure 8 above displays the results of resizing a column and dropping the grid line on top of a Fixed sized control (control aligned Top & Left). Dragging the column line resulted in the Button control being clipped since size was not being maintained. To maintain sizes, use the column handle instead of the column row when resizing as in Figure 7 above.
Figure 9 Deleting Grid Row
To delete a row or column drag the row or column header away from the grid and release the left mouse button. Notice the delete row drag icon in Figure 9 above in the center grid.
The right grid in Figure 9 shows the results of deleting the second row. The grid now has two rows and the Button control that was in Grid.Row 1 is now in Grid.Row 0.
In a row or column delete operation, the WPF Designer will renumber all affected control's Grid.Row or Grid.Column attached properties. Margins will be adjusted to maintain control positioning unless the control alignment is centered, in that case the control will remain centered.
Rows and columns can be added and removed from a Grid by editing the RowDefinitions or ColumnDefinitions collections using the Properties Window.
Figure 10 Properties Window
With the Grid control selected, using the Properties Window search box, enter "def" and the RowDefinitions and ColumnDefinitions collections will be visible.
Clicking on the ellipsis button will open a collection editor for adding, removing or reordering row or column definitions. Figure 11 below shows the ColumnDefinitions collection editor.
Figure 11 ColumnDefinitions Collection Editor
The ColumnDefinitions collection editor allows editing each of the ColumnDefinition properties. In addition to the Width property which is currently set to 68*, the MinWidth and MaxWidth properties are sometimes used by developers to provide a size range for the column by restricting the column's minimum and/or maximum width.
A ColumnDefinition can be added or removed from the ColumnDefinitions collection using the Add or Delete button.
When using the Collection Editor and a ColumnDefinition is deleted, the Grid.Column attached property value is not adjusted like it is when using the WPF Designer.
ColumnDefinitions can be reordered using the up or down arrows.
When using the Collection Editor and ColumnDefinitions are reordered, only the ColumnDefinitions are reordered. The Grid.Column attached property value is not changed for any control.
RowDefinitions have a collection editor similar to the ColumnDefinition editor.
The WPF Designer provides visual clues when creating child controls by dragging and dropping from the ToolBox. These same visual clues are displayed when performing a drag move operation on the design surface.
Figure 12 Drag Drop from the ToolBox
All WPF controls that allow the dropping of child controls will display a blue border around themselves when a control is being dragged over them. This blue border indicates that this control will be the parent of the control being dragged if it's dropped. Additionally the target control is colored white and other areas on the design surface outside the control are shaded.
The Grid has an enhanced drag over behavior. The cell that the mouse is over will be white and the rest of the design surface will be shaded as in Figure 12 above.
If the control being dragged would span multiple rows or columns, the additional rows or columns will also be white and not shaded.
The Grid control has a unique feature that allows either rows or columns to be automatically sized to the largest row or column in their SharedSizeGroup. The SharedSizeGroup scope is determined by the attached property Grid.IsSharedSizeScope.
Figure 13 Grid.IsSharedSizeScope
In Figure 13 above the three ColumnDefinitions are participants of the SharedSizeGroup "buttons." The scope of their size sharing is the immediate parent Grid control. The parent Grid control has the attached property Grid.IsSharedSizeScope set to True. This establishes this Grid control as a shared size scope.
Each of the columns will automatically size to the largest column width in the SharedSizeGroup. In Figure 13 the Button "Long Button Name" is the widest Button control. Since the other two Button controls are using auto sizing, they will grow as their column resizes to match the widest column in the SharedSizeGroup.
Figure 14 Multiple Grids Sharing the Same Shared Size Scope
Figure 14 above shows multiple Grid Controls sharing the same shared size scope. This is accomplished by nesting Grid Controls.
The outer Grid has the Grid.IsSharedSizeScope attached property set to True.
The nested child Grid rows or columns can now participate in the same SharedSizeGroup.
In Figure 14 the two Grid control's columns will all be the size of the widest column in the SharedSizeGroup "buttons."
The GridSplitter control provides runtime resizing of the Grid control's rows or columns.
Figure 15 GridSplitter
In Figure 15 the GridSplitter is located in Grid.Column zero and aligned to the right of the column. The GridSplitter control can also be placed in its own row or column.
After adding the GridSplitter control to the Grid, use the Properties Window or the XAML editor to set the required properties on it.
At runtime the user will be able to resize the columns by dragging the GridSplitter left or right.
The StackPanel arranges child elements into a single line that can be oriented horizontally or vertically.
Figure 16 StackPanel with Vertical Orientation
Figure 16 above shows the default orientation of the StackPanel, vertical.
Figure 17 StackPanel with Horizontal Orientation
Figure 17 above shows the StackPanel with its Orientation property set to Horizontal.
Figure 18 StackPanel Child Control Reordering
The StackPanel control has a design time experience that displays a position line when dragging controls into the StackPanel or when dragging controls to reorder them.
In Figure 18 above Button B is being dragged below Button C. The three above image display before, during and after the drag operation.
Notice the blue border and white drop surface applied to the drop target StackPanel and the shading outside the StackPanel control.
The Canvas defines an area which you can explicitly position child elements by using coordinates that are relative to the Canvas area.
Figure 19 Canvas
When controls are placed on a Canvas, the Margin, Vertical and Horizontal alignment properties do not play a part in the control's layout. Instead the Canvas uses the attached properties Canvas.Left and Canvas.Top determine child control positioning. In Figure 19 the Canvas.Left and Canvas.Top attached properties are highlighted.
The DockPanel defines an area where you can arrange child elements either horizontally or vertically, relative to each other.
Figure 20 DockPanel
Except for adding controls to the DockPanel, the WPF Designer does not provide additional design time help. After adding controls to the DockPanel, use the Properties Window or the XAML editor to set the properties on the child controls.
The location of the DockPanel child controls is determined by the attached property DockPanel.Dock. Controls can by docked, left, top, right or bottom.
By default the DockPanel will allocate all remaining space to the last child added to it. In Figure 20 above you can see how the last Button control has consumed the remaining space of the DockPanel.
The secret to using the DockPanel is to add the outer controls to the DockPanel first. Note the order the controls are added in the XAML. The last control you add should be the control that will consume the remaining space.
The WrapPanel positions child elements in sequential position from left to right, breaking content to the next line at the edge of the containing box. Subsequent ordering happens sequentially from top to bottom or from right to left, depending on the value of the Orientation property.
Figure 21 WrapPanel
Except for adding controls to the WrapPanel, the WPF Designer does not provide additional design time help.
When the WrapPanel is resized at runtime, it will automatically lay its child controls out again.
Child controls can be laid out horizontally or vertically by setting the Orientation property.
A real world example of using the WrapPanel would be the Windows Control Panel. With each icon and text being wrapped in its own panel, those panels would be added to the WrapPanel to provide flexible layout repositioning at runtime as the Control Panel is resized.
The UniformGrid provides a way to arrange content in a grid where all the cells in the grid have the same size.
Figure 22 UniformGrid
Except for adding controls to the UniformGrid, the WPF Designer does not provide additional design time help.
Each of the controls in Figure 22 above has the same space allocated to them.
The UniformGrid provides properties for setting the desired number of row and columns if the default layout does not suit your application's needs.
Before looking at some additional layout panels, let's cover a layout attached property that is exposed by the Panel class that all panels derive from.
The Canvas is a panel so this attached property applies to the Canvas as well as other panels.
The Panel.ZIndex attached property is used by all panel controls to determine the stacking order of controls laid on top of one another.
Figure 23 Control Stacking Order
The Panel.ZIndex property can be set on child controls of all panels. This example is showing the Panel.ZIndex attached property being used with the Canvas.
Normally the control stacking order is determined by the order that the controls are added to the layout.
In Figure 23 above buttons A, B and C were added in the order they appear in the XAML.
However Button B is rendered on top of Button C. This is because the Panel.ZIndex attached property for Button C has been set to a lower value than the Panel.ZIndex attached property for Button B.
The default value of the Panel.ZIndex attached property is zero. You can assign positive or negative values to this attached property to get the stacking order your application requires.
The Border control draws a border, background, or both around another element.
Figure 24 Border
Except for adding a single child control to the Border, the WPF Designer does not provide additional design time help.
In Figure 24 above, the StackPanel is the single child control of the Border.
The Window control provides the ability to create, configure, show, and manage the lifetime of windows and dialog boxes.
Figure 25 Window
Except for adding a single child control to the Window and the size mode button, the WPF Designer does not provide additional design time help.
WPF applications each have one or more windows. Since a Window control can only contain a single control, the content of a Window control is normally a layout panel to enable the layout of many additional controls.
The size mode button was covered in the Setting Up Visual Studio for WPF and Silverlight Development article.
The UserControl provides a simple way to create a control or extract out a set of controls for reuse.
Figure 26 UserControl
Except for adding a single child control to the UserControl and the size mode button, the WPF Designer does not provide additional design time help.
Since a UserControl can only contain a single control, the content of a UserControl is normally a layout panel to enable the layout of many additional controls.
The UserControl size mode defaults to Auto size.
The GroupBox is a control that creates a container that has a border and header for its single content object.
Figure 27 GroupBox
Except for adding a single child control to the GroupBox, the WPF Designer does not provide additional design time help.
In Figure 27 above, the StackPanel is the single child control of the GroupBox.
When dragging a GroupBox from the ToolBox, the default child control for the GroupBox is a Grid. In Figure 27, the Grid has been replaced with a StackPanel.
The Expander control displays a header that has a collapsible window that displays content.
Figure 28 Expander Control Expanded
At design time, when the Expander control is selected it will expand. This provides access to its single child control. The child control is typically a panel. The default panel is the Grid control. In Figure 28 above the Grid was replaced with a StackPanel.
The Header property typically provides text at the top of the Expander. However, the Header property is not limited to just text as it's of type Object. The Header can contain any single WPF control. An example of a non-standard Header could be a StackPanel that contains an Image control and a TextBlock control.
Figure 29 Expander Control Collapsed
Selecting another control outside the Expander will cause the Expander to collapse as pictured in Figure 29 above.
The TabItem control represents a selectable item inside a TabControl.
Figure 30 TabItem
The TabControl contains one or more TabItem controls that the user can select at runtime. The TabItem control typically contains a single panel child control that is used to layout additional controls.
The default panel for the TabItem when added from the TabControl Context Menu is the Grid control as pictured in the XAML in Figure 30 above.
WPF: At design time in you can select the TabItem you need to layout by clicking on its Header.
The Header property typically provides text for the TabItem Header. However, the Header property is not limited to just text as it's of type Object. The Header can contain any single WPF control. An example of a non-standard Header could be a StackPanel that contains an Image control and a TextBlock control.
The TabControl is a control that contains multiple items that share the same space on the screen and is pictured in Figure 30 above.
The TabControl TabStripPlacement property determines the location of the TabItem Headers. The default value is Top. Other possible locations are Left, Right and Bottom.
Figure 31 Adding TabItem using TabControl Context Menu
At design time additional TabItem controls can be added to the TabControl by selecting the TabControl, right clicking to bring up the Context Menu and selecting Add Tab as pictured in Figure 31 above. In Figure 31 the mouse was right clicked when the mouse cursor was in the white space to the right of TabItem2's Header.
Figure 32 Adding TabItem using Properties Window
At design time additional TabItem controls can also be added, removed and reordered by using the TabControl Items property Collection Editor as in Figure 32 above.
The following section briefly covers common properties that affect layout.
The Margin property is of type Thickness and provides spacing from the control's outer edge to other controls around it.
Figure 33 Visibility
In Figure 33 above the left Widow shows the design time rendering of controls on the design surface. Regardless of the Visibility property, all controls are rendered on the design surface.
In Figure 33 above the right Window shows the runtime rendering of controls with the different Visibility property values set.
The ClipToBounds property indicates whether to clip the content of this control (or content coming from the child elements of this control) to fit into the size of the containing element.
Figure 34 ClipToBounds
In Figure 34 above the top TextBox extends past the boundary of its parent Canvas control.
In Figure 34 above the bottom Canvas has its ClipToBounds property set to True. This results in the bottom TextBox being clipped at the boundary of its parent Canvas control.
Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:
Thank you for your feedback and have a great day,
Karl Shifflett Visual Studio Cider Team
Excellent reference. I learned a load by reading this and will be coming back often when a question comes up.
Ahh but you forgot one very useful and often neglected layout control - InkCanvas. Aside from collecting ink (yeah, remember us Tablet PC supporters?) it also works great as a poor man's designer surface because you can set its editing mode to Select and resize/move/delete controls at runtime with zero code.
Nice run-time idea for sure. Thank you for the great tip.
Have a super day,
Lovely piece of code!
Really nice article...got very very good understanding about WPF
Thanks a lot.
Thank you for your kind words on the article. WPF is a wonderful framework for developing Windows applications.
Is there any way to control the "position" of the Gridsplitter from code behind, og preferrably XAML for MVVM Property Binding?
Very nice explanations! Well done.
hoping that the video have chinese translation.
those video are very good.