Quickstart: Defining layouts (Windows Runtime apps using C#/VB/C++ and XAML)
When you create a Windows Runtime app using C++, C#, or Visual Basic, you have a flexible layout system available that helps you accommodate multiple devices and application states. With a flexible design, you can make your app look great on screens with different app window sizes, resolutions, pixel densities, and orientations. We describe how to design a user interface that automatically adjusts to different sizes.
Roadmap: How does this topic relate to others? See:
- Roadmap for Windows Store apps using C# or Visual Basic
- Roadmap for Windows Store apps using C++
- Windows Store app UI, start to finish, highlighted in our App features, start to finish series
This topic assumes that you can create a basic Windows Runtime app using C++, C#, or Visual Basic. For instructions on creating your first Windows Runtime app, see Creating your first Windows Store app with C# or Visual Basic.
Although this topic introduces you to some basic layouts, there are a number of user interface guidelines you should keep in mind:
- Guidelines for window sizes and scaling to screens
- Guidelines for scaling to pixel density
- Guidelines for resizing windows to tall and narrow layouts
- Guidelines for form layouts
Layout is the process of sizing and positioning objects in your UI. To position visual objects, you must put them in a Panel or other container object. The XAML framework provides various Panel classes, such as Canvas, StackPanel, and Grid, which serve as containers and enable you to position and arrange the UI elements within them.
The XAML layout system supports both fixed layout and dynamic layout. In a fixed layout, elements are sized and positioned using explicit dimensions. For example, you can use a Canvas panel for fixed positioning. And you can set a fixed size on an element no matter what layout panel contains it. In a dynamic layout, the user interface automatically sizes to proportions (in the case of Grid rows and columns) or to the content of panels and controls, or to various screen resolutions. For a dynamic layout, use for example a StackPanel, Grid, or VariableSizedWrapGrid.
In an fixed layout, you arrange child elements in a layout panel by specifying their exact locations and sizes relative to their parent element. Fixed positioning doesn't necessarily consider that the size of the screen or app window will be different on different devices. If the application requires fixed positioning of UI elements while also adjusting for size of the app window, you can design different pages for different screen resolutions or use scaling as an alternative.
All panels in the XAML framework support fixed positioning, but Canvas is an example of a panel that only supports fixed positioning. To position a child element within a Canvas, you set the Canvas.Left and Canvas.Top attached properties on the child element. When you use the XAML designer in Microsoft Visual Studio, these properties are updated when you drag the child element within the Canvas on the design surface.
In a dynamic layout, the user interface adjusts for various screen resolutions and app window sizes. You arrange child elements by specifying how they should be arranged in relationships to each other, and how they should position relative to their content and/or their parent. For example, you can arrange UI elements within a panel and specify that they should wrap horizontally. To use automatic or proportional sizing, you assign values to the Height and Width properties. Here are the recommended settings for a dynamic layout:
- Set the Height and Width of the UI elements to Auto. When these values are used for UI elements in the Grid layout, the Grid panel fills the cell that contains it. Auto sizing is supported for UI elements in general and for the Grid and StackPanel layouts.
- For UI elements that contain text (text elements), leave the Height and Width properties unset, and set the MinWidth or MinHeight properties. This prevents the text from scaling down to a size that's unreadable because the layout container cuts it off.
- To set proportional values for the RowDefinition and ColumnDefinition elements that define the cell structure of a Grid layout, use relative Height and Width values. For example, to specify that one column is 5 times wider than the second column in a 2-column layout, use "*" and "5*" for the Width properties in the ColumnDefinition elements.
Auto sizing is used to allow controls to fit their content, even if the content changes size. Star sizing is used to distribute available space among the rows and columns of a grid by weighted proportions. In XAML, star values are expressed as * (or n* for weighted star sizing). For example, if you have a grid with 4 columns, you could set the widths of the columns to the values shown here:
|Column_1||Auto||The column will size to fit its content.|
|Column_2||*||After the Auto columns are calculated, the column gets part of the remaining width. Column_2 will be one-half as wide as Column_4.|
|Column_3||Auto||The column will size to fit its content.|
|Column_4||2*||After the Auto columns are calculated, the column gets part of the remaining width. Column_4 will be twice as wide as Column_2.|
The built-in layout panels in the XAML include the Canvas panel for fixed layout, and several other panels for various techniques of dynamic layout.
The Canvas panel positions its child elements using fixed coordinate points. You specify the points on individual child elements by setting the Canvas.Left and Canvas.Top attached properties on each element. During layout, the parent Canvas object uses its class logic to read these attached property values from its children and uses these values during the Arrange pass of layout.
<Canvas Background="Black"> <Rectangle Canvas.Left="200" Canvas.Top="100" Fill="Red" Width="350" Height="350" /> </Canvas>
The preceding XAML produces output that is similar to this illustration:
With fixed positioning you can create overlaps of objects, where one object will draw on top of another object. To make it possible to easily adjust the draw order of children and also to enable changing the draw order during run time, Canvas also supports a Canvas.ZIndex. attached property that you can set on each of the child elements. Highest Canvas.ZIndex value draws last and therefore draws over any other elements that share the same space or overlaps in any way. For more info, see Canvas.ZIndex. Note that alpha value (transparency) is respected, so even if elements overlap, the contents shown in overlap areas might be blended if the top one has a nonmaximum alpha value.
Use the Canvas panel with discretion. While it's convenient to be able to precisely control positions of elements in UI for some scenarios, an fixed positioned layout panel causes that area of your UI to be less adaptive to overall app window size changes. App window resize might come from device orientation changes, split app windows, changing monitors, and a number of other user scenarios.
The StackPanel panel is a simple layout panel that arranges its child elements into a single line that can be oriented horizontally or vertically. You can use the Orientation property to specify the direction of the child elements. The default value for Orientation is Vertical. StackPanel controls are typically used in scenarios where you want to arrange a small subsection of the UI on your page.
The following XAML shows how to create a vertical StackPanel of items.
<StackPanel Margin="20"> <Rectangle Fill="Red" Width="100" Height="100" Margin="10" /> <Rectangle Fill="Blue" Width="100" Height="100" Margin="10" /> <Rectangle Fill="Green" Width="100" Height="100" Margin="10" /> <Rectangle Fill="Purple" Width="100" Height="100" Margin="10" /> </StackPanel>
The preceding XAML produces output that is similar to the following illustration.
Nesting panels using more than one StackPanel is a common technique in layout. For example, you can create a sidebar and a main content area with a horizontal StackPanel, and stack items in the main content with a vertical StackPanel. Note that if you do nest panels, attached properties on UI elements that specify layout characteristics to a parent are interpreted by the most immediate parent panel only.
The Grid panel supports arranging controls in multi-row and multi-column layouts. You can specify a Grid panel's row and column definitions by using the RowDefinitions and ColumnDefinitions properties that are declared within the Grid element (uses property element syntax in XAML). You can position objects in specific cells of the Grid by using the Grid.Column and Grid.Row attached properties. You can distribute space within a column or a row by using Auto or star sizing. Content can span across multiple rows and columns by using the Grid.RowSpan and Grid.ColumnSpan attached properties.
The next XAML example shows how to create a Grid with three rows and two columns. The height of the first and third rows is just large enough to contain the text. The height of the second row fills up the rest of the available height. The width of the columns is split equally within the available container width.
<Grid Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBox Text="1st row 1st column" FontSize="60" Grid.Column="0" Grid.Row="0" /> <TextBox Text="3rd row 1st column" FontSize="60" Grid.Column="0" Grid.Row="2" /> <Button Content="1st row 2nd column" FontSize="60" Grid.Column="1" Grid.Row="0" /> <Button Content="3rd row 2nd column" FontSize="60" Grid.Column="1" Grid.Row="2" /> </Grid>
This produces output that is similar to the following illustration.
VariableSizedWrapGrid provides a grid-style layout panel where each tile or cell can be of variable size based on content. In a VariableSizedWrapGrid, elements are arranged in rows or columns that automatically wrap to a new row or column when the MaximumRowsOrColumns value is reached. The Orientation property specifies whether the grid adds its items in rows or columns before wrapping. Cell dimensions are specified with ItemHeight and ItemWidth (values in pixels). Child elements can use the attached properties VariableSizedWrapGrid.ColumnSpan and VariableSizedWrapGrid.RowSpan (values as cell counts) to adjust how many of the variable cells the child element should use (the default is 1). For more info, see VariableSizedWrapGrid.
WrapGrid and VirtualizingStackPanel are special-purpose panels that can only be used to display items in an ItemsControl. For more info, see WrapGrid. ItemsStackPanel and ItemsWrapGrid are similar panels with restrictions on where it can be used (an ItemsControl with multiple items).
Migration notes: Windows Presentation Foundation (WPF) has a VirtualizingStackPanel class that can be used as a general-purpose panel with no restrictions on where it can exist. If you are migrating XAML that used VirtualizingStackPanel you'll have to change your items data control to be a ListView, then you'll get item virtualization within your list due to the contained VirtualizingStackPanel in the default template.
- Roadmap for creating apps using C#, C++, or VB
- Quickstart: Adding layout controls
- Adding ListView, SemanticZoom, and other data controls