0% found this document useful (0 votes)
41 views103 pages

Windows 8 Tutorial

The document provides instructions on how to create a basic 'Hello World' Windows app using Visual Studio. It explains how to set up a new project, replace the default page with a basic page template, and modify the start page to display 'Hello World'.

Uploaded by

api-247740815
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
41 views103 pages

Windows 8 Tutorial

The document provides instructions on how to create a basic 'Hello World' Windows app using Visual Studio. It explains how to set up a new project, replace the default page with a basic page template, and modify the start page to display 'Hello World'.

Uploaded by

api-247740815
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 103

Part

1: app
Create
a "Hello,
world"
(Windows
Store
apps
C#/VB and
XAML)using
(Windows)
This tutorial teaches you how to create a simple "Hello, world" Windows Store app using
Extensible Application Markup Language (XAML) with Microsoft Visual Basic or C#. It's the first
tutorial in a series that teach you what you need to know to build Windows Store apps.
In this tutorial, you learn how to:

Create a new project

Add XAML content to your start page

Handle touch, pen, and mouse input

Switch between the light and dark themes

Create your own custom styles

We show you how to create a Windows Store app using XAML with Visual Basic or C#.

For the JavaScript, HTML, and CSS versions of these tutorials, see Create your first
Windows Store app using JavaScript.

For the C++ and XAML tutorial, see Create your first Windows Store app using C++.

For the DirectX and C++ tutorial, see Create your first Windows Store app using
DirectX.

Before you start...

To complete this tutorial, you need Windows 8 and Microsoft Visual Studio
Express 2012 for Windows 8. To download them, see Get the tools.

You also need a developer license. For instructions, see Get a developer license.

We assume you have a basic understanding of XAML and the concepts in the XAML
overview.

We assume you're using the default window layout in Microsoft Visual Studio. If you
change the default layout, you can reset it in the Window menu by picking the Reset
Window Layout command.

You can see the complete code for this tutorial in Part 1 complete code.

Step 1: Create a new project in Visual Studio

Launch Visual Studio Express 2012 for Windows 8.


The Visual Studio Express 2012 for Windows 8 start screen appears.
(Going forward, we'll refer to Visual Studio Express 2012 for Windows 8 as just "Visual
Studio".)

Select File > New Project.


The New Project dialog appears. The left pane of the dialog lets you select the type of

templates to display.
In the left pane, expand Installed > Templates, then expand Visual Basic or Visual
C# and pick the Windows Store template type. The dialog's center pane displays a
list of project templates for Windows Store apps.
In the center pane, select the Blank App template.
The Blank App template creates a minimal Windows Store app that compiles and
runs, but contains no user interface controls or data. You add controls and data to the
app over the course of these tutorials.

In the Name text box, enter "HelloWorld".

Click OK to create the project.


Visual Studio creates your project and displays it in the Solution Explorer.

Although the Blank App is a minimal template, it still contains a lot of files:

A manifest file (package.appxmanifest) that describes your app (its name, description,
tile, start page, and so on) and lists the files that your app contains.

A set of large and small logo images (logo.png and smalllogo.png)to display in the start
screen.

An image (storelogo.png) to represent your app in the Windows Store.

A splash screen (splashscreen.png) to show when your app starts.

XAML and code files for the app (App.xaml and App.xaml.cs/.vb) .

A start page (MainPage.xaml) and an accompanying code file (MainPage.xaml.cs/.vb)


that run when your app starts.

These files are essential to all Windows Store apps using Visual Basic or C#. Any project that
you create in Visual Studio contains them.

Replace the MainPage


The MainPage in the Blank App project template is based on the Blank Page template. It
contains the minimum amount of XAML and code to instantiate a Page. However, when you
create an app for the Windows Store, you must do more. For example, even a simple one page
app must adapt to different layouts and views, save its state when suspended, and restore its
state when resumed. The other project and Page templates in Visual Studio include some
additional code and helper classes that help you with view and state management. When you
use the Blank App project template, you typically replace the blank MainPage with one of the
other Page templates to take advantage of the layout and helper classes they provide.
In this example, you replace the default MainPage with a page that uses the Basic
Page template. Later tutorials in this series depend on the helper classes used by this
template for view and state management. For more info about the Pagetemplates you can
choose in Visual Studio, see C#, VB, and C++ item templates.
To replace MainPage in the blank app

In Solution Explorer, right-click MainPage.xaml and select Delete.

Click OK to confirm the deletion.

Select Project > Add New Item. The Add New Item dialog box opens. It looks

similar to the New Project dialog.

Under Visual C# or Visual Basic in the left pane, pick the Windows Store template
type.

In the center pane, pick Basic Page as the type of page to add to your project.

Enter "MainPage.xaml" as the name for the page.


Important If you leave the default name, "BasicPage1", the project will not build
correctly.

Click Add.
The first time you add a new page to the Blank App template (other than a Blank
Page), Visual Studio shows a dialog with a message that the addition depends on files
that are missing from your project. Click Yes to add these files. Files for several utility
classes are added to your project in the Common folder.
The XAML and code behind files for your page are added to the project.

Click Build > Build solution to build the app.


Important The new page will show an error in the designer until you build the helper
classes it depends on.

Step 2: Start the app

At this point, you created a very simple app. If you want to see what it looks like, press F5 to
build, deploy, and launch your app in debugging mode. A default splash screen appears first.
The splash screen is defined by an image (splashscreen.png) and a background color (specified
in our app's manifest file). We don't cover it here, but it's easy to customize your splash
screen. (To find out how, see Adding a splash screen.)
The splash screen disappears, and then your app appears. It contains a black screen and the
title "My Application".
There's no button or command to close the app. You can use the close gesture or Alt+F4 to
close it, but you typically don't close Windows Store apps, as we discuss more in Part 2:
Manage app lifecycle and state. Press the Windows key to go to the Start screen; notice that
deploying the app adds its tile to the last group on the Start screen. To run the app again, tap
or click its tile on the start screen, or press F5 in Visual Studio to run it in debugging mode.
It doesn't do muchyetbut congratulations, you've built your first Windows Store app!
To stop debugging the app, press Alt+Tab to return to Visual Studio. In Visual Studio,
click Debug > Stop debugging to close the app. You can't edit in Visual Studio while you're
debugging.
For more info, see Running Windows Store apps from Visual Studio.

Step 3: Modify your start page


What's in the files?

When you create a new project that uses the Blank App template, Visual Studio creates an
app that contains a handful of files. To view and edit the files, double-click the file in
the Solution Explorer. You can expand a XAML file just like a folder to see its associated code
file. By default, XAML files open in a split view that shows both the design surface and the
XAML editor.
In this tutorial, you work with just a few of the files listed previously: App.xaml,
App.xaml.cs/.vb, MainPage.xaml, and MainPage.xaml.cs/.vb.

App.xaml
App.xaml is where you declare resources that are used across the app. This file contains
a ResourceDictionary that has a reference to the

StandardStyles.xaml ResourceDictionary located in the Common folder. StandardStyles.xaml


provides a set of default styles that gives your app the Windows 8 look and feel.
XAML

<Application
x:Class="HelloWorld.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorld">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

App.xaml.cs/vb
App.xaml.cs/.vb is the code-behind file for App.xaml. Code-behind is the code that is joined
with the XAML page's partial class. Together, the XAML and code-behind make a complete
class. App.xaml.cs/.vb is the entry point for your app. Like all code-behind pages, it contains a
constructor that calls the InitializeComponent method. You don't write
theInitializeComponent method. It's generated by Visual Studio, and its main purpose is
to initialize the elements declared in the XAML file. App.xaml.cs/.vb also contains methods to
handle activation and suspension of the app. You add some code to these methods in Part 2:
Manage app lifecycle and state.
C#
VB

using
using
using
using
using

System;
Windows.ApplicationModel;
Windows.ApplicationModel.Activation;
Windows.UI.Xaml;
Windows.UI.Xaml.Controls;

// The Blank Application template is documented at http://go.microsoft.com/fwlink/?


LinkId=234227
namespace HelloWorld
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application

class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored
code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other
entry points
/// will be used when the application is launched to open a specific file, to display
/// search results, and so forth.
/// </summary>
/// <param name="args">Details about the launch request and
process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first
page
rootFrame = new Frame();
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
{

throw new Exception("Failed to create initial page");


}
}
// Ensure the current window is active
Window.Current.Activate();
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is
saved
/// without knowing whether the application will be terminated or resumed with
the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}

MainPage.xaml
In the MainPage.xaml file you define the UI for your app. You can add elements directly using
XAML markup, or you can use the design tools provided by Visual Studio. The Basic
Page template creates a new class called MainPage (or whatever name you enter) that
inherits from LayoutAwarePage. The LayoutAwarePage class extends the base Page class
and provides methods for navigation, state management, and view management. The Basic
Page template also includes some simple content, like a back button and page title.
XAML

<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="HelloWorld.MainPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource
Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorld"
xmlns:common="using:HelloWorld.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>

<!-- TODO: Delete this line if the key AppName is declared in App.xaml -->
<x:String x:Key="AppName">My Application</x:String>
</Page.Resources>
<!-This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Click="GoBack" IsEnabled="{Binding
Frame.CanGoBack, ElementName=pageRoot}" Style="{StaticResource
BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource
AppName}" Style="{StaticResource PageHeaderTextStyle}"/>
</Grid>
<VisualStateManager.VisualStateGroups>
<!-- Visual states reflect the application's view state -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- The entire page respects the narrower 100-pixel margin convention for
portrait -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!-- The back button and title have different styles when snapped -->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames

Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>

MainPage.xaml.cs/vb
MainPage.xaml.cs/.vb is the code-behind page for MainPage.xaml. Here you add your app logic
and event handlers. TheBasic Page template includes 2 methods where you can save and
load the page state.
C#
VB

using System;
using System.Collections.Generic;
using Windows.UI.Xaml.Controls;
// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?
LinkId=234237
namespace HelloWorld
{
/// <summary>
/// A basic page that provides characteristics common to most applications.
/// </summary>
public sealed partial class MainPage : HelloWorld.Common.LayoutAwarePage
{
public MainPage()
{
this.InitializeComponent();
}
/// <summary>
/// Populates the page with content passed during navigation. Any saved state
is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially
requested.
/// </param>

/// <param name="pageState">A dictionary of state preserved by this page


during an earlier
/// session. This will be null the first time a page is visited.</param>
protected override void LoadState(Object navigationParameter,
Dictionary<String, Object> pageState)
{
}
/// <summary>
/// Preserves state associated with this page in case the application is suspended
or the
/// page is discarded from the navigation cache. Values must conform to the
serialization
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <param name="pageState">An empty dictionary to be populated with
serializable state.</param>
protected override void SaveState(Dictionary<String, Object> pageState)
{
}
}
}

Modify the start page


Now, let's add some content to the app.
To modify the start page

Double-click MainPage.xaml in Solution Explorer to open it.

To change the page title, select the "My Application" text near the top of the page in
the XAML designer.

Make sure the TextBlock named pageTitle is showing in the Properties panel. By
default, the Properties panel is below the Solution Explorer panel.
The Properties panel contains a list of properties and values for the selected object.
Next to each property value is a property marker, a small box symbol that you can
click to open a property menu. The Text property marker is green to indicate that it's
set to a resource.
Under Common in the Properties panel, click the property marker for
the Text property. The property menu opens.

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,
world!".

Click OK.
Instead of entering the app name directly into the text block, you updated a string
resource that the text block'sText property is bound to. Using a resource like this
makes text reusable, easier to maintain, and easier to localize. In MainPage.xaml, the
XAML for the AppName resource definition is updated like this.
XAML

<x:String x:Key="AppName">Hello, world!</x:String>

In the XAML editor, add the controls for the UI.


In the root Grid, immediately before
the <VisualStateManager.VisualStateGroups> tag, add this XAML. It contains
a StackPanel with a TextBlock that asks the user's name, a TextBox element to
accept the user's name, a Button, and another TextBlock element.
XAML

<StackPanel Grid.Row="1" Margin="120,30,0,0">


<TextBlock Text="What's your name?"/>
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<TextBox x:Name="nameInput" Width="300"
HorizontalAlignment="Left"/>
<Button Content="Say &quot;Hello&quot;"/>
</StackPanel>
<TextBlock x:Name="greetingOutput"/>
</StackPanel>

We talk more about XAML layout in Part 3: Navigation, layout, and views.
Press F5 to run the app. It looks like this.
You can type in the TextBox, but right now, clicking the Button doesn't do anything.
In the next steps, you create an event handler for the button's Click event that
displays a personalized greeting. You add the event handler code to your
MainPage.xaml.cs/.vb file.

Step 4: Create an event handler

XAML elements can send messages when certain events occur. These event messages give
you the opportunity to take some action in response to the event. You put your code to
respond to the event in an event handler method. One of the most common events in many
apps is a user clicking a Button.
Let's create an event handler for your button's Click event. The event handler will get the
user's name from thenameInput TextBox control and use it to output a greeting to
the greetingOutput TextBlock.

Using events that work for touch, mouse, and pen input

What event should you handle? Because they can run on a variety of devices, design your
Windows Store apps with touch input in mind. Your app must also be able to handle input from
a mouse or a stylus. Fortunately, events such asClick and DoubleTapped are deviceindependent. If you're familiar with Microsoft .NET programming, you might have seen
separate events for mouse, touch, and stylus input, like MouseMove, TouchMove,
and StylusMove. In Windows Store apps, these separate events are replaced with a
single PointerMoved event that works equally well for touch, mouse, and stylus input.
To add an event handler

In XAML or design view, select the "Say Hello" Button that you added to
MainPage.xaml.

In the Properties Window, click the Events button (

).

Find the Click event at the top of the event list. In the text box for the event, type the
name of the function that handles the Click event. For this example, type
"Button_Click".

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.
In the XAML editor, the XAML for the Button is updated to declare the Click event
handler like this.
XAML

<Button Content="Say &quot;Hello&quot;" Click="Button_Click"/>

Add code to the event handler that you created in the code behind page. In the event
handler, retrieve the user's name from the nameInput TextBox control and use it to
create a greeting. Use the greetingOutput TextBlock to display the result.
C#
VB

private void Button_Click(object sender, RoutedEventArgs e)


{
greetingOutput.Text = "Hello, " + nameInput.Text + "!";
}

Press F5 to build and run the app. When you enter your name in the text box and click
the button, the app displays a personalized greeting.

Part 5: Style the start page


Choosing a theme
It's easy to customize the look and feel of your app. By default, your app uses resources with a
dark style. The system resources also include a light theme. Let's try it out and see what it
looks like.
To switch to the light theme

In Solution Explorer, double click App.xaml to open it.

In the opening Application tag, add the RequestedTheme property with its value set
to Light.
XAML

RequestedTheme="Light"
Here's the full Application tag with the light theme added.
XAML

<Application
x:Class="HelloWorld.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:HelloWorld"
RequestedTheme="Light">

Press F5 to build and run the app. Now it uses the light theme.

Which theme should you use? Whichever one you want. For apps that mostly display images or
video, we recommend using the dark theme, and for apps that contain a lot of text, we
recommend using the light theme. If you're using a custom color scheme, use the theme that
goes best with your app's look and feel.
Note The theme is applied when the app is started. You can't change themes while the app is
running.

Using standard styles


Earlier in this tutorial, we pointed out that the App.xaml file contains a reference to the
StandardStyles.xamlResourceDictionary:
XAML

<ResourceDictionary.MergedDictionaries>
<!-Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>

Right now, all the text is very small and difficult to read. You can easily apply the standard
styles to elements in your app to make them look great.
To style an element

Double-click MainPage.xaml in Solution Explorer to open it.

In XAML or design view, select the "What's your name?" TextBlock that you added
previously.

In the Properties Window, click the Properties button (

Expand the Miscellaneous group and find the Style property.

Click the property marker next to the Style property to open the menu.

In the menu, select Local Resource > BasicTextStyle.


BasicTextStyle is a resource defined in the
StandardStyles.xaml ResourceDictionary.

).

In the XAML design surface, the appearance of the text changes. In the XAML editor,
the XAML for the TextBlockis updated.
XAML

<TextBlock Text="What's your name?" Style="{StaticResource


BasicTextStyle}"/>

Repeat the process to assign the BasicTextStyle to


the greetingOutput TextBlock element.
Tip There's no text in this TextBlock, but when you hover the mouse pointer over the
XAML design surface, a blue outline shows where the TextBlock is so you can select it.
Your XAML now looks like this.
XAML

<StackPanel Grid.Row="1" Margin="120,30,0,0">


<TextBlock Text="What's your name?" Style="{StaticResource
BasicTextStyle}"/>
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<TextBox x:Name="nameInput" Width="300"
HorizontalAlignment="Left"/>
<Button Content="Say &quot;Hello&quot;" Click="Button_Click"/>
</StackPanel>
<TextBlock x:Name="greetingOutput" Style="{StaticResource
BasicTextStyle}"/>
</StackPanel>

Press F5 to build and run the app. It now looks like this.

Creating your own styles


To customize the look and feel of your app, you can create your own styles. For more info,
see Quickstart: Styling controls.
Here, you create a new style and apply it to the greetingOutput TextBlock. You put the
style in theResourceDictionary in App.xaml.
To use your own style

In XAML or design view, select the greetingOutput TextBlock that you added to
MainPage.xaml.

Expand the Miscellaneous group and find the Style property.

Click the property marker next to the Style property to open the menu.

