Part 3: Navigation, layout, and views
[ This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation ]
The UI design for your Windows Store app is about organizing and presenting content to your users, and providing commands that enable your users to act on the content. UI design includes the organization of pages in the app, the navigation between pages, and the layout of content and commands on each page.
There are various navigation patterns that can be used in a Windows Store app. Navigation patterns will help you choose the best navigation pattern for your app.
Note
See the two primary navigation patterns (Flat navigation and Hierarchical navigation) in action as part of our App features, start to finish series.
Important This tutorial is intended for use with Microsoft Visual Studio 2013 and Windows 8.1. Parts of it will not work correctly with Microsoft Visual Studio 2012 and Windows 8.
In this tutorial, you learn how to:
- Add pages and navigation
- Arrange controls and content on a page
- Adapt the page layout to different orientations and views
Before you start...
- This is the third tutorial in a series. Before you start this tutorial, read Part 1: Create a "Hello, world!" app and Part 2: Manage app lifecycle and state.
- You can see the complete code for this tutorial in Part 3 complete code.
Step 1: Add pages and navigation
In this tutorial, we go over the basics of creating a user interface in Extensible Application Markup Language (XAML). To learn these basics, you create a simple photo viewer that lets the user pick an image from their Pictures, and then it shows the image and some info about the image file. For the photo viewer, you add a new page to the "Hello, world" app from Part 2. To use the new page, you add commands to navigate between the pages.
The first thing you need to do is add a new page to your app for the photo viewer. Then you add a navigation command to the main page so that the user can navigate to the new page.
Add the photo viewer page
We start here with the code from Part 2: Manage app lifecycle and state.
To add a page to an app
Select Project > Add New Item. The Add New Item dialog box opens.
Tip Make sure the project, and not the solution, is selected in Solution Explorer.
Under Visual C# or Visual Basic in the left pane, pick the Windows Store template type.
In the center pane, pick Basic Page.
Enter "PhotoPage.xaml" as the name for the page.
Click Add. The XAML and code behind files for your page are added to the project.
Here's the Add New Item dialog.
(The first time you add a new page to the Blank App template (other than a Blank Page), Microsoft Visual Studio shows a dialog with a message that you need to add files that are missing from your project. You added these files in Part 1, so you should not see this warning. If you do, click Yes to add these files. Files for several utility classes are added to your project in the Common folder.)
To change the page title, select the "My Application" text near the top of PhotoPage.xaml.
Make sure the TextBlock named
pageTitle
is showing in the Properties panel and the Properties view () is selected.Under Common in the Properties panel, click the property marker for the Text property. The property menu opens.
Note The property marker is the small box symbol to the right of each property value. The Text property marker is green to indicate that it's set to a resource.
In the property menu, select Edit Resource. The Edit Resource dialog opens.
In the Edit Resource dialog, change the value from "My Application" to "Hello, photo!".
Click OK.
The XAML for the resource definition is updated like this.
<x:String x:Key="AppName">Hello, photo!</x:String>
Add navigation
The XAML UI framework provides a built-in navigation model that uses Frames and Pages and works much like the navigation in a web browser. The Frame control hosts Pages, and has a navigation history that you can use to go forward and back through pages you've visited. You can also pass data between pages as you navigate.
In Part 1 and Part 2, you saw the code in App.xaml.cs/.vb that creates a Frame and navigates to MainPage
when the app is started. Here, you add a command to MainPage
to navigate to the new PhotoPage
in the same way.
To navigate between pages
In Solution Explorer, double-click MainPage.xaml to open it.
In the XAML editor, find the StackPanel that contains the
greetingOutput
TextBlock. Immediately after thegreetingOutput
TextBlock, add a Button element, like this:<Button Content="Go to photo page"/>
Here's the button you added with the surrounding XAML.
<StackPanel Grid.Row="1" Margin="120,30,0,0"> <TextBlock Text="What's your name?" Style="{ThemeResource BaseTextBlockStyle}"/> <StackPanel Orientation="Horizontal" Margin="0,20,0,20"> <TextBox x:Name="nameInput" Width="300" HorizontalAlignment="Left" TextChanged="NameInput_TextChanged"/> <Button Content="Say "Hello"" Click="Button_Click"/> </StackPanel> <TextBlock x:Name="greetingOutput" Style="{StaticResource BigGreenTextStyle}"/> <Button Content="Go to photo page"/> </StackPanel>
In the XAML editor or design view, select the "Go to photo page" Button that you added to MainPage.xaml.
In the Properties panel, click the Events button ().
Find the Click event at the top of the event list. In the text box for the event, type "PhotoPageButton_Click" as the name of the function that handles the Click event.
Press Enter. The event handler method is created and opened in the code editor so you can add code that's executed when the event occurs.
Add this code to the event handler that you created in the code behind page. In the event handler, navigate to the new photo page that you added to the app.
// Add this code. if (this.Frame != null) { this.Frame.Navigate(typeof(PhotoPage)); }
' Add this code. If Me.Frame IsNot Nothing Then Me.Frame.Navigate(GetType(PhotoPage)) End If
This call to Navigate causes a new
PhotoPage
to be instantiated. To preserve the state of the photo page, you can enable the navigation cache so the page isn't recreated each time a user navigates.Switch back to PhotoPage.xaml. In the XAML editor or design view, select the root Page element.
In the Properties panel, click the Properties button ().
Under Common in the Properties panel, click the down arrow to show advanced properties, and change the NavigationCacheMode value to Enabled.
Press F5 to build and run the app. Click the Go to photo page button. The photo page opens. Click the back button to navigate back to the main page.
You don't need to add a back button to the photo page. The photo page is based on the Basic Page template, which has built-in support for navigation. The back button uses the Frame history to go back to the previous page, and is shown only when the Frame.CanGoBack property is true.
Step 2: Add controls and content to a page
Now you add content to the photo page. Before you start working on the layout of the photo page, it's helpful to understand the fundamentals of layout using XAML.
About creating a UI with XAML
The XAML layout system supports both static and fluid layouts.
In a static layout, you give controls explicit pixel sizes and positions. When the user changes the resolution or orientation of their device, the UI doesn't change. Static layouts can become stretched, shrunk, or clipped across different form factors and display sizes.
Fluid layouts shrink, grow, and reflow to adapt to the visual space available on a device. In a fluid layout, the layout containers and the controls are automatically sized and repositioned as the app resizes. In a Windows Store app, you still use static elements and values in some places, but make sure that the overall UI is fluid and adapts to different resolutions, layouts, and views.
Most app content can be organized into some form of groupings or hierarchies. You use layout containers to group and arrange UI elements. The XAML layout system provides various Panel controls, such as Grid, StackPanel, and Canvas, that serve as containers in which you arrange your content. Most containers do some automatic sizing of their child elements if the elements don't have an explicit size set.
You use a Grid to arrange content in rows and columns. You position elements using the Grid.Row and Grid.Columnattached properties. You can make elements span multiple rows and columns by using the Grid.RowSpan and Grid.ColumnSpan attached properties.
You use a StackPanel to arrange content in single line. You can set the Orientation property to stack items either vertically or horizontally.
You use a Canvas when you want to control all aspects of positioning and sizing of content. In a Canvas, you position elements absolutely using Canvas.Top and Canvas.Left attached properties. A canvas doesn't do any sizing of child elements, so you have to size them explicitly.
To control the size and position of an element, you set its layout properties. Here are some common layout properties and their effect.
- HorizontalAlignment and VerticalAlignment: Specifies what position an object takes in relation to its parent object.
- Margin: Specifies the amount of empty space around the control, between the outside of the child object and the boundaries of the panel.
- Width and Height: Specifies fixed values measured in pixels.
- MinWidth/MaxWidth and MinHeight/MaxHeight: Specifies values that constrain the size of an element while allowing fluid resizing.
You use these containers and layout properties to create a fluid layout for the photo viewer page.
XAML layout tools
In Part 1, you added controls to the main page by entering XAML directly into the XAML editor. But Visual Studio also includes a visual XAML designer that you can use to add and arrange controls. For the rest of this tutorial, you use the XAML designer to create the UI. Before we start, let's take a look at the parts of Visual Studio UI that you use, and how to complete some common tasks.
Here are the main parts of Visual Studio that you use:
Panel | Image | Description |
---|---|---|
Solution Explorer | Use to manage files in your project.
|
|
Properties | Use to view and edit properties of the selected item.
|
|
XAML Designer | Use to add and arrange elements of the app UI.
|
|
XAML editor | Use to directly edit XAML. | |
Toolbox | Use to add controls and other items to your app UI.
|
|
Device | Use to simulate different settings of a physical device in the designer.
|
|
Document Outline | Use to select and arrange UI elements in a hierarchical view.
|
We assume that you're using the default window layout in Visual Studio. If you change the default layout, you can reset it in the Window menu by picking the Reset Window Layout command.
There are some common tasks that you repeat often while creating a UI. Knowing how to complete these tasks before we start will make creating the UI easier.
To open a file
|
By default, the Toolbox, Device, and Document Outline panels are collapsed to the left of the designer. To open the Toolbox, Device, or Document Outline panels
|
Here are various ways you can select an item and make it active. In some situations, one way might be easier than others. In that case, we will suggest the easiest way to select the item. To select an item
|
The Properties panel has views for managing both properties and events. To switch the Properties panel between Properties and Events views
|
To reference an element in your code, you must give it a name. To name a UI element
|
When you add an element in the designer, the designer sets layout properties to absolutely position and size the element. These properties typically need to be reset to create a fluid layout. To reset a property
|
To change the alignment of an element
|
To change the margins of an element
|
Add navigation commands
In Step 1, you added a Button to navigate from the main page to the new photo page. For convenience, you put the button on the canvas of the main page. But the navigation command is not related to anything else on the main page, and the button seems out of place. When designing your Windows Store app, it's important to consider the placement of commands.
Windows Store apps provide app bars for grouping commands that are hidden by default. The user can show the commands when needed by swiping from the top or bottom edge of the screen, or by right-clicking. The app bar at the top of the screen is typically used for navigation, so you add a top app bar and move the navigation button to it.
To add a top app bar
In Solution Explorer, double-click MainPage.xaml to open it.
In the Document Outline, expand the "pageRoot" element and right-click TopAppBar.
In the context menu, pick Add CommandBar. A CommandBar element is added to the page.
You can add either an AppBar or a CommandBar to a page. AppBar is more customizable, but requires you to handle more of the layout yourself. CommandBar is less customizable, but handles layout for you. Unless you need the flexibility of AppBar, we recommend using a CommandBar.
A CommandBar can only contain AppBarButton, AppBarToggleButton, and AppBarSeparator elements. To replace the navigation button you added earlier, add an AppBarButton to the CommandBar.
Add an app bar button
In the Document Outline, expand the CommandBar element and right-click PrimaryCommands.
In the context menu, pick Add AppBarButton. An AppBarButton is added to the CommandBar and selected.
Under Icon in the Properties panel, pick "Pictures" from the Symbol drop down.
Under Common in the Properties panel, change the Label value from "AppBarButton" to "Pictures".
In the Properties panel, click the Events button ().
Find the Click event at the top of the event list. In the text box for the event, type
PhotoPageButton_Click
. You use the same event handler that you created for the navigation button you added earlier.Here's the final XAML for the app bar.
<Page.TopAppBar> <CommandBar> <AppBarButton Label="Pictures" Icon="Pictures" Click="PhotoPageButton_Click"/> </CommandBar> </Page.TopAppBar>
Select the "Go to photo page" button, and press Delete. You have the app bar button for navigation now, so you don't need this button.
Press F5 to build and run the app. To open the app bar, swipe from the top or bottom edge of the screen, or right-click the app.
You used the app bar to clean up the layout of the main page. Now we turn our attention the new photo viewer page.
Add a layout grid
You start by adding a Grid to divide the content area of the page into 3 rows. The first 2 rows are fixed height, and the last row fills the remaining available space.
To add a Grid panel to a page
Open PhotoPage.xaml.
Drag a Grid from the Toolbox and drop it onto the design surface in the middle of the page.
The Grid is added to the page, and the designer sets some properties based on its best guess at the layout you want. A blue highlight appears around the Grid to indicate that it is now the active object.
In the Properties panel, enter "contentGrid" as the name of the Grid.
Reset these Grid properties: Width, Height, HorizontalAlignment, VerticalAlignment, and Margin. The Grid now completely fills the content area of the page.
Under Layout, set the left Margin and bottom Margin to "120".
In the designer, dotted lines called grid rails appear along the top and left sides of the Grid. Move your cursor over the left side grid rail. The pointer changes to an arrow with a plus (+) sign, and an orange line shows where a row will be added.
Click anywhere on the left grid rail to add a row.
Repeat the previous step to add another row to the Grid.
There are now 3 rows in the Grid. When your cursor is over the grid rail, a small flyout appears that you can use to select the sizing options and adjust the row Height property.
Place your cursor over the grid rail in the first row until the flyout appears.
Click the down arrow to open the flyout menu. Select Pixel in the menu.
Place your cursor over the grid rail again until the flyout appears. In the flyout, click the number value.
Type "50" and press Enter to set the Height property to 50 pixels.
Repeat the process in steps 9-12 to set the second row Height to 70 pixels.
The last row is set to the default value of "1*" (1 star), which means it will use any remaining space.
Now, let's look at the XAML that's produced by this.
<Grid x:Name="contentGrid" Grid.Row="1" Margin="120,0,0,120">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="70"/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
To define rows in a Grid, you add RowDefinition objects to the Grid.RowDefinitions collection. You can set properties on the RowDefinition to specify what the row will look like. You add columns in the same way, using ColumnDefinition objects and the Grid.ColumnDefinitions collection.
Notice this setting in the opening Grid tag: Grid.Row="1"
. You position elements in a Grid using the Grid.Row and Grid.Column attached properties. The row and column numbering is zero-based, so this setting indicates that the "contentGrid" panel is added to the second row of it's parent Grid. This property is set by Visual Studio, based on where you drop the Grid when you add it.
Add controls to photo page
Now you add controls to the Grid. You add a Button to get a picture from Pictures, an Image control to show the picture, and some TextBlock controls to show information about the picture file. You use StackPanels in the last grid row to arrange the Image and TextBlock controls.
To add controls to the page
Add the "Get photo" button
- In the Document Outline, select the "contentGrid" panel.
- With the "contentGrid" panel selected, drag a Button control from the Toolbox and drop it in the first grid row.
- In the Properties panel, reset these Button properties: HorizontalAlignment, VerticalAlignment, and Margin.
- Set the button's Content property to "Get photo".
Add the image name TextBlock
- With the "contentGrid" panel selected, drag a TextBlock control from the Toolbox and drop it in the second grid row.
- In the Properties panel, reset these TextBlock properties: HorizontalAlignment, VerticalAlignment, and Margin.
- Expand the Miscellaneous group and find the Style property.
- In the Style property menu, select System Resource > SubheaderTextBlockStyle.
Add the Image
With the "contentGrid" panel selected, drag a StackPanel from the Toolbox and drop it on the last grid row.
Reset these StackPanel properties: Width, Height, HorizontalAlignment, VerticalAlignment, and Margin.
In the Properties panel, set the StackPanel's Orientation property to Horizontal.
In the Name text box for the StackPanel, type "imagePanel", then press Enter.
With the StackPanel selected, drag a Border control from the Toolbox and drop it in the StackPanel.
Under Brush in the Properties panel, select Background.
Pick the solid color brush tab, then set the color value to "#FF808080".
Repeat steps f-g for the BorderBrush property.
Drag an Image control from the Toolbox and drop it in the Border.
In the Name text box for the Image, type "displayImage", then press Enter.
In the drop-down list for the ImageSource property, select "Logo.png".
In the Document Outline, select the Border that contains the Image.
Add the image info
Drag a TextBlock control from the Toolbox and drop it in the "imagePanel" StackPanel, to the right of the Image control.
Here, you don't need to reset any layout properties, unlike when you dropped the TextBlock in the Grid. The StackPanel and Grid handle the sizing of their child elements differently. For more info, see Quickstart: Adding layout controls.
Drag 5 more TextBlock controls into the StackPanel.
There are now 6 TextBlock controls lined up horizontally to the right of the Image control.
Select the first TextBlock and set its Text property to "File name:".
Select the third TextBlock and set its Text property to "Path:".
Select the fifth TextBlock and set its Text property to "Date created:".
The photo viewer UI looks like this now. The layout is nearly complete, but you still need to fix the appearance of the TextBlocks that show the picture info.
Here's the XAML that's generated for this layout.
<Grid x:Name="contentGrid" Grid.Row="1" Margin="120,0,0,120">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="70"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Content="Get photo"/>
<TextBlock Grid.Row="1" TextWrapping="Wrap" Text="TextBlock"
Style="{StaticResource PageSubheaderTextStyle}"/>
<StackPanel x:Name="imagePanel" Grid.Row="2" Orientation="Horizontal">
<Border BorderBrush="Gray" BorderThickness="7" Background="Gray">
<Image x:Name="displayImage" Source="Assets/Logo.png"/>
</Border>
<TextBlock TextWrapping="Wrap" Text="File name:"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"/>
<TextBlock TextWrapping="Wrap" Text="Path:"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"/>
<TextBlock TextWrapping="Wrap" Text="Date created:"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"/>
</StackPanel>
</Grid>
You need to fix the layout and formatting of the TextBlocks you added. To give the picture info text the layout you want, you group the controls into a vertical StackPanel.
To group items into a StackPanel
In the Document Outline, click the first TextBlock in the "imagePanel" StackPanel.
Press Shift, then click the last TextBlock in the group. The 6 TextBlock controls are now selected.
Right-click the group of selected TextBlock controls. In the context menu, select Group Into > StackPanel.
A StackPanel is added to the page, and the 6 TextBlock controls are put inside the StackPanel.
Under Layout in the Properties panel, set the StackPanel's Orientation property to Vertical.
Set the StackPanel left Margin to "20".
The last thing to do is to format the picture info text. You use built-in styles for the text, and set some margins to create space between the elements.
To style the text
- In the Document Outline, click the first TextBlock in the "imagePanel" StackPanel.
- Press Ctrl, then click the third and fifth TextBlock in the group. Three TextBlock controls are now selected.
- Under Miscellaneous in the Properties panel, find the Style property.
- In the Style property menu, select System Resource > CaptionTextBlockStyle.
- Select the second, fourth, and sixth TextBlock controls in the group.
- Set the Style property to System Resource > BodyTextBlockStyle.
- Set the left Margin property value to 10, and the bottom value to 30.
The XAML for the picture info text now looks like this.
<StackPanel Margin="20,0,0,0">
<TextBlock TextWrapping="Wrap" Text="File name:"
Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0,0,30"/>
<TextBlock TextWrapping="Wrap" Text="Path:"
Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0,0,30"/>
<TextBlock TextWrapping="Wrap" Text="Date created:"
Style="{ThemeResource CaptionTextBlockStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{ThemeResource BodyTextBlockStyle}" Margin="10,0,0,30"/>
</StackPanel>
Press F5 to build and run the app. Navigate to the photo page. It now looks like this.
Step 3: Adapt the page layout to different orientations and views
So far, you've designed the app to be viewed full screen in the landscape orientation. But a new Windows UI must adapt to different orientations and layouts. Specifically, it must support both landscape and portrait orientations. Here, we see how you can make your app look good in any resolution or orientation.
Use different views in Visual Studio
To see what the app looks like in different views, you can use the Device panel in Visual Studio 2013. (The Device panel is available only when a XAML page is active.) This lets you simulate various views, displays, and display options for your app in the Visual Studio designer. Here, you see how to use the Orientation options, but you need to also use the Display options to see how the UI looks at different screen resolutions. A fluid layout adapts to look good on different screens.
Let’s try the portrait orientation to see how the app looks.
To use different views in Visual Studio
In the Device panel, click the portrait () button. The designer changes to simulate the portrait view.
This is what the app looks like when the user rotates it to portrait orientation. This view is too narrow. You need to make some adjustments to the width of the app UI.
Click the Landscape button to switch back to the default view.
Adjust the portrait view
Now, let's fix the portrait view.
When you change the StackPanel from Horizontal to Vertical, the Border and Image resize automatically. This is an example of fluid layout. The StackPanel lets its child elements stretch in the direction that it's oriented, and constrains them in the opposing orientation. Instead of setting the image to a fixed size, you let the layout panel arrange and size its child elements.
To adjust the portrait view
In the XAML editor, add this block of XAML after the
contentGrid
Grid element.<VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="DefaultLayout"> <Storyboard> </Storyboard> </VisualState> <VisualState x:Name="Portrait"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(StackPanel.Orientation)" Storyboard.TargetName="imagePanel"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Orientation>Vertical</Orientation> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="imagePanel"> <DiscreteObjectKeyFrame KeyTime="0"> <DiscreteObjectKeyFrame.Value> <Thickness>0,0,20,0</Thickness> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
In the Document Outline, select the "pageRoot" element.
In the Properties panel, click the Events button ().
Find the SizeChanged event in the event list. In the text box for the event, type "PhotoPage_SizeChanged" as the name of the function that handles the SizeChanged event.
Press Enter. The event handler method is created and opened in the code editor so you can add code that's executed when the event occurs.
Add this code to the event handler.
if (e.NewSize.Height/e.NewSize.Width >= 1) { VisualStateManager.GoToState(this, "Portrait", true); } else { VisualStateManager.GoToState(this, "DefaultLayout", true); }
If e.NewSize.Height / e.NewSize.Width >= 1 Then VisualStateManager.GoToState(Me, "PortraitLayout", True) Else VisualStateManager.GoToState(Me, "DefaultLayout", True) End If
To test the app in different orientations, views, and resolutions, you can use the simulator in Visual Studio. To run your Windows Store app in the simulator, select Simulator from the drop-down list next to the Start Debugging button on the Standard toolbar. For more information about testing the app in the simulator, see Running Windows Store apps from Visual Studio.
The app now looks like this in when you run it in the simulator in portrait orientation.
Summary
Congratulations, you're done with the third tutorial! You learned how to save app data and session state in a Windows Store app.
See the code
Did you get stuck, or do you want to check your work? If so, see Part 3 complete code.
Next steps
In the next part of this tutorial series, you learn how to access and work with files. Go to Part 4: File access and pickers.
Related topics
For designers
Guidelines for the hub control
For developers (XAML)
Navigating between pages (XAML)
Windows.UI.Xaml.Controls Hub class