In the menu, select Convert to New Resource.... The Create Style


Resource dialog opens.
Note The style that you want to modify must already be applied to the control. In this
example, theBasicTextStyle is still applied from the previous step, so that's the style
you'll modify a copy of.

In the Create Style Resource dialog, enter "BigGreenTextStyle" as the resource key,
and select the option to define the resource in the application.

Click OK. The new style is created in App.xaml and the TextBlock is updated to use
the new style resource.
XAML

<TextBlock x:Name="greetingOutput" Style="{StaticResource


BigGreenTextStyle}"/>

Click the property marker next to the Style property to open the menu again.

In the menu, select Edit Resource. App.xaml opens in the editor.


Note Nothing is shown in the XAML designer for App.xaml.

In the "BigGreenTextStyle" resource, change the Foreground value to "Green" and


the FontSize value to "36".
XAML

<Style x:Key="BigGreenTextStyle" TargetType="TextBlock">


<Setter Property="Foreground" Value="Green"/>
<Setter Property="FontSize" Value="36"/>
<Setter Property="FontFamily" Value="{StaticResource
ContentControlThemeFontFamily}"/>
<Setter Property="TextTrimming" Value="WordEllipsis"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Typography.StylisticSet20" Value="True"/>
<Setter Property="Typography.DiscretionaryLigatures" Value="True"/>
<Setter Property="Typography.CaseSensitiveForms" Value="True"/>
</Style>

Press F5 to build and run the app. The greeting is now displayed in large, green letters.

Summary
Congratulations, you're done with the first tutorial! You learned how to add content to a
Windows Store app. You also learned how to add interactivity and how to style the app.

Next steps

In the next part of this tutorial series, you learn how to app lifecycle works and how to save
your app's state. Go to Part 2: Manage app lifecycle and state.

Part
2:
Manage
app
lifecycle
and
state
(Windows
Store
apps
using
C#/VB
and XAML)
(Windows)

In Windows 8, you can launch a bunch of apps and switch between them without having to
worry about slowing down the system or running the battery down. That's because the system
automatically suspends (and sometimes terminates) apps that are running in the background
for you. A well-designed app can be suspended, terminated, and relaunched by the system and
seem as though it were running the entire time.
In this tutorial, you learn how to:

Save state using different types of storage

Restore your app's state the next time the app is launched

Before you start...

This is the second tutorial in a series. Before you start this tutorial, read Part 1: Create
a "Hello, world!" app.

You can see the complete code for this tutorial in Part 2 complete code.

About the app's lifecycle


Before you go back to the code, let's talk a bit about the app's lifecycle. Activation marks the
beginning of the app's lifecycle. At any given point, an app is not running, running, or
suspended.
An app can be suspended when the user switches away from it or when Windows enters a low
power state. While your app is suspended, it continues to reside in memory so that users can
quickly and reliably switch between suspended apps, resuming them. When your app is
suspended and then resumed, you don't have to write any extra code to make it look as
though it had been running the entire time.
But Windows can also terminate a suspended app at any time to free up memory for other
apps or to save power. When your app is terminated, it stops running and is unloaded from
memory.
When the user closes an app by pressing Alt+F4 or using the close gesture, the app is
suspended for 10 seconds and then terminated.
Windows notifies your app when it suspends it, but doesn't provide additional notification when
it terminates the app. That means your app must handle the suspended event and use it to
save its state and release its exclusive resources and file handles immediately.
To create a good user experience, you want your app to look like it never stopped running. The
app needs to retain any data the user entered, settings they changed, and so on. That means
you need to save your app's state when it's suspended, in case Windows terminates it, so that
you can restore its state later.
There are two types of data for you to manage in your app: app data and session data.
In the next steps, you learn how to update the app to save these types of data. What state do
you need to save? Right now, the only thing the user can change is their name entry. The user
can also click the Say "Hello" button to generate a personalized greeting.

Step 1: Using SuspensionManager

In Part 1: Create a "Hello, world" app, you replaced the default MainPage file with one based on
the Basic Page template. When you used the Basic Page template, Microsoft Visual Studio
added several files to the project in the Common folder. One of these files contains

the SuspensionManager class. SuspensionManager is a helper class that simplifies


lifecycle management for the app. It does several things for you. It saves and restores the
navigation state of the Frame that hosts the app pages. In a single-page app, saving the
navigation state doesn't seem very important, but it becomes very important when you add
multiple pages to an app. It also gives each page the opportunity to save and restore its
state.SuspensionManager serializes the page state data and writes it to an XML file in your
app's local storage.
To use the SuspensionManager class in the app, you first need to register the main
app Frame. When you are done,SuspensionManager knows about each page in the app, and
it can save and restore the navigation state. You register theFrame immediately after it's
created in the OnLaunched method in App.xaml.cs/vb.
To use SuspensionManager

Double-click App.xaml.cs/vb in Solution Explorer to open it.

In the OnLaunched method, call the SuspensionManager.RegisterFrame method


to register the root Frame.
C#
VB

HelloWorld.Common.SuspensionManager.RegisterFrame(rootFrame,
"appFrame");
Add this code after the new Frame is created, as shown here.
C#
VB

if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first
page
rootFrame = new Frame();
HelloWorld.Common.SuspensionManager.RegisterFrame(rootFrame,
"appFrame");
...

Step 2: Save the app's state


Generally, there are two types of data for you to manage in your app: app data and session
data. App data is persistent across sessions and must always be accessible to the user. In your
app, the Text of the nameInput TextBox is app data. Always save important app data
incrementally throughout the life of your app. Because your app has only up to five seconds to
run code in the suspending event handler, you need to ensure that your important app data is
saved to persistent storage by the time it's suspended.
Windows provides a Windows.Storage.ApplicationData object to help you manage your
app data. This object has aRoamingSettings property that returns
an ApplicationDataContainer. You can use this ApplicationDataContainer to store app
data that persists across sessions. Let's store the user's name in the
roaming ApplicationDataContainer as the user types it in.
Note This tutorial shows how to use RoamingSettings. The roaming settings app data

container makes it easy to store data in a way that is accessible to the user across multiple
machines. Basically, the data is uploaded to the cloud in the background for you. You can also
use the local settings app data container (LocalSettings), but you should only use it when
you want to store machine-specific info.
Save persistent app data as often as it makes sense in your application. Here, you handle
the TextBox.TextChangedevent and save the user name as the user enters it.
To save app data

Double-click MainPage.xaml in Solution Explorer to open it.

In Extensible Application Markup Language (XAML) or design view, select


the nameInput TextBox that you added to MainPage.xaml.

In the Properties panel, click the Events button (

Find the TextChanged event in the event list. In the text box for the event, type
"NameInput_TextChanged" as the name of the function that handles
the TextChanged 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 in the code behind page. In the event handler, you
save the nameInput text inroamingSettings.

).

C#
VB

Windows.Storage.ApplicationDataContainer roamingSettings =
Windows.Storage.ApplicationData.Current.RoamingSettings;
roamingSettings.Values["userName"] = nameInput.Text;

Press F5 to build and run the app. Your name is saved as you enter it into the text box.

Session data is temporary data that is relevant to the users current session in your app. A
session ends when the user closes the app using the close gesture or Alt + F4, reboots the
computer, or logs off the computer. In your app, the Textof
the greetingOutput TextBlock is session data. You restore it only if Windows suspends and
terminates the app. You need to save the navigation state of the app Frame, so the app can
be restored to the same page is was on, and so the SuspensionManager knows which page to
restore the state of. You also need to save the state of the page itself. This is where you save
the greetingOutput text. You use the SuspensionManager class to save session state in
theApplication.Suspending event handler.
(For more info about the other ways you can save state, see Managing app data and Working
with state efficiently.)
The App.xaml.cs/vb file contains a handler for the Application.Suspending event. This event
handler gets called when Windows is about to suspend your app. This is your opportunity to
save the state of the app in case it gets terminated. You use the SuspensionManager class to
simplify saving session state. It saves the navigation state of the app, and gives you the
opportunity to save the session state of the active page.
To save the session state

Double-click App.xaml.cs/vb in Solution Explorer to open it.

In App.xaml.cs/vb, add the async keyword to the OnSuspending method signature.


For more info about asynchronous programming, see Quickstart: using the await
operator for asynchronous programming.

In the OnSuspending method, call the SuspensionManager.SaveAsync method.


C#
VB

await HelloWorld.Common.SuspensionManager.SaveAsync();

Calling SaveAsync saves the navigation state of the Frame and then gives
your Page the opportunity to save its content.
Here's the full OnSuspending method with the updates made.
C#
VB

/// <summary>
/// Invoked when application execution is being suspended. Application
state is saved
/// without knowing whether the application will be terminated or
resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend
request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
await HelloWorld.Common.SuspensionManager.SaveAsync();
deferral.Complete();
}

Double-click MainPage.xaml.cs/vb in Solution Explorer to open it.

In MainPage.xaml.cs/vb, add this code to the SaveState method to save the page
state.
C#
VB

pageState["greetingOutputText"] = greetingOutput.Text;

The SuspensionManager class serializes and saves the pageState dictionary to an


XML file. Data saved in pageStateis saved only for this session. You save
the greetingOutput text here.
Here's the full code of the SaveState method.
C#
VB

/// <summary>
/// Preserves state associated with this page in case the application is
suspended or the
/// page is discarded from the navigation cache. Values must conform to
the serialization
/// requirements of <see cref="SuspensionManager.SessionState"/>.
/// </summary>
/// <param name="pageState">An empty dictionary to be populated
with serializable state.</param>
protected override void SaveState(Dictionary<String, Object>
pageState)
{
pageState["greetingOutputText"] = greetingOutput.Text;
// The user name is already saved, so you don't need to save it here.
}

Click Build > Build solution to make sure the app builds with no errors.

That's all you need to do to save your app's state before your app is terminated. Now you need
to learn how to restore your app's state the next time the user launches the app.

Step 3: Restore the app's state

Earlier, you saw that the App.xaml.cs/vb file contains code that handles your app's activation.
There are many different ways to activate an app. Here we look at the Launch activation and
the OnLaunched method.
An app is launched whenever it wasn't running and then the user activates it. When an app is
launched, Windows displays a splash screen for the app.
Let's take a look at the code in App.xaml.cs/vb that handles app activation. The code defines
an override of theOnLaunched method. The code in this method is executed only if the
activation is a Launch activation. (You can override other methods to handle other kinds of
activation, but we don't do it here. For more info, see Application lifecycle.)
First, the code declares a Frame and tries to assign the current window contents to it.
C#
VB

Frame rootFrame = Window.Current.Content as Frame;


If the window already contains a Frame, that indicates that the app is already initialized, so

initializing the Frame is skipped.


If the app isn't initialized, the code creates a Frame to host the app pages. You register
the Frame with theSuspensionManager. This is the code you added in Step 1.
Next, the code checks the previous execution state to see how the app was last shut down.
When the previous execution state is Terminated it means that the last time the app ran,
Windows successfully suspended the app and then terminated it. In that case, you need to
restore the app's state.
C#
VB

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first
page
rootFrame = new Frame();
HelloWorld.Common.SuspensionManager.RegisterFrame(rootFrame,
"appFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}

Next, the code checks if the Frame contains any content. If the app is already running, or the
navigation state was restored, the Frame already has content. Otherwise,
the Frame navigates to the first page in the app. In this case, it navigates to MainPage.
C#
VB

if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}

Finally, the code activates the window.


C#

VB

// Ensure the current window is active


Window.Current.Activate();

Now that you know what happens when the app is launched, let's look at how to restore the
app state.
To restore the app's state

In App.xaml.cs/vb, add the async keyword to the OnLaunched method signature.


C#
VB

protected async override void OnLaunched(LaunchActivatedEventArgs args)

If the app was terminated, call the SuspensionManager.RestoreAsync method.


Calling RestoreAsync restores the navigation state of the Frame and then gives
the Page the opportunity to restore its content.
C#
VB

if (args.PreviousExecutionState ==
ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
await HelloWorld.Common.SuspensionManager.RestoreAsync();
}

In MainPage.xaml.cs/vb, add code to the LoadState method to restore the page state.

First, check to see if the pageState dictionary exists and has a key
named greetingOutputText. If the key exists, use it to restore
the greetingOutput text.
C#
VB

// Restore values stored in session state.


if (pageState != null &&
pageState.ContainsKey("greetingOutputText"))
{
greetingOutput.Text =
pageState["greetingOutputText"].ToString();

Next, load the user name. Because you want the user name data to persist
over multiple sessions, you store it in the RoamingSettings app data
container. Let's add some code to see whether the user name exists and, if it
does, display it.
C#
VB

// Restore values stored in app data.


Windows.Storage.ApplicationDataContainer roamingSettings =
Windows.Storage.ApplicationData.Current.RoamingSettings;
if (roamingSettings.Values.ContainsKey("userName"))
{
nameInput.Text =
roamingSettings.Values["userName"].ToString();
}

Here's the complete code for the LoadState method.

C#

VB

/// <summary>
/// Populates the page with content passed during navigation. Any saved
state is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed
to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was
initially requested.
/// </param>
/// <param name="pageState">A dictionary of state preserved by this
page during an earlier
/// session. This will be null the first time a page is visited.</param>
protected override void LoadState(Object navigationParameter,
Dictionary<String, Object> pageState)
{
// Restore values stored in session state.
if (pageState != null &&
pageState.ContainsKey("greetingOutputText"))
{
greetingOutput.Text = pageState["greetingOutputText"].ToString();
}

// Restore values stored in app data.


Windows.Storage.ApplicationDataContainer roamingSettings =
Windows.Storage.ApplicationData.Current.RoamingSettings;
if (roamingSettings.Values.ContainsKey("userName"))
{
nameInput.Text = roamingSettings.Values["userName"].ToString();
}
}

Now you can build and run the app, and see how the session state is saved and restored. So
far, you've tested your app by running it in debug mode, and stopped it by
selecting Debug > Stop Debugging in Visual Studio. But doing this causes the app to
perform a normal shutdown, and the Suspending event doesn't occur. Fortunately, Visual
Studio lets you simulate suspending, terminating, and restoring an app.
To simulate suspending, terminating, and restoring an app in Visual Studio

Press F5 to run the app in debug mode.

Enter your name in the input box and click "Say "Hello"". The greeting is displayed.

Press Alt+Tab to return to Visual Studio.

Open the drop down menu next to the Suspend button on the Debug
Location toolbar.
The Debug Location toolbar appears by default while the debugger is running. If you
don't see it, click View >Toolbars > Debug Location to show it.

Select Suspend and shutdown.


Visual Studio simulates suspending and terminating your app, so
the Suspending event occurs and your state management code is executed.

Press F5 to run the app again. The app is restored to its previous state.

Change the name in the text box, and click "Say "Hello"".

Press Alt+Tab to return to Visual Studio.

Close the app by selecting Debug > Stop Debugging.

Press F5 to run the app again.


Now, the user name is restored because it was saved as you typed it in. The greeting is
not restored because theSuspending event didn't occur, so the session state wasn't
saved.

Summary

Congratulations, you're done with the second tutorial! You learned how to save app data and
session state in a Windows Store app.

Next steps

In the next part of this tutorial series, you learn how to use the design tools in Visual Studio to
create a more complex UI. Go to Part 3: Navigation, layout, and views.

Part
3:
Navigation,
layout,
and views (Windows)

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.
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 Library, 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.
XAML

<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:
XAML

<Button x:Name="photoPageButton" Content="Go to photo page"/>


Here's the button you added with the surrounding XAML.
XAML

<StackPanel Grid.Row="1" Margin="120,30,0,0">


<TextBlock Text="What's your name?" Style="{StaticResource
BasicTextStyle}"/>
<StackPanel Orientation="Horizontal" Margin="0,20,0,20">
<TextBox x:Name="nameInput" Width="300"
HorizontalAlignment="Left"
TextChanged="NameInput_TextChanged"/>
<Button Content="Say &quot;Hello&quot;" Click="Button_Click"/>
</StackPanel>
<TextBlock x:Name="greetingOutput" Style="{StaticResource

BigGreenTextStyle}"/>
<Button x:Name="photoPageButton" 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.

).

C#
VB

// Add this code.


if (this.Frame != null)
{
this.Frame.Navigate(typeof(PhotoPage));
}

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 LayoutAwarePage class, 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. For more examples of navigation support, see the
"Navigation support" region of the LayoutAwarePage.cs/.vb file in the Common folder of the
project.

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 andGrid.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
Solution
Explorer

Image

Description
Use to manage
files in your
project.

Double-click
a file to
open it. If
the file is
already
open, it's
made the
active

document.
Properti
es

Use to view and


edit properties of
the selected item.
By default,
properties
are
grouped
by
category.
Expand a
category
to see its
properties.

XAML
Designe
r

Show
advanced
properties
by clicking
the down
arrow at
the bottom
of a
category.

Use to add and


arrange elements
of the app UI.

Common
interaction
s are drag
-and-drop
to arrange
items, and
click to
select an
item.

XAML
editor

Use to directly edit


XAML.

Toolbox

Use to add
controls and other
items to your app
UI.

Drag and
drop

controls
onto the
surface of
the
designer.
Device

Use to simulate
different settings
of a physical
device in the
designer.
Click the
view
buttons to
simulate
different
app views
in the
designer.

Docume
nt
Outline

Change the
Display
settings to
simulate
different
resolutions
in the
designer.

Use to select and


arrange UI
elements in a
hierarchical view.
Click an
item to
select it.
Click an
arrow to
expand an
item and
see its
child
elements.
Use
Ctrl+Click
to select
multiple
non-

contiguous
items.
Use
Shift+Click
to select
multiple
contiguous
items.

Drag-anddrop items
to
rearrange
them.

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

Double-click the file name in Solution Explorer. If the file is already open, it is made
active in the designer and XAML editor.

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
Open any of the panels by clicking the name of the panel you want to open.
To keep the panel open, click the Auto Hide (pin) icon in the panel header.
Tip If the Toolbox covers a part of the XAML designer where you need to drop a control,
pin the Toolboxopen.
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
In the Document Outline, click the element or the element name if it has a name.
In the XAML editor, click the opening tag for the element.
In the XAML designer, do one of these:
Move your mouse cursor over the item until a blue highlight appears around it.
Click the highlighted item to make it active.
Right-click an object in the designer. In the context menu, open the Set Current
Selection sub-menu and pick the item to make active.

Check the Properties panel to ensure the correct element is active.

The Properties panel has views for managing both properties and events.

To switch the Properties panel between Properties and Events views


In the Properties panel,
click the Events button (

) to show the Events view.

click the Properties button (

) to show the Properties view.

To reference an element in your code, you must give it a name.


To name a UI element
Select the element to name.
In the Properties panel, type a name into the Name text box.
Press Enter to commit the name.
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
Ensure that the element that has the property is selected, and the Properties panel is
showing the Propertiesview.
In the Properties panel, click the property marker next to the property value. The
property menu opens.
In the property menu, click Reset.
To change the alignment of an element
Select the element to align.
Under Layout in the Properties panel, do one of the following:
Change the HorizontalAlignment property to one of these:
Left
Anchors to the left but stretches to the right when resized.
Center
Always anchored to the horizontal center regardless of resizing.
Right
Anchors to the right but stretches to the left when resized.
Stretch
Stretches in both horizontal directions when resized.

Change the VerticalAlignment property to one of these:

Bottom
Anchors to the bottom but stretches to the top when resized.
Center
Always anchored to the vertical center regardless of resizing.
Top
Anchors to the top but stretches to the bottom when resized.
Stretch
Stretches in both vertical directions when resized.
To change the margins of an element
Select the element to set margins on.
Under Layout in the Properties panel, set one or more of the Margin values: Left, Right,
Top, Bottom.

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 navigation app bar

In Solution Explorer, double-click MainPage.xaml to open it.

In the Document Outline, select the "pageRoot" element.

In the Properties panel, click the Properties button (


the Properties view.

Under Common in the Properties panel, find the TopAppBar property.

Click the New button next to TopAppBar. An AppBar control is added to the page.

In the Document Outline, expand the TopAppBar property.

Select the "photoPageButton" element, drag it onto the AppBar, and drop it.

Under Layout in the Properties panel, set the HorizontalAlignment property


to Right (
).

Press F5 to build and run the app. To test the app bar, right-click on the main page. The

) to show

app bar opens at the top of the screen.


Commands in an app bar are typically shown using a special style with a round button and
icon. Many common app bar button styles are included in the StandardStyles.xaml resource
dictionary. Here, you apply one of these styles to the navigation button in the app bar.
Style the app bar button

In Solution Explorer, expand the Common folder and double-click


StandardStyles.xaml to open it.

Find the Style with the x:Key value PicturesAppBarButtonStyle.


Tip Press Ctrl+F to open the Find window and search for
"PicturesAppBarButtonStyle".

Move this Style outside of the comment tags (<!-- comment -->) to make it
available to use.

Or, copy the XAML into the local ResourceDictionary in App.xaml.


Here's the XAML for the Style.
XAML

<Style x:Key="PicturesAppBarButtonStyle" TargetType="ButtonBase"


BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId"
Value="PicturesAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="Pictures"/>
<Setter Property="Content" Value="&#xE158;"/>
</Style>

Save and close StandardStyles.xaml.

In MainPage.xaml, select the "photoPageButton" element in the Document


Outline panel.
(You might need to expand the TopAppBar element to see it.)

Reset these Button properties: Content.

Under Miscellaneous in the Properties panel, find the Style property.

Click the property marker next to the Style property to open the menu.

In the menu, select Local Resource > PicturesAppBarButtonStyle.


Here's the final XAML for the app bar. (In VB, the Click event declaration might be
missing. The event handler uses the Handles keyword instead.)
XAML

<common:LayoutAwarePage.TopAppBar>
<AppBar>
<Button x:Name="photoPageButton"
Click="PhotoPageButton_Click"
HorizontalAlignment="Right"
Style="{StaticResource PicturesAppBarButtonStyle}"/>

</AppBar>
</common:LayoutAwarePage.TopAppBar>

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 Gridnow 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.
XAML

<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 ColumnDefinitionobjects
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 andGrid.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 the Pictures library,
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,
andMargin.

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,
andMargin.

Expand the Miscellaneous group and find the Style property.

In the Style property menu, select Local


Resource > PageSubheaderTextStyle.

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, Vertic
alAlignment, andMargin.

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 6-7 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 Image Source property, select "Logo.png".

In the Document Outline, select the Border that contains the Image.

In the Properties panel, reset the Border Width property.

Add the image info

Drag a TextBlock control from the Toolbox and drop it in the


"imagePanel" StackPanel, to the right of theImage 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 theTextBlocks that show the picture info.

Here's the XAML that's generated for this layout.


XAML

<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 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 Local Resource > CaptionTextStyle.

Select the second, fourth, and sixth TextBlock controls in the group.

Set the Style property to Local Resource > ItemTextStyle.

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.
XAML

<StackPanel Margin="20,0,0,0">
<TextBlock TextWrapping="Wrap" Text="File name:"
Style="{StaticResource CaptionTextStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{StaticResource ItemTextStyle}" Margin="10,0,0,30"/>
<TextBlock TextWrapping="Wrap" Text="Path:"
Style="{StaticResource CaptionTextStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{StaticResource ItemTextStyle}" Margin="10,0,0,30"/>
<TextBlock TextWrapping="Wrap" Text="Date created:"
Style="{StaticResource CaptionTextStyle}"/>
<TextBlock TextWrapping="Wrap" Text="TextBlock"
Style="{StaticResource ItemTextStyle}" 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. In the landscape orientation, it must support Full
Screen, Filled, and Snapped layouts. 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 each view, you can use the Device panel in Microsoft Visual
Studio 2012. 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 View 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.
First, lets try the different views to see how the app looks.
To use different views in Visual Studio

In the Device panel, click the filled (


simulate the filled view.

) view button. The designer changes to

This is what the app looks like when the user snaps another app next to it. This view
looks okay, so you can leave it as is.

In the Device panel, click the snapped (


the snapped view.

) button. The designer changes to simulate

This is what the app looks when the user snaps it next to another app. This view is too
narrow to show the whole app, so you need to make some adjustments for this to
work.

In the Device panel, click the portrait (


the portrait view.

) button. The designer changes to simulate

This is what the app looks like when the user rotates it to portrait orientation. This view
is also too narrow. You need to make some adjustments similar to those you make for
the snapped view.

Adjust the snapped view


You start by making some changes to the snapped view.
To adjust the snapped view

In the Device panel, click the snapped (

) button to show the snapped view.

Check the Enable state recording checkbox.


When you enable state recording, changes to the layout are applied only to the current
visual state, and the changes are made in the VisualStateManager section of the
XAML. Otherwise, changes are made to the default view.

Select the "contentGrid" Grid control.

Under Layout, set the grid's left Margin to "20".

Set the grid's bottom Margin to "20".

Select the "imagePanel" StackPanel.

Under Layout in the Properties panel, set the panel's Orientation property
to Vertical.

The app now looks like this in snapped view.


When you changed the StackPanel from Horizontal to Vertical,
the Border and Image resized 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.

Adjust the portrait view


Now, let's fix the portrait view.
To adjust the portrait view

In the Device panel, click the portrait (

) button to show the portrait view.

Check the Enable state recording checkbox.

Select the "imagePanel" StackPanel.

Under Layout in the Properties panel, set the panel's Orientation property
to Vertical.

Set the panel's right Margin property to "20".

The app now looks like this in portrait orientation.


To test the app in different orientations, views, and resolutions, you can use the simulator in
Visual Studio. For more information about testing the app in the simulator, see Running
Windows Store apps from Visual Studio.

Summary

Congratulations, you're done with the third tutorial! You learned how to save app data and
session state in a Windows Store app.

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.

Part
4:
File
access
and
pickers (Windows)

In Part 2 of this tutorial series, Manage app lifecycle and state, you learned aboutapp
data and session data, and how to save this data in ApplicationDatastorage. Your app can
access certain file system locations, like app data locations, the app install directory, and items
it creates in the Downloads folder, by default.
In contrast, user data, such as pictures, videos, and document files, is independent of your app
and is typically stored in other locations in the file system, such as the users library folders. To
access these locations, your app needs to declare capabilities to access the data
programmatically, or use a file picker to let the user open the file manually. Here, you use a file
picker to access the users Pictures library, so you don't need to declare any app capabilities.
For more info about capabilities, see App capability declarations.
In this tutorial, you add functionality to the photo page layout you created in Part 3:
Navigation, layout, and views. First, you handle the "Get photo" button click event to open a
file picker and let the user select an image from their Pictures library. Then you bind UI controls
to file properties to show the picture info. Finally, we revisit what you learned in Part 2 about
how to save app state. Here, you use aMostRecentlyUsedList to keep access to the image
selected by the user.
In this tutorial, you learn how to:

Use a FileOpenPicker to let a user get a file

Bind UI controls to data

Use a MostRecentlyUsedList to access a previously opened file

Before you start...

This is the fourth tutorial in a series. Before you start, read Part 1: Create a "Hello,
world!" app, Part 2: Manage app lifecycle and state, and Part 3: Navigation, layout, and
views.

You can see the complete code for this tutorial in Part 4 complete code.

Step 1: Use a file picker to get an image file


Through the file picker, your app can access files and folders all over the user's system. When
you call the file picker, the user can browse their system and select files (or folders) to access
and save. After the user picks files or folders, your app receives those picks
as StorageFile and StorageFolder objects. Your app can then operate on picked files and
folders by using those objects.

The first thing you need to do is handle the GetPhotoButton_Click event to get a picture to
show.
We start here with the code from Part 3: Navigation, layout, and views.
To add a file picker

In Solution Explorer, double-click PhotoPage.xaml to open it.

Select the "Get photo" Button.

In the Properties Window, click the Events button (

Find the Click event at the top of the event list. In the text box for the event, type
"GetPhotoButton_Click" as the name of the method 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 the async keyword to the method signature of the event handler.

).

C#
VB

private async void GetPhotoButton_Click(object sender, RoutedEventArgs e)


{
}

Add this code to the event handler method. It opens a file picker to let the user select a
picture from their Pictures library. When they pick a file, it's set as the source of the
image and the data context of the page.
C#
VB

// File picker APIs don't work if the app is in a snapped state.


// If the app is snapped, try to unsnap it first. Only show the picker if it
unsnaps.
if (Windows.UI.ViewManagement.ApplicationView.Value !=
Windows.UI.ViewManagement.ApplicationViewState.Snapped ||
Windows.UI.ViewManagement.ApplicationView.TryUnsnap() ==
true)
{
Windows.Storage.Pickers.FileOpenPicker openPicker = new
Windows.Storage.Pickers.FileOpenPicker();
openPicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
openPicker.ViewMode =
Windows.Storage.Pickers.PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types.

openPicker.FileTypeFilter.Clear();
openPicker.FileTypeFilter.Add(".bmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".jpg");
// Open the file picker.
Windows.Storage.StorageFile file = await
openPicker.PickSingleFileAsync();
// file is null if user cancels the file picker.
if (file != null)
{
// Open a stream for the selected file.
Windows.Storage.Streams.IRandomAccessStream fileStream =
await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Set the image source to the selected bitmap.
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapImage =
new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bitmapImage.SetSource(fileStream);
displayImage.Source = bitmapImage;
this.DataContext = file;
// mruToken =
Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUs
edList.Add(file);
}
}

Press F5 to build and run the app. Navigate to the photo page, and click the "Get
photo" button to launch theFileOpenPicker. The photo appears, but the photo info
text is not updated. You'll fix that in the next step.
Here's what the app looks like with a picture selected.

Lets take a closer look at the code to use the FileOpenPicker. To use a file picker you need to
do 3 basic steps: ensure that the file picker can be opened, create and customize a file picker
object, and show the file picker so the user can pick an item.
You cant open the file picker UI in snapped view. So, before you call a file picker you must first
make sure that your app isnt snapped, or if it is, you must call the TryUnsnap method to
unsnap it.
C#
VB

if (Windows.UI.ViewManagement.ApplicationView.Value !=
Windows.UI.ViewManagement.ApplicationViewState.Snapped ||
Windows.UI.ViewManagement.ApplicationView.TryUnsnap() == true)

Next, create a FileOpenPicker object.


C#
VB

Windows.Storage.Pickers.FileOpenPicker openPicker = new


Windows.Storage.Pickers.FileOpenPicker();

Set the properties on the file picker object that are relevant to your users and your app. For
guidelines to help you decide how to customize the file picker, see Guidelines for file pickers.
Because the user is picking a picture, you set the SuggestedStartLocation to the Pictures
library and the ViewMode toThumbnail. You also add file type filters so the picker shows only
the file types you specify for image files.
C#
VB

openPicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
openPicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types.
openPicker.FileTypeFilter.Clear();
openPicker.FileTypeFilter.Add(".bmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".jpg");

After you create and customize a file picker, call FileOpenPicker.PickSingleFileAsync to


show it and let the user pick one file.
Note To let a user pick multiple files, call PickMultipleFilesAsync.
C#
VB

// Open the file picker.


Windows.Storage.StorageFile file = await openPicker.PickSingleFileAsync();

When the user picks a file, PickSingleFileAsync returns a StorageFile object that represents
the picked file. You process the image stream to create a BitmapImage and set
the BitmapImage as the Source of the Image control in the UI. You also set the file as
the DataContext of the page so that you can bind UI elements to its properties.
C#
VB

// file is null if user cancels the file picker.


if (file != null)
{
// Open a stream for the selected file
Windows.Storage.Streams.IRandomAccessStream fileStream =
await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Set the image source to the selected bitmap.
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapImage =
new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bitmapImage.SetSource(fileStream);
displayImage.Source = bitmapImage;
this.DataContext = file;
}

Step 2: Bind UI controls to file data


At this point, the image is shown in the UI, but the image file properties are not shown in the
text blocks you added. You could set the Text property of each TextBlock in code, just as you
set the Image.Source property.
But to display data, you typically use data binding to connect a data source to the UI, either by
setting theBinding.Source property or by setting the DataContext on the UI element. When
you establish a binding and the data source changes, the UI elements that are bound to the
data source reflect the changes automatically.
Note Bindings are one-wayby default, which means updates to the data source are reflected
in the UI. You can specify atwo-way binding so that changes the user makes in a UI element
can be reflected in the data source. For example, if the user edits the value in a TextBox, the
binding engine automatically updates the underlying data source to reflect that change.
The DataContext property lets you set the default binding for an entire UI element, including
all of its child elements. You set the StorageFile selected in the FileOpenPicker as
the DataContext of the photo page. Remember that after picking the image, you set
the DataContext with this line of code.
C#
VB

this.DataContext = file;

Here, you show the file name by binding the Text property of the title TextBlock to
the StorageFile.DisplayNameproperty of the selected file.
Because you dont specify a binding Source, the data binding engine looks for
the DisplayName property on theDataContext. If the DataContext is null or doesn't have
a DisplayName property, the binding fails silently and no text is shown in the TextBlock.
Here, you bind the TextBlock controls to StorageFile properties .
To bind controls to data

In Solution Explorer, double-click PhotoPage.xaml to open it.

Select the TextBlock for the photo name that's under the "Get photo" button.

In the Properties panel, click the Properties button (


the Properties view.

) to show

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 black to indicate that it's set to a string value.

In the property menu, select Create Data Binding.... The Create Data
Binding dialog opens.

In the Create Data Binding dialog, select Data context in the Binding type dropdown list.

Enter "DisplayName" in the Path text box as shown here.


Note The message in the Create Data Binding dialog says the data context is not
set. That's okay because you set the data context in code when the you run the app
and get a picture.

Click OK.
Here's the Extensible Application Markup Language (XAML) for the TextBlock after you
add the binding.
XAML

<TextBlock Grid.Row="1" TextWrapping="Wrap" Text="{Binding


DisplayName}"
Style="{StaticResource PageSubheaderTextStyle}"/>

Select the TextBlock after the "File name:" TextBlock.

Repeat steps 3-5 to create a data binding for this TextBlock.

Enter "Name" in the Path text box and click OK.

Select the TextBlock after the "Path:" TextBlock.

Repeat steps 3-5 to create a data binding for this TextBlock.

Enter "Path" in the Path text box and click OK.

Select the TextBlock after the "Date created:" TextBlock.

Repeat steps 3-5 to create a data binding for this TextBlock.

Enter "DateCreated" in the Path text box and click OK.

Here's the XAML for the photo info StackPanel after you add the bindings.
XAML

<StackPanel Margin="20,0,0,0">
<TextBlock Text="File name:" Style="{StaticResource

CaptionTextStyle}"/>
<TextBlock Text="{Binding Name}" Style="{StaticResource
ItemTextStyle}" Margin="10,0,0,30"/>
<TextBlock Text="Path:" Style="{StaticResource
CaptionTextStyle}"/>
<TextBlock Text="{Binding Path}" Style="{StaticResource
ItemTextStyle}" Margin="10,0,0,30"/>
<TextBlock Text="Date created:" Style="{StaticResource
CaptionTextStyle}"/>
<TextBlock Text="{Binding DateCreated}"
Style="{StaticResource ItemTextStyle}" Margin="10,0,0,30"/>
</StackPanel>

Press F5 to build and run the app. Navigate to the photo page. Click the "Get photo"
button to launch theFileOpenPicker. With bindings in place, file properties are now
shown when you pick a file.
Here's what the app looks like with a picture selected and the text blocks bound to
data.

Step 3: Save and load state


In Part 2 of this tutorial series, Manage app lifecycle and state, you learned how to save and
restore the app state. Now that youve added a new page to the app, you need to save and
load the state of the new page, too. For the photo page, you only need to save and restore the
currently displayed image file.
But you cant just save the path to the file and then re-open it using that path. When a user
picks a file with aFileOpenPicker, they implicitly give your app permission to that file. If you
try to later retrieve the file using just the path, permission is denied.
Instead, to preserve access to the file for later use,
the StorageApplicationPermissions class provides 2 lists where you can store the file and
its permissions that were granted when the user opened it with the file picker.

MostRecentlyUsedList - use to store the last 25 files accessed.

FutureAccessList - use for general storage of up to 1000 files for future access.

You only need access to the last file the user picked so you can use it to restore the page state.
For this, theMostRecentlyUsedList fits your needs.
When a user picks a file, you add it to the MostRecentlyUsedList. When you add a file to this
list, theMostRecentlyUsedList returns a token that you use to retrieve the file later. You save
this token in the pageStatedictionary and use it to retrieve the current image file when you
restore the page state.
To save state

In Solution Explorer, double-click PhotoPage.xaml.cs/vb to open it.

At the top of the PhotoPage class, add this code. It declares a variable to hold the
token returned by theMostRecentlyUsedList.
C#

VB

private string mruToken = null;


Here's the code with its surrounding code.
C#
VB

public sealed partial class PhotoPage : HelloWorld.Common.LayoutAwarePage


{
private string mruToken = null;
public PhotoPage()
{
this.InitializeComponent();
}
...

In the GetPhotoButton_Click event handler, add this code. It adds the picked file to
the MostRecentlyUsedListand gets the token.
C#
VB

// Add picked file to MostRecentlyUsedList.


mruToken =
Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUs
edList.Add(file);
Here's the code with its surrounding code.
C#
VB

// file is null if user cancels the file picker.


if (file != null)
{
// Open a stream for the selected file.
Windows.Storage.Streams.IRandomAccessStream fileStream =
await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Set the image source to the selected bitmap.
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapImage =
new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bitmapImage.SetSource(fileStream);
displayImage.Source = bitmapImage;

this.DataContext = file;
// Add picked file to MostRecentlyUsedList.
mruToken =
Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUs
edList.Add(file);
}

In the SaveState method, add this code. It checks if the token exists, and saves it in
the pageState dictionary if it does.
C#
VB

if (!String.IsNullOrEmpty(mruToken))
{
pageState["mruToken"] = mruToken;
}
Here's the complete code for the SaveState method.
C#
VB

protected override void SaveState(Dictionary<String, Object> pageState)


{
if (!String.IsNullOrEmpty(mruToken))
{
pageState["mruToken"] = mruToken;
}
}
To load state

In PhotoPage.xaml.cs/vb, add the async keyword to the LoadState method signature.


C#
VB

protected async override void LoadState(Object navigationParameter,


Dictionary<String, Object> pageState)
{
}

Add this code in the LoadState method.

Here, you get the token from the pageState dictionary. You use the token to retrieve
the file from theMostRecentlyUsedList and restore the UI state.
C#
VB

if (pageState != null && pageState.ContainsKey("mruToken"))


{
object value = null;
if (pageState.TryGetValue("mruToken", out value))
{
if (value != null)
{
mruToken = value.ToString();
// Open the file via the token that you stored when adding this
file into the MRU list.
Windows.Storage.StorageFile file =
await
Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUs
edList.GetFileAsync(mruToken);
if (file != null)
{
// Open a stream for the selected file.
Windows.Storage.Streams.IRandomAccessStream fileStream
=
await
file.OpenAsync(Windows.Storage.FileAccessMode.Read);
// Set the image source to a bitmap.
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapImage
=
new Windows.UI.Xaml.Media.Imaging.BitmapImage();
bitmapImage.SetSource(fileStream);
displayImage.Source = bitmapImage;
// Set the data context for the page.
this.DataContext = file;
}
}
}
}

Press F5 to build and run the app. Navigate to the photo page, and click the "Get
photo" button to launch theFileOpenPicker and pick a file. Now, when the app is
suspended, terminated, and restored, the image is re-loaded.
Note Review Part 2: Manage app lifecycle and state for instructions on how to
suspend, terminate, and restore an app.

Summary

Congratulations, you're done with the fourth tutorial! You learned how to use file pickers and
data binding in a Windows Store app.

Next steps

In the next part of this tutorial series, you learn how to create a full blog reader app. Go to Part
5: Create a blog reader.

Part
5: Create
a apps
blog reader
(Windows
Store
using
C#/VB
and XAML)
(Windows)
We introduce the essential code and concepts you need to create a Windows Store app using
C# or Visual Basic. You'll use Extensible Application Markup Language (XAML) to define the UI,
and your selected language to write the app logic.
If you'd rather use another programming language, see:

Create your first Windows Store app using JavaScript

Create your first Windows Store app using C++

Roadmap: How does this topic relate to others? See: Roadmap for Windows Store apps using
C# or Visual Basic.

Before you start...

This is the last tutorial in a series. Before you start this tutorial, we recommend that
you read Part 1: Create a "Hello, world!" app, Part 2: Manage app lifecycle and
state, Part 3: Navigation, layout, and views, andPart 4: File access and pickers. This
tutorial introduces new concepts, and adds to concepts from the previous tutorials.

You can complete this tutorial without reading the previous ones. However, we assume
that you understand concepts from previous tutorials and can complete basic tasks in
Microsoft Visual Studio.

We assume you have a basic understanding of XAML and the concepts in the XAML
overview.

We assume 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.

You can see the complete code for this tutorial in Blog reader complete code.

Objectives
In this tutorial, we take a quick tour of the features that you'll use to build Windows Store apps.
Through the process of creating a simple blog reader app, we introduce concepts that are core
to development with XAML, including layout, controls, templates, and data binding. You learn
how to use the page templates and navigation that are built into Microsoft Visual Studio
Express 2012 for Windows 8 to quickly start your app development. You then learn how to use
custom styles to modify the look of the app, and how to adapt the UI to various layouts and
views. Finally, we briefly discuss integrating the app with Windows 8 and publishing it to the
Windows Store. By the time you complete this tutorial, you'll be prepared to start building your
own Windows Store apps.

Hello World

When you create your Windows Store app using C# or Visual Basic, you typically define the UI

using XAML, and write your app logic in an associated code behind file in your selected
language. The XAML UI framework for Windows Store apps using C# or Visual Basic is in the
Windows.UI.Xaml.* namespaces of the Windows Runtime. If you've written apps using Windows
Presentation Foundation (WPF), Microsoft Silverlight, or Silverlight for Windows Phone, you're
already familiar with this programming model and you can use this experience to create your
Windows Store app using C# or Visual Basic.
The example here shows the XAML that defines the UI for a simple "Hello, world" app and its
associated code behind page. Even this simple example shows several concepts that are
important to the XAML-based programming model, including partial classes, layout, controls,
properties, and events.
XAML

<Page
x:Class="WindowsBlogReader.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WindowsBlogReader"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Button Content="Click Me" Click="HelloButton_Click" />
<TextBlock x:Name="DisplayText" FontSize="48" />
</StackPanel>
</Grid>
</Page>
C#
VB

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace WindowsBlogReader
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
}
private void HelloButton_Click(object sender, RoutedEventArgs e)
{
DisplayText.Text = "Hello, world";
}

}
}
A "Hello, world" app is good place to start. But it doesn't take you very far down the road to
profitability, so we'll take a different path as we explore building Windows Store apps. The
sample app that you use to get started is a simple blog reader that downloads and displays
data from a Really Simple Syndication (RSS) 2.0 or Atom 1.0 feed. It seems appropriate to use
the feeds from the Windows team blogs site. When you're done, the app looks like this.

Creating Windows Store apps in Visual Studio


In this section, you will learn how to:

create a new Windows Store app project in Visual Studio Express 2012 for
Windows 8.

Visual Studio is a powerful Integrated Development Environment (IDE) for developing Windows
apps. It provides source file management; integrated build, deployment and launching support;
XAML, Visual Basic, C#, C++, graphics, and manifest editing; debugging, and more. Visual
Studio comes in several editions, but you'll use Visual Studio Express 2012 for Windows 8. You
can download it for free along with the Windows Software Development Kit (SDK) for Windows
8 so that you have everything you need to build, package and deploy your Windows Store
apps.
To get started creating an app, you create a new Windows Store project using C# or Visual
Basic. Visual Studio Express 2012 for Windows 8 includes several templates for Windows
Store projects that give you a head start on apps using a variety of layouts. The Blank App
(XAML) project template provides the minimum files you need for any Windows Store app.
For more info about Visual Studio Express 2012 for Windows 8, see Develop Windows Store
apps using Visual Studio 2012.
To create a new Windows Store project

Open Visual Studio Express 2012 for Windows 8.

Select File > New Project. The New Project dialog opens.

Under Templates in the left pane, expand Visual C# or Visual Basic.

Select the Windows Store template type.

In the center pane, select Blank App (XAML).

Enter a name for the project. Name this project "WindowsBlogReader".


Here's a new project being created in Visual Studio Express 2012 for Windows 8.

Click OK. Your project files are created.

When you create your project, Visual Studio creates the project files and displays them
in Solution Explorer. Let's look at the folders and files that the Blank App (XAML) template
creates.
File Name

Description

Properties/AssemblyInfo (.vb
or .cs)

Contains the name and version metadata that is embedded


into the generated assembly.

Package.appxmanifest

Contains metadata that describes your app, including display


name, description, logos, and capabilities.

Assets/*

The default logo and splash screen images that you can
replace with your own.

Common/StandardStyles.xa
ml

Contains default styles and templates for the app.

App.xaml, App.xaml.cs/vb

These files specify app-level logic. The App class is required to


display the user interface.

MainPage.xaml

The default start page that you use to create the user
interface.

MainPage.xaml.cs/vb

The code-behind file that contains the logic for the default start
page.

To learn more about these files and templates, see Templates to speed up your app
development.

Getting data into an app


In this section, you will learn how to:

create a custom data class

retrieve an RSS or Atom data feed asynchronously.

Before you create the UI for the app, you write the code to get the blog feed data so you have
something to show in the UI. The Windows team blogs expose the full text of the posts in both
RSS and Atom form. The blog data that you want to display in the reader app is the title,
author, date, and content from each of the latest blog posts.
To start, you need to download the data for each of the posts. Fortunately, the Windows
Runtime contains a set of classes that does a lot of the work of processing the feed data for
you. You find these classes in theWindows.Web.Syndication namespace. Its possible to use
these classes directly to show the data in the UI. But in the blog reader, you create your own
data classes. This gives you some additional flexibility and allows you to treat RSS and Atom
feeds in the same way.
You use 3 classes to hold and retrieve the feed data in the blog reader app. You put all 3
classes in one file named FeedData.cs/vb. The FeedData class holds info about the RSS or
Atom feed. The FeedItem class holds info about individual blog posts that the feed contains.
The FeedDataSource class contains a collection of feeds and a method to retrieve the feeds
from the network.
To add data classes to the project

Select Project > Add Class. The New Item dialog box opens.

Enter "FeedData" as the name for the class file.

Click Add. Your new class file is created.

Copy this code into the FeedData.cs/vb file. Replace any code that is in the file.
C#

VB

using
using
using
using
using
using

System;
System.Collections.Generic;
System.Collections.ObjectModel;
System.Linq;
System.Threading.Tasks;
Windows.Web.Syndication;

namespace WindowsBlogReader
{
// FeedData
// Holds info for a single blog feed, including a list of blog posts (FeedItem).
public class FeedData
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime PubDate { get; set; }
private List<FeedItem> _Items = new List<FeedItem>();
public List<FeedItem> Items
{
get
{
return this._Items;
}
}
}
// FeedItem
// Holds info for a single blog post.
public class FeedItem
{
public string Title { get; set; }
public string Author { get; set; }
public string Content { get; set; }
public DateTime PubDate { get; set; }
public Uri Link { get; set; }
}
// FeedDataSource
// Holds a collection of blog feeds (FeedData), and contains methods
needed to
// retreive the feeds.
public class FeedDataSource
{
private ObservableCollection<FeedData> _Feeds = new
ObservableCollection<FeedData>();
public ObservableCollection<FeedData> Feeds
{
get

{
return this._Feeds;
}
}
public async Task GetFeedsAsync()
{
Task<FeedData> feed1 =
GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.asp
x");
Task<FeedData> feed2 =
GetFeedAsync("http://windowsteamblog.com/windows/b/windowsexperience/a
tom.aspx");
Task<FeedData> feed3 =
GetFeedAsync("http://windowsteamblog.com/windows/b/extremewindows/ato
m.aspx");
Task<FeedData> feed4 =
GetFeedAsync("http://windowsteamblog.com/windows/b/business/atom.aspx")
;
Task<FeedData> feed5 =
GetFeedAsync("http://windowsteamblog.com/windows/b/bloggingwindows/ato
m.aspx");
Task<FeedData> feed6 =
GetFeedAsync("http://windowsteamblog.com/windows/b/windowssecurity/ato
m.aspx");
Task<FeedData> feed7 =
GetFeedAsync("http://windowsteamblog.com/windows/b/springboard/atom.asp
x");
Task<FeedData> feed8 =
GetFeedAsync("http://windowsteamblog.com/windows/b/windowshomeserver/
atom.aspx");
// There is no Atom feed for this blog, so use the RSS feed.
Task<FeedData> feed9 =
GetFeedAsync("http://windowsteamblog.com/windows_live/b/windowslive/rss.
aspx");
Task<FeedData> feed10 =
GetFeedAsync("http://windowsteamblog.com/windows_live/b/developer/atom.
aspx");
Task<FeedData> feed11 =
GetFeedAsync("http://windowsteamblog.com/ie/b/ie/atom.aspx");
Task<FeedData> feed12 =

GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wpdev/atom.a
spx");
Task<FeedData> feed13 =
GetFeedAsync("http://windowsteamblog.com/windows_phone/b/wmdev/atom.
aspx");
Task<FeedData> feed14 =
GetFeedAsync("http://windowsteamblog.com/windows_phone/b/windowsphon
e/atom.aspx");
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await
this.Feeds.Add(await

feed1);
feed2);
feed3);
feed4);
feed5);
feed6);
feed7);
feed8);
feed9);
feed10);
feed11);
feed12);
feed13);
feed14);

}
private async Task<FeedData> GetFeedAsync(string feedUriString)
{
Windows.Web.Syndication.SyndicationClient client = new
SyndicationClient();
Uri feedUri = new Uri(feedUriString);
try
{
SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
// This code is executed after RetrieveFeedAsync returns the
SyndicationFeed.
// Process the feed and copy the data you want into the FeedData
and FeedItem classes.
FeedData feedData = new FeedData();
if (feed.Title != null && feed.Title.Text != null)
{
feedData.Title = feed.Title.Text;
}
if (feed.Subtitle != null && feed.Subtitle.Text != null)
{
feedData.Description = feed.Subtitle.Text;

}
if (feed.Items != null && feed.Items.Count > 0)
{
// Use the date of the latest post as the last updated date.
feedData.PubDate = feed.Items[0].PublishedDate.DateTime;
foreach (SyndicationItem item in feed.Items)
{
FeedItem feedItem = new FeedItem();
if (item.Title != null && item.Title.Text != null)
{
feedItem.Title = item.Title.Text;
}
if (item.PublishedDate != null)
{
feedItem.PubDate = item.PublishedDate.DateTime;
}
if (item.Authors != null && item.Authors.Count > 0)
{
feedItem.Author = item.Authors[0].Name.ToString();
}
// Handle the differences between RSS and Atom feeds.
if (feed.SourceFormat == SyndicationFormat.Atom10)
{
if (item.Content != null && item.Content.Text != null)
{
feedItem.Content = item.Content.Text;
}
if (item.Id != null)
{
feedItem.Link = new Uri("http://windowsteamblog.com" +
item.Id);
}
}
else if (feed.SourceFormat == SyndicationFormat.Rss20)
{
if (item.Summary != null && item.Summary.Text != null)
{
feedItem.Content = item.Summary.Text;
}
if (item.Links != null && item.Links.Count > 0)
{
feedItem.Link = item.Links[0].Uri;
}
}
feedData.Items.Add(feedItem);
}
}
return feedData;
}
catch (Exception)

{
return null;
}
}
// Returns the feed that has the specified title.
public static FeedData GetFeed(string title)
{
// Simple linear search is acceptable for small data sets
var _feedDataSource = App.Current.Resources["feedDataSource"] as
FeedDataSource;
var matches = _feedDataSource.Feeds.Where((feed) =>
feed.Title.Equals(title));
if (matches.Count() == 1) return matches.First();
return null;
}
// Returns the post that has the specified title.
public static FeedItem GetItem(string uniqueId)
{
// Simple linear search is acceptable for small data sets
var _feedDataSource = App.Current.Resources["feedDataSource"] as
FeedDataSource;
var _feeds = _feedDataSource.Feeds;
var matches = _feedDataSource.Feeds.SelectMany(group =>
group.Items).Where((item) => item.Title.Equals(uniqueId));
if (matches.Count() == 1) return matches.First();
return null;
}
}
}

Click Build > Build solution to make sure the solution builds without error.

Retrieving the feed data


Let's take a closer look at how you download the blog feeds.
The Windows.Web.Syndication.SyndicationClient class retrieves a fully parsed RSS or
Atom feed, so you can use the data without worrying about parsing XML. To download a feed
using the SyndicationClient class, you have to use the
asynchronous RetrieveFeedAsync method. The asynchronous programming model is
common in the Windows Runtime to help apps remain responsive. Fortunately, much of the
complexity you might expect when using asynchronous methods has been taken care of for
you.

Using await in C# and Visual Basic


Using the await keyword in C# and Visual Basic, the code for retrieving the feed
asynchronously is similar to the code you would use to retrieve the feed synchronously. Let's
take a look.
In the GetFeedsAsync method, you call GetFeedAsync for each of the blog feeds you want
to retrieve. Where possible, you pass in the URL for the Atom feed because it includes author

data that you want to show. If there's no Atom feed, use the RSS feed. When each blog feed is
returned, you add it to the FeedDataSource.Feeds collection.
To do this using synchronous methods, your code might look like this. Here,
the GetFeed method returns a FeedDataobject. When the FeedData is returned, it's added
to the Feeds collection.
C#
VB

public void GetFeeds()


{
FeedData feed1 =
GetFeed("http://windowsteamblog.com/windows/b/developers/atom.aspx");
...
this.Feeds.Add(feed1);
...
}
Now let's look at how you do this using "async" methods, and see how the await keyword
helps. The first thing to notice is that you add the async keyword to the method signature. You
can use the await keyword only in a method that's defined as async. You specify the return
type of GetFeedsAsync as Task.
C#
VB

public async Task GetFeedsAsync()


{
Task<FeedData> feed1 =
GetFeedAsync("http://windowsteamblog.com/windows/b/developers/atom.aspx");
...
this.Feeds.Add(await feed1);
...
}
In your async code, the GetFeedAsync method returns a Task<FeedData>, or Task(Of
FeedData) in VB, that represents the FeedData that will eventually be the return value of the
method.
At this point in the code:
C#
VB

this.Feeds.Add(await feed1);
the call to GetFeedAsync is made, and a Task<FeedData> is returned. Then the next line of
code is executed (to getfeed2), but feed1 is not added to the Feeds collection until
the FeedData object is actually passed to theTask<FeedData> that's waiting for it. We come
back to this shortly. Now let's look at what happens in the GetFeedAsyncmethod.
You specify the return type of GetFeedAsync as Task<FeedData>. This tells the compiler to

generate a Task that represents the FeedData object that the method retrieves.
C#
VB

private async Task<FeedData> GetFeedAsync(string feedUriString)


{
...
}
Inside the method, you instantiate a SyndicationClient and call
its RetrieveFeedAsync method to get theSyndicationFeed that contains the RSS or Atom
info that you want.
C#
VB

Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();


Uri feedUri = new Uri(feedUriString);
...
SyndicationFeed feed = await client.RetrieveFeedAsync(feedUri);
Because RetrieveFeedAsync is an asynchronous method, you use the await keyword again.
The await keyword tells the compiler to do a lot of work for you behind the scenes. The
compiler schedules the rest of the method after this call as a callback to be executed when the
call returns. It then immediately returns control to the calling thread, typically the UI thread, so
that the app remains responsive. The Task<FeedData> that represents the eventual outcome
of this method, a FeedData object, is returned to the caller at this point.
When RetrieveFeedAsync returns the SyndicationFeed with the data you want, the rest of
the code in your method is executed. And, importantly, it's executed in the same thread
context that you made the original call from (the UI thread), so you don't have to worry about
using a dispatcher if you want to update the UI in this code. With
theSyndicationFeed retrieved, you copy the parts you need into
your FeedData and FeedItem data classes.
C#
VB

// This code is executed after RetrieveFeedAsync returns the SyndicationFeed.


// Process the feed and copy the data you want into the FeedData and FeedItem
classes.
FeedData feedData = new FeedData();
if (feed.Title != null && feed.Title.Text != null)
{
feedData.Title = feed.Title.Text;
}
if (feed.Subtitle != null && feed.Subtitle.Text != null)
{
feedData.Description = feed.Subtitle.Text;
}
if (feed.Items != null && feed.Items.Count > 0)

{
// Use the date of the latest post as the last updated date.
feedData.PubDate = feed.Items[0].PublishedDate.DateTime;
foreach (SyndicationItem item in feed.Items)
{
FeedItem feedItem = new FeedItem();
if (item.Title != null && item.Title.Text != null)
{
feedItem.Title = item.Title.Text;
}
if (item.PublishedDate != null)
{
feedItem.PubDate = item.PublishedDate.DateTime;
}
if (item.Authors != null && item.Authors.Count > 0)
{
feedItem.Author = item.Authors[0].Name.ToString();
}
// Handle the differences between RSS and Atom feeds.
if (feed.SourceFormat == SyndicationFormat.Atom10)
{
if (item.Content != null && item.Content.Text != null)
{
feedItem.Content = item.Content.Text;
}
if (item.Id != null)
{
feedItem.Link = new Uri("http://windowsteamblog.com" + item.Id);
}
}
else if (feed.SourceFormat == SyndicationFormat.Rss20)
{
if (item.Summary != null && item.Summary.Text != null)
{
feedItem.Content = item.Summary.Text;
}
if (item.Links != null && item.Links.Count > 0)
{
feedItem.Link = item.Links[0].Uri;
}
}
feedData.Items.Add(feedItem);
}
}
return feedData;
When the code gets to the return statement, it's not actually returning in the sense that a
synchronous method returns. Remember that the method returned to the caller immediately
after the "await" statement. It returned aTask<FeedData> to represent the eventual result of
the method. Here, you finally get the result. The line return feedData;, gives

the FeedData object that is the result of the method to the Task<FeedData> that is waiting
for it.
The Task was awaited at this line in the GetFeedsAsync method.
C#
VB

this.Feeds.Add(await feed1);
When the Task gets the FeedData result that it's waiting for, the code execution proceeds and
the FeedData is added to the FeedDataSource.Feeds collection.

Using the data in the app

To use the data in the app, you create an instance of the data source as a resource in
App.xaml. You name the instancefeedDataSource.
To add a resource to an app

Double-click App.xaml in Solution Explorer. The file opens in the XAML editor.

Add the resource declaration, <local:FeedDataSource


x:Key="feedDataSource"/>, to the rootResourceDictionary, after
the MergedDictionaries collection.

Here's the complete XAML for the Application.Resources section after you add the new
resource.
XAML

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<local:FeedDataSource x:Key="feedDataSource"/>
</ResourceDictionary>
</Application.Resources>
To retrieve the feeds, you add code to the OnLaunched method override in the
App.xaml.cs/vb file. This method is executed each time a user launches the app.
Here, you add the async keyword to the method declaration because you use
the await keyword inside the method. Because the app requires an active internet connection
to download feeds, you use the NetworkInformation class to check for a connection. If the
app is connected, you download the feeds; otherwise, you notify the user. You add code to get
the app's instance of FeedDataSource and check to see if it already contains feeds. If it
doesn't, you call theFeedDataSource.GetFeedsAsync method to retrieve the feeds.
To retrieve the feeds

Double-click App.xaml.cs/vb in Solution Explorer. The file opens in the code editor.

Add the async keyword to the OnLaunched method signature.


C#
VB

protected async override void OnLaunched(LaunchActivatedEventArgs args)

Add this code to the OnLaunched method, immediately after the instantiation of the
new Frame, rootFrame = New Frame().
C#
VB

// Add this code after "rootFrame = new Frame();"


var connectionProfile =
Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionP
rofile();
if (connectionProfile != null)
{
FeedDataSource feedDataSource =
(FeedDataSource)App.Current.Resources["feedDataSource"];
if (feedDataSource != null)
{
if (feedDataSource.Feeds.Count == 0)
{
await feedDataSource.GetFeedsAsync();
}
}
}
else
{
var messageDialog = new Windows.UI.Popups.MessageDialog("An
internet connection is needed to download feeds. Please check your
connection and restart the app.");
var result = messageDialog.ShowAsync();
}
Here's the full code for the OnLaunched method after you add the code.
C#
VB

protected async override void OnLaunched(LaunchActivatedEventArgs args)


{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)

{
// Create a Frame to act as the navigation context and navigate to the first
page
rootFrame = new Frame();
// Add this code after "rootFrame = new Frame();"
var connectionProfile =
Windows.Networking.Connectivity.NetworkInformation.GetInternetConnectionProfile();
if (connectionProfile != null)
{
FeedDataSource feedDataSource =
(FeedDataSource)App.Current.Resources["feedDataSource"];
if (feedDataSource != null)
{
if (feedDataSource.Feeds.Count == 0)
{
await feedDataSource.GetFeedsAsync();
}
}
}
else
{
var messageDialog = new Windows.UI.Popups.MessageDialog("An
internet connection is needed to download feeds. Please check your connection and
restart the app.");
var result = messageDialog.ShowAsync();
}
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}

You can build and run the app in debugging mode to make sure it builds and retrieves the
feeds without error. If there are no errors, the app runs, but only shows a black screen. If there
are errors, Visual Studio shows info about the error. To learn more about running apps in Visual
Studio, see Running Windows Store apps from Visual Studio.
To run the app in debugging mode

To run the app, do one of these:

Click Debug > Start debugging.

Press F5.

To stop debugging:
1.

Press Alt+Tab to return to Visual Studio.

2.

In Visual Studio, do one of these.

Click Debug > Stop debugging.

Press Shift+F5.

Now you create the UI to show the data.

Adding pages and navigation


To show the Windows team blogs, you must add pages to the app and handle navigation
between these pages. First, you want a page that lists all of the Windows team blogs. When a
reader picks a blog from this page, you navigate to a new page and load the list of posts for
that blog. You also add a detail page so a user can read individual blog posts without the list
view taking up space.

Page templates
Fortunately, you don't have to create each page from a blank template. Visual Studio
Express 2012 for Windows 8 ships with a collection of page templates that are useful for a
variety of situations. Here are the available page templates.
Page Type

Description

Group Detail
Page

Displays details for a single group and previews for each item in the group.

Grouped Items
Page

Displays grouped collections.

Item Detail Page

Displays one item in detail, and enables navigation to adjacent items.

Items Page

Displays a collection of items.

Split Page

Displays a list of items and details for the selected item.

Basic Page

An empty page that can adapt to different orientations and views, and has
a title and back button.

Blank Page

A blank page for a Windows Store app.

You use the Items Page template to show the list of Windows team blogs. You use the Split
Page template to show the posts for each blog, and the text of the selected post. You use
the Basic Page template for the detail page.
To add pages to the app

Select Project > Add New Item. The Add New Item dialog opens.
Here's the Add New Item dialog.

Under Visual C# or Visual Basic in the left pane, pick the Windows Store template
type.

In the center pane, select the type of page to add to your project. Select the Items
Page template.

Enter a name for the page. Enter "ItemsPage.xaml".

Click Add.
The first time you add a new page to the Blank App template (other than a Blank
Page), Visual Studio shows a dialog with a message that you need to add files that are
missing from your project. Click Yes to add these files. Files for several utility classes
are added to your project in the Common folder.
The XAML and code behind files for your page are added to the project.

Click Build > Build solution to build the app. The new page will show an error in the
designer until you build the helper classes it depends on.

Repeat steps 1-5 to add a split page.

In step 3, select the Split Page template.

In step 4, name the page, "SplitPage.xaml".

Repeat steps 1-5 to add a basic page.

In step 3, select the Basic Page template.

In step 4, name the page, "DetailPage.xaml".

When you add the page templates to your project and look at the XAML and code behind, it's
apparent that these page templates do a lot of work for you. In fact, it's easy to get lost, so
let's take a closer look at the page templates and see what's in them. All the XAML page
templates for Windows Store apps have the same format.
The XAML for the page templates has 3 main sections:
Resources

Styles and data templates for the page are defined in the Resources section.
We talk more about this in the Creating a consistent look with styles section.

App
Content

The controls and content that make up the app UI are defined within the root
layout panel.

Visual State
Manager

Animations and transitions that adapt the app to different layouts and
orientations are defined in theVisualStateManager section. We talk more
about this in the Adapting to different layouts section.

The template pages you use are all derived from the LayoutAwarePage class and can do
much more by default than theBlank Page that's used for the MainPage.xaml in a Blank
app. LayoutAwarePage is an implementation of Page that enables important functionality for
Windows Store app development:

The mapping of application view state to visual state lets the page adapt to different
resolutions, orientations, and views.

GoBack and GoHome event handlers support basic navigation.

A default view model gives you a simple bindable data source.

SaveState and LoadState methods work with the SuspensionManager class to


manage app session state.

The page templates also use styles and templates found in StandardStyles.xaml that apply the
design guidelines for Windows Store apps. You'll use some of these styles as a starting point
and modify copies of them to customize the look of the app.

Navigating between pages


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 pass data between pages as you navigate.

Navigating to ItemsPage
In the Visual Studio project templates, a Frame named rootFrame is set as the content of the
app window. This Framehosts all the Pages in the app. Let's look at the relevant code in
App.xaml.cs/vb.
C#
VB

protected async override void OnLaunched(LaunchActivatedEventArgs args)


{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first
page
rootFrame = new Frame();
...
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation

// parameter
if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}
This code gets an existing Frame if there is one; otherwise, it creates a new one and sets it as
the window's content. It then navigates to MainPage. Because you want the first page in the
app to be ItemsPage, you change the call to theNavigate method and pass in ItemsPage as
the Page to navigate to.
To navigate to ItemsPage

Double-click App.xaml.cs/vb in Solution Explorer. The file opens in the code editor.

In the OnLaunched method, update the call to rootFrame.Navigate and


pass ItemsPage as the first parameter as shown here.
C#
VB

if (!rootFrame.Navigate(typeof(ItemsPage), args.Arguments))
{
throw new Exception("Failed to create initial page");
}

Press F5 to build and run the app. Now the ItemsPage is loaded instead of the default
MainPage.

Note The default MainPage.xaml file is no longer needed in this project, and you can
safely delete it.
In the items page, you don't see any content yet because you haven't connected any data to
the UI. You do that now.

Loading ItemsPage
When ItemsPage is loaded, you need to get the app's instance of the data source and hook it
up to the UI. For pages that are derived from LayoutAwarePage, you can hook up your data
to the DefaultViewModel provided by LayoutAwarePage. You do this in
the LoadState method override.
To load data in the items page

Double-click ItemPage.xaml.cs/vb in Solution Explorer to open it.

Add this code to the LoadState method.


C#

VB

FeedDataSource feedDataSource =
(FeedDataSource)App.Current.Resources["feedDataSource"];
if (feedDataSource != null)
{
this.DefaultViewModel["Items"] = feedDataSource.Feeds;
}

Press F5 to build and run the app.

Now the ItemsPage is loaded and shows a grid of all the blogs. It looks something like this,
but the items might be arranged differently depending on your screen resolution.

Navigating to SplitPage
When the user picks a blog from the collection, you navigate from the items page to the split
page . To do this navigation, you want the GridView items to respond to a click like a button,
instead of being selected. To make theGridView items clickable, you set
the SelectionMode and IsItemClickEnabled properties as shown here. You then add a
handler for GridView's ItemClick event.
To navigate to SplitPage

Double-click ItemsPage.xaml in Solution Explorer to open it.

Select the GridView control named itemGridView.

In the Properties panel, expand the Common section, then click the down arrow at
the bottom of the section to expand the advanced properties.

Check the box for the IsItemClickEnabled property. This sets the property to true.

Add a handler for the ItemClick event.

In the Properties panel, click the Events button (

).

Find the ItemClick event in the event list. In the text box for the event, type
"ItemView_ItemClick" for the name of the method that handles
the ItemClick 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 ItemView_ItemClick event handler in the code behind
page.
Here, you navigate to the split page and pass the title of the selected feed.
C#
VB

// Navigate to the split page, configuring the new page


// by passing the title of the clicked item as a navigation
parameter

if (e.ClickedItem != null)
{
string title = ((FeedData)e.ClickedItem).Title;
this.Frame.Navigate(typeof(SplitPage), title);
}

In ItemsPage.xaml, select the ListView control named itemListView.

In the Properties Window, click the Properties button (

Repeat steps 4-5.3 for the itemListView control.

).

The itemListView list is shown in place of the grid when the app is Snapped. We talk more
about this in the sectionAdapting to different layouts. For now, you just make the same
changes to the ListView that you made to the GridViewso they have the same behavior.
To navigate between pages, you use the Frame control's Navigate, GoForward,
and GoBack methods. To navigate back, the Visual Studio page templates include a Back
button. The handler for the BackButton's Click event calls theFrame.GoBack method.
The Navigate(TypeName, Object) method lets you navigate and pass a data object to the
new page. You use this method to pass data between your pages. The first
parameter, typeof(SplitPage), is the Type of the page that you are navigating to. The
second parameter is the data object that you pass to the page you're navigating to. In this
case, you pass the title of the clicked item.
You could pass your custom data objects as navigation parameters, but they won't be persisted
and will even cause an exception when you save the app's session state using
the SuspensionManager class. In order to save the navigation state of the app
using SuspensionManager, you must pass only basic, serializable types as the navigation
parameter. That's why you pass the title of the item, and have a method in
the FeedDataSource class to get the item from the title.
Before you move on to the split page, you need to make one more change to the items page.
The default page title is "My Application". You change this to "Windows Team Blogs".
To change the page title

Double-click ItemsPage.xaml in Solution Explorer to open it.

Select the TextBlock named pageTitle.

In the Properties Window, click the Properties button (

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 "Windows
Team Blogs".

Click OK.

In ItemsPage.xaml, the page title is bound to a static resource with the key AppName. The text
in this resource is updated to "Windows Team Blogs", and the XAML now looks like this.

XAML

<x:String x:Key="AppName">Windows Team Blogs</x:String>


Press F5 to build and run the app. Now when you click an item the split page is loaded. But the
split page is still blank because you haven't connected it to the data yet.

Loading SplitPage
In the SplitPage.xaml.cs/vb code behind page, you need to do something with the object that
was just passed from the items page. For this, you again override the LoadState method. This
method is already added in the page template code, so you just need to modify it to hook up
your data. The navigationParameter has the data object that was passed from the items
page. You cast this back to a string, and then pass it as the parameter to
the FeedDataSource.GetFeedmethod. You add the returned feed data
to DefaultViewModel with the key Feed, and add the FeedData.Items property
to DefaultViewModel with the key Items.
To load data in the split page

Double-click SplitPage.xaml.cs/vb in Solution Explorer to open it in the code editor.

Add this code to the top of the LoadState method, after the "TODO" comments.
Tip Expand the "Page state management" region to see the LoadState method.
C#
VB

// TODO: Assign a bindable group to this.DefaultViewModel["Group"]


// TODO: Assign a collection of bindable items to
this.DefaultViewModel["Items"]
string feedTitle = (string)navigationParameter;
FeedData feedData = FeedDataSource.GetFeed(feedTitle);
if (feedData != null)
{
this.DefaultViewModel["Feed"] = feedData;
this.DefaultViewModel["Items"] = feedData.Items;
}
Here's the updated LoadState method.
C#
VB

protected override void LoadState(Object navigationParameter,


Dictionary<String, Object> pageState)
{
// TODO: Assign a bindable group to this.DefaultViewModel["Group"]
// TODO: Assign a collection of bindable items to
this.DefaultViewModel["Items"]
string feedTitle = (string)navigationParameter;
FeedData feedData = FeedDataSource.GetFeed(feedTitle);
if (feedData != null)
{

this.DefaultViewModel["Feed"] = feedData;
this.DefaultViewModel["Items"] = feedData.Items;
}
if (pageState == null)
{
// When this is a new page, select the first item automatically unless logical
page
// navigation is being used (see the logical page navigation #region below.)
if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View !=
null)
{
this.itemsViewSource.View.MoveCurrentToFirst();
}
}
else
{
// Restore the previously saved state associated with this page
if (pageState.ContainsKey("SelectedItem") && this.itemsViewSource.View !
= null)
{
// TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with the
selected
//

item as specified by the value of pageState["SelectedItem"]

}
}
}
Press F5 to build and run the app. Now when you navigate to the split page, the data is
displayed and you can select from the list of blog posts. But the page title is still blank. You'll
fix that now.
In the Visual Studio page template, the "TODO" comments indicate where you add your data
object to DefaultViewModelwith the key Group.
C#
VB

// TODO: Assign a bindable group to this.DefaultViewModel["Group"]


...
this.DefaultViewModel["Feed"] = feedData;

You can think of a blog feed as a group of blog posts, but it makes the code easier to read if
you use the key Feed in place of Group. Because you used the key Feed instead, you need to
change the binding in the page title to bind to the Feed property instead of Group. You also
make the title span 2 columns so it's not cut off.
To update the page title

Double-click SplitPage.xaml in Solution Explorer to open it.

Select the Grid named titlePanel.

Under Layout in the Properties panel, set the ColumnSpan property to "2" and
press Enter.
Note At the default width of the Properties panel, the ColumnSpan property is
shown as Colum....
The XAML is updated as shown here.
XAML

<!-- Back button and page title -->


<Grid x:Name="titlePanel" Grid.ColumnSpan="2">

Select the TextBlock named pageTitle.

Under Common in the Properties panel, click the property marker for
the Text property. The property menu opens.
Note The Text property marker is orange to indicate that it's set to a binding.

In the property menu, select Create Data Binding.... The Create Data
Binding dialog opens.

In the Create Data Binding dialog, change the value in the Path text box to
"Feed.Title" and click OK.
The XAML for the TextBlock is updated like this.
XAML

<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{Binding Feed.Title}"


Style="{StaticResource PageHeaderTextStyle}"/>

Press F5 to build and run the app. Now when you navigate to the split page, the page
title is shown.

Add the WebView


By default, the split page template shows the details for the selected item in a TextBlock.
However, the string that contains the post content is not plain text, but a string of HTML. When
you show the string in a TextBlock, you see a bunch of HTML tags, which is not what you
want. Instead, you use a WebView control to display the HTML. You also change the layout
used to show the title and content of the selected blog post.
To add the web view

In SplitPage.xaml, delete the ScrollViewer named itemDetail and all of its contents.

In the XAML editor, add this XAML in place of the itemDetail ScrollViewer you
deleted.
XAML

<!-- Details for selected item -->


<ScrollViewer
x:Name="itemDetail"
AutomationProperties.AutomationId="ItemDetailScrollViewer"

Grid.Column="1"
Grid.Row="1"
Padding="70,0,120,0"
DataContext="{Binding SelectedItem, ElementName=itemListView}"
Style="{StaticResource VerticalScrollViewerStyle}">
<Grid x:Name="itemDetailGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="itemTitle" Text="{Binding Title}"
Style="{StaticResource SubheaderTextStyle}"/>
<Border x:Name="contentViewBorder" BorderBrush="Gray"
BorderThickness="2"
Grid.Row="1" Margin="0,15,0,20">
<Grid>
<WebView x:Name="contentView" />
<Rectangle x:Name="contentViewRect" />
</Grid>
</Border>
</Grid>
</ScrollViewer>
The WebView control gives you a way to host HTML data within your app. But if you look at
its Source property, you see that it takes the Uri of the web page to display. Your HTML data is
just a string of HTML. It doesn't have a Uri that you can bind to the Source property. Luckily,
there is a NavigateToString method that you can pass your string of HTML to.
Whenever you use a WebView control to view content that might not be available, handle any
failures that occur.
Here, you handle the NavigationFailed event to show the error message in
the WebView control if the navigation fails.
To handle navigation errors

Select the WebView named contentView that you added in the previous step.

In the Properties Window, click the Events button (

Find the NavigationFailed event in the event list. In the text box for the event, type
"ContentView_NavigationFailed" for the name of the method that handles
the NavigationFailed 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 ContentView_NavigationFailed event handler in the code


behind page.
C#
VB

).

string errorString = "<p>Page could not be loaded.</p><p>Error is: "


+ e.WebErrorStatus.ToString() + "</p>";
this.contentView.NavigateToString(errorString);
To populate the WebView, you add your code to
the ItemListView_SelectionChanged event handler. In the event handler, you cast the
selected item to a FeedItem and get the string of HTML from the Content property. You then
pass the string to the NavigateToString method. If no item is selected, you clear
the WebView by passing an empty string.
To populate the web view

Double-click SplitPage.xaml.cs/vb in Solution Explorer. The file opens in the code


editor.

Add this code to the end of the ItemListView_SelectionChanged method to


populate the WebView with the content of the selected blog post.
Note Expand the "Logical page navigation" region to see
the ItemListView_SelectionChanged method.
C#
VB

// Add this code to populate the web view


// with the content of the selected blog post.
Selector list = sender as Selector;
FeedItem selectedItem = list.SelectedItem as FeedItem;
if (selectedItem != null)
{
this.contentView.NavigateToString(selectedItem.Content);
}
else
{
this.contentView.NavigateToString("");
}

Press F5 to build and run the app.

The split page is looking better now, and shows the selected blog post in a more readable
format.

Load DetailPage
Now you add content to the detail page. In DetailPage.xaml, you need to bind the
title TextBlock to the blog post title and add a WebView control to show the blog page.
To update the detail page

Double-click DetailPage.xaml in Solution Explorer to open it.

Bind the page title TextBlock to the Title property of the selected blog post.

Select the TextBlock named pageTitle.

In the Properties Window, click the Properties button (

).

Under Common in the Properties panel, click the property marker for
the Text property. The property menu opens.

In the property menu, select Create Data Binding.... The Create Data
Binding dialog opens.

In the Create Data Binding dialog, select Data context in the Binding
type drop-down list.

Enter "Title" in the Path text box then click OK.


Note The message in the Create Data Binding dialog says the data context
is not set. That's okay because you set the data context in code when the you
run the app.

In the XAML editor, add this XAML after the Grid that has the page title, and before
theVisualStateManager.VisualStateGroups section.
XAML

<Border x:Name="contentViewBorder" BorderBrush="Gray"


BorderThickness="2"
Grid.Row="1" Margin="120,15,20,20">
<WebView x:Name="contentView"
NavigationFailed="ContentView_NavigationFailed"/>
</Border>

Double-click DetailPage.xaml.cs/vb in Solution Explorer to open it.

Add this code to the LoadState method override.


This code navigates the WebView to the Uniform Resource Identifier (URI) of the blog
post and sets theDataContext of the page.
C#
VB

// Add this code to navigate the web view to the selected blog post.
string itemTitle = (string)navigationParameter;
FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
if (feedItem != null)
{
this.contentView.Navigate(feedItem.Link);
this.DataContext = feedItem;
}

Add this code to the DetailPage class to handle


the WebView.NavigationFailed event.

C#
VB

private void ContentView_NavigationFailed(object sender,


WebViewNavigationFailedEventArgs e)
{
string errorString = "<p>Page could not be loaded.</p><p>Error is: "
+ e.WebErrorStatus.ToString() + "</p>";
this.contentView.NavigateToString(errorString);
}

Press F5 to build and run the app.


All the data is hooked up now, but there's no way to navigate to the details page you
created. You add navigation to the detail page next.

Adding an app bar

Most of the navigation in the blog reader app happens when the user picks an item in the UI.
But on the split page, you must provide a way for the user to go to the detail view of the blog
post. You could put a button somewhere on the page, but that would distract from the core app
experience, which is reading. Instead, you put the button in an app bar that's hidden until the
user needs it.
An app bar is a piece of UI that is hidden by default, and is shown or dismissed when the user
swipes from the edge of the screen or interacts with the app. It presents navigation,
commands, and tools to the user. An app bar can appear at the top of the page, at the bottom
of the page, or both. We recommend that you put navigation in the top app bar, and tools and
commands in the bottom app bar. You can control how and when the app bar is shown and
dismissed by setting the IsSticky and IsOpen properties. You can also respond to the app bar
being opened or dismissed by handling the Opened and Closed events.
To add an app bar in XAML, you assign an AppBar control to
a Page's TopAppBar or BottomAppBar property. You'll add a top app bar with a button to
navigate to the detail page. The StandardStyles.xaml file contains a variety of app bar button
styles for common scenarios. You use these styles as a guide to create a style for your button.
You put your style in the Page.Resources section of SplitPage.xaml, and add
the Page.TopAppBar XAML just after the resources section.
To add an app bar

Double-click SplitPage.xaml in Solution Explorer to open it.

In the XAML editor, add this XAML in the Page.Resources section near the top of the
page.
This adds the Style resource for the app bar button. We talk more about styles later in
the section Creating a consistent look with styles.
XAML

<Style x:Key="WebViewAppBarButtonStyle" TargetType="Button"


BasedOn="{StaticResource AppBarButtonStyle}">
<Setter Property="AutomationProperties.AutomationId"
Value="WebViewAppBarButton"/>
<Setter Property="AutomationProperties.Name" Value="View Web

Page"/>
<Setter Property="Content" Value="&#xE12B;"/>
</Style>

Add this XAML after the Page.Resources section of the page.


This adds an AppBar control to the TopAppBar property of the page.
XAML

<Page.TopAppBar>
<AppBar Padding="10,0,10,0">
<Grid>
<Button HorizontalAlignment="Right"
Style="{StaticResource WebViewAppBarButtonStyle}"/>
</Grid>
</AppBar>
</Page.TopAppBar>

Select the Button in the app bar you just added.

In the Properties Window, click the Events button (

Find the Click event at the top of the event list. In the text box for the event, enter
"ViewDetail_Click" for the name of the method 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 method to handle navigation to the detail page.

).

C#
VB

FeedItem selectedItem = this.itemListView.SelectedItem as FeedItem;


if (selectedItem != null && this.Frame != null)
{
string itemTitle = selectedItem.Title;
this.Frame.Navigate(typeof(DetailPage), itemTitle);
}

Press F5 to build and run the app. Click a blog to navigate to the split page, and select
a blog post to read. Right-click the page header to show the app bar, and click
the Show Web View button to navigate to the detail page.

Adding animations and transitions

When we talk about animations, we often think of objects bouncing around on the screen. But
in XAML, an animation is essentially just a way to change the value of a property on an object.
This makes animations useful for a lot more than just bouncing balls. In the blog reader app,
you use animations to adapt your UI to different layouts and orientations. You take a closer
look at this in the next section, but first, you need to understand how animations work.
To use an animation, you put it inside of a Storyboard. When the Storyboard runs, the
property changes as specified by the animation. A Storyboard can have one or many
animations in it. Each animation specifies a target object, a property to change on that object,
and a new value for the property.
For example, in the blog reader app, you have a ListView named itemListView. Here's an
animation that changes theVisibility property of itemListView to Visible when
the Storyboard runs.
XAML

<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>

Adding theme animations


Run the app again, and notice how UI elements slide in smoothly when a page loads. Except
for the WebView control you added. It just shows up. Windows 8 uses animations and
transitions to enhance the user experience throughout the UI. You want to have the same
experience in your app to match the personality of Windows 8. Fortunately, you can use built
in theme animations and theme transitions in your app to match the ones used in Windows 8.
You find these in the Windows.UI.Xaml.Media.Animation namespace.
A theme animation is a pre-configured animation that you can put inside a Storyboard.
The PopInThemeAnimationmakes the web view slide in from right to left when the page
loads. Increasing the value of the FromHorizontalOffsetproperty makes the effect more
extreme. Here, you put the PopInThemeAnimation in a Storyboard and make it a resource
in DetailPage.xaml. Set the target of the animation to be the Border that surrounds your web
content. This animates the Border and everything in it.
To add a theme resource

Double-click DetailPage.xaml in Solution Explorer to open it.

In the XAML editor, add this XAML to the Page.Resources section.


XAML

<Storyboard x:Name="PopInStoryboard">
<PopInThemeAnimation Storyboard.TargetName="contentViewBorder"
FromHorizontalOffset="400"/>
</Storyboard>

In the code behind page, you start the Storyboard in the LoadState method so that the pop-

in animation is applied to the Border when the user navigates to the detail page.
To start an animation storyboard

Double-click DetailPage.xaml.cs/vb in Solution Explorer to open it.

Add this code at the beginning of the LoadState method.


C#
VB

// Run the PopInThemeAnimation


Windows.UI.Xaml.Media.Animation.Storyboard sb =
this.FindName("PopInStoryboard") as
Windows.UI.Xaml.Media.Animation.Storyboard;
if (sb != null) sb.Begin();

Press F5 to build and run the app. Navigate to the detail page. Now
the WebView control slides in with the other UI elements when the split page is
loaded.

Here's the updated code for the LoadState method.


C#
VB

protected override void LoadState(Object navigationParameter,


Dictionary<String, Object> pageState)
{
// Run the PopInThemeAnimation
Windows.UI.Xaml.Media.Animation.Storyboard sb =
this.FindName("PopInStoryboard") as
Windows.UI.Xaml.Media.Animation.Storyboard;
if (sb != null) sb.Begin();
// Add this code to navigate the web view to the selected blog post.
string itemTitle = (string)navigationParameter;
FeedItem feedItem = FeedDataSource.GetItem(itemTitle);
if (feedItem != null)
{
this.contentView.Navigate(feedItem.Link);
this.DataContext = feedItem;
}
}
You can also follow these steps and use the same code to add this animation to
the contentViewBorder element in SplitPage.
For more info, and a full list of theme animations and transitions, see QuickStart: Animations.

Creating a consistent look with styles

You want to make the blog reader app look and feel like the Windows team blogs website. You

want your users to have a seamless experience when they move between the website and the
app. The default dark theme for the project doesn't match very well with the Windows team
blogs website. This is most clear on the detail page, where you load the actual blog page into
a WebView, as shown here:
To give the app a consistent appearance that you can update as needed, you use brushes and
styles. A Brush lets you define a look in one place and use it wherever you need it.
A Style lets you set values for a control's properties and reuse those settings across your app.
Before we get into the details, let's look at how you use a brush to set the background color of
the pages in your app. Each page in your app has a root Grid with a Background property set
to define the page's background color. You could set each page's background individually, like
this.
XAML

<Grid Background="Blue">
A better way is to define a Brush as a resource and use it to define the background color of all
of your pages. You define objects and values as resources to make them reusable. To use an
object or value as a resource, you must set its x:Keyattribute. You use this key to refer to the
resource from your XAML. Here, the background is set to a resource with the
key ApplicationPageBackgroundThemeBrush, which is a system
defined SolidColorBrush.
XAML

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">


This is fine to set the Background property of the Grid, but you typically need to set more
than one property to get the look you want. You can group settings for any number of
properties together is a Style, and apply the Style to the control.
You can define resources in an individual page's XAML file, in the App.xaml file, or in a separate
resource dictionary XAML file, like StandardStyles.xaml. Where the resource is defined
determines the scope in which it can be used. Visual Studio creates the StandardStyles.xaml
file as part of the project template and puts it in the Common folder. It's a resource dictionary
that contains the values, styles, and data templates used in the Visual Studio page templates.
A resource dictionary XAML file can be shared across apps, and more than one resource
dictionary can be merged in a single app.
In the blog reader app, you define resources in App.xaml to make them available across the
entire app. And you have some resources defined in the XAML file for individual pages. These
resources are available only in the page where they are defined. If resources with the same key
are defined in both App.xaml and in a page, the resource in the page overrides the resource in
App.xaml. In the same way, a resource defined in App.xaml will override a resource defined
with the same key in a separate resource dictionary file. For more info, see Quickstart: Styling
controls.
Now let's look at an example of using Styles in the app. The look of the template pages is
defined by a style with the keyLayoutRootStyle. The Style definition is in the
StandardStyles.xaml file.
XAML

<Grid Style="{StaticResource LayoutRootStyle}">

XAML

<!-- Page layout roots typically use entrance animations


and a theme-appropriate background color -->
<Style x:Key="LayoutRootStyle" TargetType="Panel">
<Setter Property="Background"
Value="{StaticResource ApplicationPageBackgroundThemeBrush}"/>
<Setter Property="ChildrenTransitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
In the Style definition, you need a TargetType attribute and a collection of one or
more Setters. You set theTargetType to a string that specifies the type that the Style is
applied to, in this case, a Panel. If you try to apply a Styleto a control that doesn't match
the TargetType attribute, an exception occurs. Each Setter element requires a Propertyand
a Value. These property settings indicate what control property the setting applies to, and the
value to set for that property.
To change the Background of your pages, you need to replace
the ApplicationPageBackgroundThemeBrush with your own custom brush. For your
custom brush, you use the Color #FF0A2562, which is a nice blue that fits with the colors on
the http://windowsteamblog.com site. To replace the system theme brush, you create a
new Style that is based onLayoutRootStyle, and change the Background property there.
Here, you define a new style for the layout root.
To change the page background

Double-click App.xaml in Solution Explorer to open it.

In the XAML editor, add these brush and style definitions in


the ResourceDictionary with your other app specific resources, after
the feedDataSource resource.
XAML

<SolidColorBrush x:Key="WindowsBlogBackgroundBrush"
Color="#FF0A2562"/>
<Style x:Key="WindowsBlogLayoutRootStyle"
TargetType="Panel"
BasedOn="{StaticResource LayoutRootStyle}">
<Setter Property="Background"
Value="{StaticResource
WindowsBlogBackgroundBrush}"/>
</Style>

Here's the full XAML for the ResourceDictionary section of App.xaml.


XAML

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/StandardStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<local:FeedDataSource x:Key="feedDataSource"/>
<SolidColorBrush x:Key="WindowsBlogBackgroundBrush"
Color="#FF0A2562"/>
<Style x:Key="WindowsBlogLayoutRootStyle"
TargetType="Panel"
BasedOn="{StaticResource LayoutRootStyle}">
<Setter Property="Background"
Value="{StaticResource WindowsBlogBackgroundBrush}"/>
</Style>
</ResourceDictionary>
</Application.Resources>
Important Because you based a style on a system style in StandardStyles.xaml,
the ResourceDictionary that includes StandardStyles.xaml has to be declared in the XAML
before your style that's based on it. If it's not, the XAML parser can't find
the LayoutRootStyle that your style is based on.
The line BasedOn="{StaticResource LayoutRootStyle}" tells your new Style to inherit
from LayoutRootStyle any properties that you don't explicitly set. Your new Style is just like
the default style, but with a blue background, and you can use it for all of your pages.
To change the background of each page

Double-click ItemsPage.xaml in Solution Explorer to open it.

Select the page's root layout Grid.

Under Miscellaneous in the Properties panel, find the Style property.

Click the property marker next to the Style property to open the menu.

In the menu, select Local Resource > WindowsBlogLayoutRootStyle.

Repeat steps 2-5 for SplitPage.xaml and DetailPage.xaml.


The XAML for the root Grid in each page now looks like this.
XAML

<Grid Style="{StaticResource WindowsBlogLayoutRootStyle}">

Press F5 to build and run the app, and see the blue pages.

To give the app the look and feel of the Windows team blogs website, you also use custom data
templates in addition toBrushes and Styles. Let's start by using templates to format the list
items in the split page.

Formatting data with a data template


In SplitPage.xaml, the look of the items in itemListView is defined in the
Standard130ItemTemplate, which is in StandardStyles.xaml. The item template is assigned in
this line of XAML: ItemTemplate="{StaticResource Standard130ItemTemplate}". To
see the effect of this template, you can remove it and see what the list looks like without it.
You have the ListView bound to the Items property of the FeedData object, so the correct
data is there. But when you run the app like this, the ListView doesn't know what to show, so
it just calls ToString on the object it's bound to. That gives you a list of
"WindowsBlogReader.FeedItem" strings like you saw previously. Clearly, this is not what
you want to show.
You can make it a little better by setting the DisplayMemberPath property on the ListView.
This tells the list view to callToString on the specified property of the bound object, instead of
on the object itself. If you setDisplayMemberPath=Title, the ListView shows a list of blog
post titles.
Here's the ListView XAML with the DisplayMemberPath set to the Title property.
XAML

<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemsListView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.Row="1"
Margin="-10,-10,0,0"
Padding="120,0,0,60"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
IsSwipeEnabled="False"
SelectionChanged="ItemListView_SelectionChanged"
DisplayMemberPath="Title"/>
When you run the app, the list items look like this. This is closer to what you want to show.
But what you really want is to show the title, author, and published date for each post in the
list. To show more than one property of the data item, you define a template that tells
the ListView exactly how you want the data displayed. The controls for viewing collections of
data items are derived from the ItemsControl class. These controls have
anItemTemplate property that you can assign a DataTemplate to.
The DataTemplate defines how your data looks.
Important You can't use the DisplayMemberPath and an ItemTemplate at the same time.
When you set theItemTemplate property, be sure to remove
the DisplayMemberPath setting.
The default item template is close to what you want to show. Lets use it as the starting point
for your template.

To create a new ItemTemplate

In Solution Explorer, open SplitPage.xaml.

Select the ListView named "itemListView".

Under Miscellaneous in the Properties panel, click the property marker for
the ItemTemplate property. The property menu opens.
Note The property marker is the small box symbol to the right of each property value.
The ItemTemplateproperty marker is green to indicate that it's set to a resource.

In the property menu, select Convert to New Resource.... The Create


DataTemplate Resource dialog opens.

In the Create DataTemplate Resource dialog, enter "DefaultListItemTemplate" in


the Name (Key) text box.
Make sure the Define in setting is set to This document >
"LayoutAwarePage:pageRoot".
Note The XAML page Design view must be showing in Visual Studio. If only the XAML
editor is showing, some options are disabled.

Click OK.

A new DataTemplate is created in the Resources section of SplitPage.xaml. This is a


copy of theStandard130ItemTemplate resource that you can modify.
The ItemTemplate property of itemListView is also updated to
use DefaultListItemTemplate.
Defining the bit of UI inside the DataTemplate is just like defining any other UI. This template
has a Grid with 2 columns. The first column has a square border with a placeholder image. The
second column has a StackPanel with 3 TextBlocks stacked on top of each other. By default,
the Text properties of the TextBlocks are bound to properties of the sample data source used
in the Visual Studio templates. The default DataContext for these bindings is the object
displayed in theListView, which is a FeedItem. So you can update the bindings to show
the Title, Author, and PubDate properties of theFeedItem.
Heres the XAML for the data template with the updated bindings.
XAML

<DataTemplate x:Key="DefaultListItemTemplate">
<Grid Height="110" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource
ListViewItemPlaceholderBackgroundThemeBrush}"
Width="110" Height="110">
<Image Source="{Binding Image}" Stretch="UniformToFill"
AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top"
Margin="10,0,0,0">
<TextBlock Text="{Binding Title}"
Style="{StaticResource TitleTextStyle}"
TextWrapping="NoWrap"/>

<TextBlock Text="{Binding Author}"


Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding PubDate}"
Style="{StaticResource BodyTextStyle}" MaxHeight="60"/>
</StackPanel>
</Grid>
</DataTemplate>
Here's what the list looks like when you run the app.
Now the list shows the data you want, but it doesn't reflect the branding of the Windows team
blog website, as you see here.
To make the list view look more like the web site, you use
a ContentControl and ControlTemplate to show the date in a green block, and update the
look of the title TextBlock to show the titles in orange. You also use a value converter to
format the date the way you want it.

Formatting data with a value converter


In ItemListView's DataTemplate, you bind the PubDate property, which is a DateTime, to
a TextBlock.Text property. The binding engine automatically converts PubDate from
a DateTime to a string. But the automatic conversion shows both the date and the time, and
you want to show only the date. To fix this, you can create your own value converter that
converts a DateTime to a string, and in it you can format the string however you want to.
To create a value converter, you create a class that implements
the IValueConverter interface and then implement theConvert and ConvertBack methods.
Converters can change data from one type to another, translate data based on cultural info, or
modify other aspects of the presentation.
The Convert and ConvertBack methods also let you pass in a parameter so that you can use
the same instance of the converter with different options. In this example, you have a
formatting converter that produces different formats of the date based on the input parameter.
You can use the ConverterParameter of the Binding class to pass a parameter as an
argument into the Convert and ConvertBack methods. you use this feature to format the
date to show it in the block format used on the blog web site.
Here, you create a date converter that converts the date value passed in and formats it so that
it shows only the day, the month, and the year.
To add a value converter

Select Project > Add Class. The New Item dialog box opens.

Enter DateConverter as the name for the class file.

Click Add. The DateConverter.cs/vb class file is created.

Copy this code into the DateConverter.cs/vb file. Replace any code that's in the file.
C#
VB

using System;
using Windows.Globalization.DateTimeFormatting;
namespace WindowsBlogReader
{
public class DateConverter : Windows.UI.Xaml.Data.IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
string culture)
{
if (value == null)
throw new ArgumentNullException("value", "Value cannot be null.");
if (!typeof(DateTime).Equals(value.GetType()))
throw new ArgumentException("Value must be of type DateTime.",
"value");
DateTime dt = (DateTime)value;
if (parameter == null)
{
// Date "7/27/2011 9:30:59 AM" returns "7/27/2011"
return DateTimeFormatter.ShortDate.Format(dt);
}
else if ((string)parameter == "day")
{
// Date "7/27/2011 9:30:59 AM" returns "27"
DateTimeFormatter dateFormatter = new
DateTimeFormatter("{day.integer(2)}");
return dateFormatter.Format(dt);
}
else if ((string)parameter == "month")
{
// Date "7/27/2011 9:30:59 AM" returns "JUL"
DateTimeFormatter dateFormatter = new
DateTimeFormatter("{month.abbreviated(3)}");
return dateFormatter.Format(dt).ToUpper();
}
else if ((string)parameter == "year")
{
// Date "7/27/2011 9:30:59 AM" returns "2011"
DateTimeFormatter dateFormatter = new
DateTimeFormatter("{year.full}");
return dateFormatter.Format(dt);
}
else
{
// Requested format is unknown. Return in the original format.
return dt.ToString();
}
}

public object ConvertBack(object value, Type targetType, object


parameter, string culture)
{
string strValue = value as string;
DateTime resultDateTime;
if (DateTime.TryParse(strValue, out resultDateTime))
{
return resultDateTime;
}
return Windows.UI.Xaml.DependencyProperty.UnsetValue;
}
}
}

Click Build > Build solution to make sure the solution builds without error.

Before you can use the DateConverter class, you must declare an instance of it in your
XAML. You declare it as an app resource with the key dateConverter in App.xaml. Declaring
it here makes it available for every page in your app to use.
To add the dateConverter app resource

Double-click App.xaml in Solution Explorer to open it.

Add the resource declaration, <local:DateConverter


x:Key="dateConverter" />, to the ResourceDictionaryafter
the feedDataSource resource.

Now you can use the DateConverter in the bindings of the date block you create next. With
the converter added, the binding engine uses your custom DateConverter to change
a DateTime to a string. The string that it returns is formatted the way you want, with only the
day, month, and year.
In App.xaml, you add a ControlTemplate that defines a square block that shows the date. You
define this in App.xaml so you can use it in both ItemsPage.xaml and SplitPage.xaml.
To add a control template to App.xaml

Double-click App.xaml in Solution Explorer to open it.

Add this XAML in the ResourceDictionary with your other app specific resources,
after theWindowsBlogLayoutRootStyle resource.
XAML

<ControlTemplate x:Key="DateBlockTemplate">
<Canvas Height="86" Width="86" Margin="8,8,0,8"
HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock TextTrimming="WordEllipsis" TextWrapping="NoWrap"
Width="Auto" Height="Auto" Margin="8,0,4,0"
FontSize="32" FontWeight="Bold">
<TextBlock.Text>
<Binding Path="PubDate" Converter="{StaticResource

dateConverter}" ConverterParameter="month" />


</TextBlock.Text>
</TextBlock>
<TextBlock TextTrimming="WordEllipsis" TextWrapping="Wrap"
Width="40" Height="Auto" Margin="8,0,0,0"
FontSize="34" FontWeight="Bold" Canvas.Top="36">
<TextBlock.Text>
<Binding Path="PubDate" Converter="{StaticResource
dateConverter}" ConverterParameter="day" />
</TextBlock.Text>
</TextBlock>
<Line Stroke="White" StrokeThickness="2" X1="54" Y1="46" X2="54"
Y2="80" />
<TextBlock TextWrapping="Wrap"
Width="20" Height="Auto"
FontSize="{StaticResource ControlContentThemeFontSize}"
Canvas.Top="42" Canvas.Left="60">
<TextBlock.Text>
<Binding Path="PubDate" Converter="{StaticResource
dateConverter}" ConverterParameter="year" />
</TextBlock.Text>
</TextBlock>
</Canvas>
</ControlTemplate>
Now you can use this control template in SplitPage.xaml to update the look of the list items in
the default view.
To use the control template in SplitPage.xaml

Double-click SplitPage.xaml in Solution Explorer to open it.

In the XAML editor, find the DefaultListItemTemplate resource you created


previously.

Replace the XAML for the Border element with this XAML.
XAML

<Border Background="#FF6BBD46" Width="110" Height="110">


<ContentControl Template="{StaticResource
DateBlockTemplate}" />
</Border>

Replace the XAML for the 3 TextBlocks in the StackPanel element with this XAML.
XAML

<TextBlock Text="{Binding Title}" FontSize="26.667"

TextWrapping="Wrap"
MaxHeight="72" Foreground="#FFFE5815" />
<TextBlock Text="{Binding Author}" FontSize="18.667" />
Heres the updated XAML for the data template.
XAML

<DataTemplate x:Key="DefaultListItemTemplate">
<Grid Height="110" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="#FF6BBD46" Width="110" Height="110">
<ContentControl Template="{StaticResource DateBlockTemplate}" />
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top"
Margin="10,0,0,0">
<TextBlock Text="{Binding Title}" FontSize="26.667"
TextWrapping="Wrap"
MaxHeight="72" Foreground="#FFFE5815" />
<TextBlock Text="{Binding Author}" FontSize="18.667" />
</StackPanel>
</Grid>
</DataTemplate>
Important This template is used in the default full screen landscape view. If your screen
resolution is less than 1366 pixels wide, the split page uses the FilledOrNarrow view state,
and you will not see this template in the list view. To see this template, run the app in the
simulator in Visual Studio with a resolution of 1366 x 768 or greater. For more info about
testing the app in the simulator, see Running Windows Store apps from Visual Studio.
To finish styling the split page, you need to change the background color of the app bar and
the color of the selected item in the list view.
To update the app bar background

In SplitPage.xaml, select the AppBar control.

Under Brush in the Properties panel, or in the XAML editor, set


the Background property to "#F20A2562".
XAML

<AppBar Padding="10,0,10,0" Background="#F20A2562">


By default, the selected item in the list view has a purple background. You override the default
list view theme brushes to make the selected item blue. To override built-in theme brushes,
you define a brush with the same key in App.xaml and give it a new value.
To update the list view colors

Double-click App.xaml in Solution Explorer to open it.

Add this XAML in the ResourceDictionary after your other app specific resources.
XAML

<SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush"
Color="#FF465985"/>
<SolidColorBrush
x:Key="ListViewItemSelectedPointerOverBackgroundThemeBrush"
Color="#FF384A72"/>
<SolidColorBrush
x:Key="ListViewItemSelectedPointerOverBorderThemeBrush"
Color="#FF384A72" />
To finish styling the app, you apply similar styles to the items page. In ItemsPage.xaml, you
add these resources to define the look of the grid items in the default view.
To style ItemsPage.xaml

Double-click ItemsPage.xaml in Solution Explorer to open it.

In the XAML editor, add this XAML in the Page.Resources section after
the AppName resource.
XAML

<!-- light blue -->


<SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF557EB9"/>
<!-- Grid Styles -->
<Style x:Key="GridTitleTextStyle" TargetType="TextBlock"
BasedOn="{StaticResource BasicTextStyle}">
<Setter Property="FontSize" Value="26.667"/>
<Setter Property="Margin" Value="12,0,12,2"/>
</Style>
<Style x:Key="GridDescriptionTextStyle" TargetType="TextBlock"
BasedOn="{StaticResource BasicTextStyle}">
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="12,0,12,60"/>
</Style>
<DataTemplate x:Key="DefaultGridItemTemplate">
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{StaticResource BlockBackgroundBrush}" />
<TextBlock Text="{Binding Title}" Style="{StaticResource
GridTitleTextStyle}"/>
<TextBlock Text="{Binding Description}" Style="{StaticResource
GridDescriptionTextStyle}" />
<StackPanel VerticalAlignment="Bottom" Orientation="Horizontal"
Background="{StaticResource

ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="Last Updated" Margin="12,4,0,8"
Height="42"/>
<TextBlock Text="{Binding PubDate, Converter={StaticResource
dateConverter}}" Margin="12,4,12,8" />
</StackPanel>
</Grid>
</DataTemplate>

Select the GridView control named itemGridView.

Under Miscellaneous in the Properties panel, click the property marker for
the ItemTemplate property. The property menu opens.

In the menu, select Local Resource > DefaultGridItemTemplate.


Note The XAML page Design view must be showing in Visual Studio. If only the XAML
editor is showing, local page resources are not listed.
Here's the full updated XAML for itemGridView.
XAML

<!-- Horizontal scrolling grid used in most view states -->


<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemsGridView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.RowSpan="2"
Padding="116,136,116,46"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
ItemTemplate="{StaticResource DefaultGridItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"/>

Press F5 to build and run the app. The items page now uses the new template.

With your styles applied, the app fits in with the look and feel of the Windows team blogs
website:

By using styles and basing them on other styles you can quickly define and apply different
looks for your app. In the next section, you combine what you know about animations and
styles to make the app fluidly adapt to various layouts and orientations while its running.

Adapting to different layouts

Note In this section, you apply concepts discussed in Part3: Navigation, layout, and views. For

more info about adapting your UI to different views, and tool support that's available, review
Part 3.
Usually, an app is designed to be viewed full screen in the landscape orientation. But a
Windows Store app must adapt to different orientations and layouts. Specifically, it must
support both landscape and portrait orientations. In the landscape orientation, it must
support Full Screen, Filled, and Snapped layouts.
Tip To test the app in different orientations and resolutions, you can run it in the simulator. 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 info about the simulator,
see Running Windows Store apps from Visual Studio.
The Visual Studio templates include code that handles changes to the view state. This code is
in the LayoutAwarePage.cs/vb file, and it maps the app state to visual states defined in your
XAML. Because the page layout logic is provided for you, you only need to provide the views to
be used for each of the page's visual states.
To transition between different views using XAML, you use the VisualStateManager to define
different VisualStates for your app. Here you have a VisualStateGroup defined in
ItemsPage.xaml. This group has 4 VisualStates
namedFullScreenLandscape, Filled, FullScreenPortrait, and Snapped.
Different VisualStates from the sameVisualStateGroup can't be used at the same time.
Each VisualState has animations that tell the app what needs to change from the baseline
specified in the XAML for the UI.
XAML

<!--App Orientation States-->


<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape" />
<VisualState x:Name="Filled"> ... </VisualState>
<VisualState x:Name="FullScreenPortrait"> ... </VisualState>
<VisualState x:Name="Snapped"> ... </VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
You use the FullScreenLandscape state when the app is full screen in the landscape
orientation. Because you designed the default UI for this view, no changes are needed and this
is just an empty VisualState.
You use the Filled state when the user has another app snapped to one side of the screen.
The items view page just moves over in this case, and no changes are needed. This is just an
empty VisualState, too.
You use the FullScreenPortrait state when the app is rotated from landscape to portrait
orientation. In this visual state, you have 2 animations. One changes the style used for the
back button, and the other changes the margin ofitemGridView, so that everything fits
better on the screen.
XAML

<!-- The entire page respects the narrower 100-pixel margin convention for portrait
-->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton"
Storyboard.TargetProperty="Style">

<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource


PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="96,136,86,56"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>

You use the Snapped state when the user has two apps showing, and your app is the narrower
of the two. In this state, your app is only 320 device-independent pixels (DIPs) wide, so you
need to make more drastic changes to the layout. In the XAML for the items page UI, both
a GridView and a ListView are defined and bound to the data collection. By
default, itemGridView is shown, and itemListView is collapsed. In the Snapped state, you
have 4 animations that collapseitemGridView, show itemListView, and change
the Style of the back button and page title to make them smaller.
XAML

<!-The back button and title have different styles when snapped, and the list
representation is substituted
for the grid displayed in all other view states
-->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton"
Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle"
Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemGridView"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
In the Creating a consistent look with styles section of this tutorial, you created styles and

templates to give the app a custom look. The default landscape view uses these styles and
templates . To keep the custom look in different views, you also need to create custom styles
and templates for those views.
In ItemsPage.xaml, you created a new data template for the grid items. You also need to
provide a new data template for the list items that are shown in Snapped view. You name this
template NarrowListItemTemplate and add it to the resources section of ItemsPage.xaml,
just after the DefaultGridItemTemplate resource.
To add a template for the snapped view

Double-click ItemsPage.xaml in Solution Explorer to open it.

In the XAML editor, add this XAML in the Page.Resources section after
the DefaultGridItemTemplate resource.
XAML

<!-- Used in Snapped view -->


<DataTemplate x:Key="NarrowListItemTemplate">
<Grid Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource BlockBackgroundBrush}"
Width="80" Height="80" />
<ContentControl Template="{StaticResource DateBlockTemplate}"
Margin="-12,-12,0,0"/>
<StackPanel Grid.Column="1" HorizontalAlignment="Left"
Margin="12,8,0,0">
<TextBlock Text="{Binding Title}" MaxHeight="56"
TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</DataTemplate>

Select the ListView control named itemListView.

Under Miscellaneous in the Properties panel, click the property marker for
the ItemTemplate property. The property menu opens.

In the menu, select Local Resource > NarrowListItemTemplate.


Here's the full updated XAML for itemListView.
XAML

<!-- Vertical scrolling list only used when snapped -->


<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemsListView"
AutomationProperties.Name="Items"
TabIndex="1"

Grid.Row="1"
Visibility="Collapsed"
Margin="0,-10,0,0"
Padding="10,0,0,60"
ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
ItemTemplate="{StaticResource NarrowListItemTemplate}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"/>
In ItemsPage, you have both a GridView and a ListView, and you apply the templates in the
default XAML. You show the GridView for the default view. When the app is snapped, you
replace the grid with the ListView by using theVisualStateManager to change
the Visibility properties of the two views.
In SplitPage, you use a different way to change the UI when the view changes. You have a
single ListView that you show in all views. To change it's look when the view changes, you use
the VisualStateManager to apply a new template to theListView.
In SplitPage.xaml, you create a similar ListView template thats used in
the Filled and Snapped views, and in theFullScreenLandscape view if the screen width
is less than 1366 DIPs. You also name this templateNarrowListItemTemplate and add it to
the resources section of SplitPage.xaml, just after the DefaultListItemTemplateresource.
To add a narrow template

Double-click SplitPage.xaml in Solution Explorer to open it.

In the XAML editor, add this XAML in the Page.Resources section after
the DefaultListItemTemplate resource.
XAML

<!-- green -->


<SolidColorBrush x:Key="BlockBackgroundBrush" Color="#FF6BBD46"/>
<!-- Used in Filled and Snapped views -->
<DataTemplate x:Key="NarrowListItemTemplate">
<Grid Height="80">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource BlockBackgroundBrush}"
Width="80" Height="80"/>
<ContentControl Template="{StaticResource DateBlockTemplate}"
Margin="-12,-12,0,0"/>
<StackPanel Grid.Column="1" HorizontalAlignment="Left"
Margin="12,8,0,0">
<TextBlock Text="{Binding Title}" MaxHeight="56"
Foreground="#FFFE5815" TextWrapping="Wrap"/>
<TextBlock Text="{Binding Author}" FontSize="12" />

</StackPanel>
</Grid>
</DataTemplate>
To use this data template, you update the visual states where it's used.
To update the visual states

In the XAML for the FilledOrNarrow and Snapped visual states, find the animation
that targets the ItemTemplateproperty of itemListView.
Tip Press Ctrl+F to open the Quick Find box, and search for "Standard80ItemTemplate"
if you have trouble finding it.

Change the value to use the NarrowListItemTemplate resource, like


this: Value="{StaticResource NarrowListItemTemplate}".

You use your custom template instead of the


default Standard80ItemTemplate resource.
Here's the updated XAML for the animations.
XAML

<VisualState x:Name="FilledOrNarrow">
<Storyboard>
....
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="ItemTemplate">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
NarrowListItemTemplate}"/>
</ObjectAnimationUsingKeyFrames>
....
</Storyboard>
</VisualState>
...
<VisualState x:Name="Snapped">
<Storyboard>
....
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="ItemTemplate">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
NarrowListItemTemplate}"/>
</ObjectAnimationUsingKeyFrames>
....
</Storyboard>
</VisualState>
You also replaced the item detail section of the split page with your own detail section that
uses a WebView. Because you made this change, some animations in
the Snapped_Detail visual state target elements that no longer exist. These will cause errors
when the app is snapped, so you need to remove them.
To remove unused animations

In SplitPage.xaml, delete these animations from the Snapped_Detail visual state.

XAML

<VisualState x:Name="Snapped_Detail">
<Storyboard>
...
<!--<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="itemDetailTitlePanel"
Storyboard.TargetProperty="(Grid.Row)">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="itemDetailTitlePanel"
Storyboard.TargetProperty="(Grid.Column)">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
</ObjectAnimationUsingKeyFrames>-->
...
<!--<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="itemSubtitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
CaptionTextStyle}"/>
</ObjectAnimationUsingKeyFrames>-->
</Storyboard>
</VisualState>
When you select a blog and navigate to the split page in the snapped view, you expect the list
of blog posts to be shown. Instead, the text of the first blog post is shown because it's selected
by default. To change this behavior, you make sure nothing is selected when you navigate to
the split page in the snapped view.
To unselect the first item

Double-click SplitPage.xaml.cs/vb in Solution Explorer to open it.

In the LoadState method, find this block of code.


C#
VB

if (pageState == null)
{
// When this is a new page, select the first item automatically unless
logical page
// navigation is being used (see the logical page navigation #region
below.)
if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View
!= null)
{
this.itemsViewSource.View.MoveCurrentToFirst();
}
}

Add the else clause as shown here. The call MoveCurrentToPosition(-1) makes
the current item not set.
C#
VB

if (pageState == null)
{
// When this is a new page, select the first item automatically unless
logical page
// navigation is being used (see the logical page navigation #region
below.)
if (!this.UsingLogicalPageNavigation() && this.itemsViewSource.View
!= null)
{
this.itemsViewSource.View.MoveCurrentToFirst();
}
else
{
this.itemsViewSource.View.MoveCurrentToPosition(-1);
}
}
In DetailPage.xaml, you just need to adjust the margin of the WebView in the Snapped view
to use all the available space.
To update DetailPage.xaml

Double-click DetailPage.xaml in Solution Explorer to open it.

In the XAML for the Snapped visual state, add an animation to change the value of
the Margin property oncontentViewBorder.
XAML

<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="contentViewBorder"
Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
</ObjectAnimationUsingKeyFrames>
>
Here's the full XAML for the snapped state.
XAML

<!-- The back button and title have different styles when snapped -->
<VisualState x:Name="Snapped">

<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource
SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="contentViewBorder" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="20,5,20,20"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
Press F5 to build and run the app. Try it in different views and orientations.

Managing app lifecycle and state

Note In this section, you apply concepts discussed in Part 2: Manage app lifecycle and state.
For more info about saving app state, review Part 2.
To conserve system resources, the system automatically suspends (and sometimes terminates)
Windows Store apps that are running in the background. A well-designed app can be
suspended, terminated, and relaunched by the system and seem as though it were running the
entire time. Here, you add code to handle suspending and resuming the app. Fortunately, most
of the infrastructure is provided by the LayoutAwarePage and SuspensionManager classes
in the Visual Studio templates, so you just need to add a bit of code to save and restore
settings.

Managing navigation state


To use the SuspensionManager class to manage app state, you register the root Frame that
holds your content withSuspensionManager. When the app is suspended, you
call SuspensionManager.SaveAsync to save your app's navigation state, including which
page is the current page and the navigation parameter that was passed to that page. When
the app is restored, the navigation state is restored and the navigation parameter is passed
back to the page.
To save navigation state

Double-click App.xaml.cs/vb in Solution Explorer to open it.

Add the async keyword to the OnSuspending method.


C#
VB

private async void OnSuspending(object sender, SuspendingEventArgs e)

Add this code to the OnSuspending method, after the "TODO" comment.

SuspensionManager.SaveAsync saves the navigation state of the Frame and then


gives the Page an opportunity to save its content.
C#
VB

//TODO: Save application state and stop any background activity


await WindowsBlogReader.Common.SuspensionManager.SaveAsync();
When the app is restored after being suspended and terminated, this code is executed to
restore the navigation state of the app.
To load navigation state

In App.xaml.cs/vb, add this code in the OnLaunched method immediately after the
instantiation of the newFrame.
Here, you register the Frame with the SuspensionManager class.
C#
VB

// Add this code after "rootFrame = new Frame();"


WindowsBlogReader.Common.SuspensionManager.RegisterFrame(rootFrame,
"AppFrame");

Add this code in the OnLaunched method after the "TODO" comment.

SuspensionManager.RestoreAsync restores the navigation state of


the Frame and then gives the Page an opportunity to restore its content.
C#
VB

//TODO: Load state from previously suspended application


await
WindowsBlogReader.Common.SuspensionManager.RestoreAsync();

Managing page state


You also need to save any page specific settings when the app is suspended and restored. In
the blog reader app, you just need to save and restore the selected item in the split page. You
do this in the overrides of the SaveState andLoadState methods that are provided by
the LayoutAwarePage class.
To save page state

Double-click SplitPage.xaml.cs/vb in Solution Explorer to open it.

Add this code in the SaveState method after the "TODO" comment.
The SuspensionManager class serializes and saves the pageState dictionary to an
XML file. Data saved in pageStateis saved only for this session. Here, you save the
title of the blog post selected in the list.
C#
VB

// TODO: Derive a serializable navigation parameter and assign it to


//
pageState["SelectedItem"]
if (selectedItem != null)
{
string itemTitle = ((FeedItem)selectedItem).Title;
pageState["SelectedItem"] = itemTitle;
}

To load page state

In SplitPage.xaml.cs/vb, add this code in the LoadState method after the third
"TODO" comment.
C#
VB

// TODO: Invoke this.itemsViewSource.View.MoveCurrentTo() with


the selected
//

item as specified by the value of pageState["SelectedItem"]

string itemTitle = (string)pageState["SelectedItem"];


FeedItem selectedItem = FeedDataSource.GetItem(itemTitle);
this.itemsViewSource.View.MoveCurrentTo(selectedItem);

Adding a splash screen and logo


The first impression your app makes on a user comes from the logo and splash screen. The
logo appears in the Windows Store and on the start screen. The splash screen is shown
instantly when a user launches the app, and gives immediate feedback to the user while your
app initializes its resources. It's dismissed when the first page of your app is ready to show.
The splash screen consists of a background color and an image that's 620 x 300 pixels. You set
these values in the Package.appxmanifest file. Double click this file to open it in the manifest
editor. On the Application UI tab of the manifest editor, you set the path to your splash
screen image and the background color. The project template provides a default blank image
named SplashScreen.png. You replace this with your own splash screen image that clearly
identifies your app and immediately draws users into your app. You can also specify a logo by
replacing the template logo files with your own. Here's the splash screen for the blog reader.
The basic splash screen works well for the blog reader, but you can also extend the splash
screen using the properties and methods of the SplashScreen class. You can use
the SplashScreen class to get the coordinates of the splash screen and use them to place the
first page of the app. And you can find out when the splash screen is dismissed so you know
it's time to start any content entrance animations for the app.

See the code

Did you get stuck, or do you want to check your work? If so, see Blog reader complete code.

What's next

You learned how to use built-in page templates from Visual Studio Express 2012 for Windows 8
to build a complete multi-page app, and how to navigate and pass data between the pages.

You learned how to use styles and templates to make your app fit the personality of the
Windows team blogs website. You also learned how to use theme animations, an app bar, and
a splash screen to make your app fit the personality of Windows 8. Finally, you learned how to
adapt your app to various layouts and orientations so that it always looks its best.
For more info about developing apps, see the learning and reference resource list for creating
Windows Store apps.
Roadmap for Windows Store apps using C# or Visual Basic.

You might also like