Vous êtes sur la page 1sur 5922

Table of Contents

Get started with Universal Windows Platform


What's a UWP app?
Guide to Universal Windows Platform apps
Get set up
Enable your device for development
Sign up
Your first app
Create a "Hello, world" app (C#)
Create a "Hello, world" app (JS)
Create a "Hello, world" app (C++)
Support ink in your UWP app
Support the Surface Dial (and other wheel devices) in your UWP app
A single-page web app + REST API
A 2D UWP game in JavaScript
A 3D UWP game in JavaScript
A UWP game in MonoGame
Adding WebVR to a Babylon.js game
Plan your app
What's next?
Get UWP app samples
XAML basics tutorials
Create a user interface
Create custom styles
Create data bindings
Create adaptive layouts
Design & UI
Intro to app UI design
Layout
Navigation basics
Command basics
Content basics
Screen sizes and breakpoints
Define page layouts with XAML
Layout panels
Alignment, margins, and padding
Creating app layouts with Grid and StackPanel
Style
Acrylic
Color
Icons
Motion and animation
Parallax
Reveal
Sound
Typography
XAML Styles
Controls and patterns
Intro
Index of controls by function
App bar and command bar
Auto-suggest box
Buttons
Check box
Color picker
Date and time
Dialogs and flyouts
Flip view
Hub
Hyperlinks
Images and image brushes
Inking controls
Lists
Master/details
Media playback
Menus and context menus
Nav view
Person picture
Progress
Radio button
Rating control
Scrolling and panning controls
Search
Semantic zoom
Slider
Split view
Tabs and pivot
Text
Tiles, badges, and notifications
Toggle
Tooltip
Tree view
Web view
Inputs and devices
Input primer
Device primer
Usability
Accessibility
App settings
Globalization and localization
Guidelines for app help
Voice and tone
Fluent Design System
Design toolkits
Develop Windows apps
What's new in Windows 10 for developers, version 1703
API additions in Windows 10, version 1703
Prerelease APIs in Windows 10 SDK Preview Build 16267
What's new in the Windows 10 Build 2017 Preview
What's new in Windows 10, version 1607
What's new in Windows 10, version 1607 Preview
What's new in Windows 10, version 1511
What's new in Windows 10, version 1507
What's new in the Windows docs, August 2017
What's new in the Windows docs, July 2017
App-to-app communication
Share data
Receive data
Copy and paste
Drag and drop
Audio, video, and camera
Camera
Media playback
Detect faces in images or videos
Custom video effects
Custom audio effects
Media compositions and editing
Audio device information properties
Create, edit, and save bitmap images
Transcode media files
Process media files in the background
Audio graphs
MIDI
Import media from a device
Camera-independent Flashlight
Supported codecs
Query for installed codecs
Contacts, My People, and calendar
My People
Select contacts
Send email
Send an SMS message
Manage appointments
Connect your app to actions on a contact card
Data access
Entity framework Core with SQLite for C# apps
SQLite databases
Data binding
Data binding overview
Data binding in depth
Sample data on the design surface, and for prototyping
Bind hierarchical data and create a master/details view
Debugging, testing, and performance
Deploying and debugging UWP apps
Testing and debugging tools for PLM
Test with the Microsoft Emulator for Windows 10
Test Surface Hub apps using Visual Studio
Beta testing
Windows Device Portal
Windows App Certification Kit
Performance
Version adaptive apps
Develop UWP education apps
Take a Test API
Devices, sensors, and power
Enable device capabilities
Enable usermode access
Enumerate devices
Pair devices
Point of service
Sensors
Bluetooth
Printing and scanning
3D printing
NFC
Get battery information
Enterprise
Windows Information Protection (WIP)
Enterprise shared storage
Files, folders, and libraries
Enumerate and query files and folders
Create, write, and read a file
Get file properties
Open files and folders with a picker
Save a file with a picker
Accessing HomeGroup content
Determining availability of Microsoft OneDrive files
Files and folders in the Music, Pictures, and Videos libraries
Track recently used files and folders
Access the SD card
File access permissions
Game programming
Windows 10 game development guide
Planning
UWP programming
Game development videos
DirectX programming
Get started
Samples
Fundamentals
Add features
Optimization and advanced topics
Port DirectX 9 to UWP
Port OpenGL to Direct3D
Direct3D Graphics Learning Guide
Coordinate systems and geometry
Vertex and index buffers
Devices
Lighting
Depth and stencil buffers
Textures
Graphics pipeline
Views
Compute pipeline
Resources
Streaming resources
Appendices
Graphics and animation
Draw shapes
Use brushes
Animations overview
Transforms overview
Hosted Web Apps
Launching, resuming, and background tasks
App lifecycle
Launch an app with a URI
Launch an app through file activation
Reserved file and URI scheme names
Auto-launching with AutoPlay
Use app services
Support your app with background tasks
Connected apps and devices (Project Rome)
Splash screens
Maps and location
Request authentication key
Display maps
Display POI
Display routes and directions
Overlay tiled images
Perform geocoding
Get current location
Design guidance for location-aware apps
Set up a geofence
Design guidance for geofencing
Map style sheet reference
Monetization, engagement, and Store services
In-app purchases and trials
Display ads in your app with the Microsoft Advertising SDK
Engage customers with the Microsoft Store Services SDK
Windows Store services
Send requests to the Store
Create a Retail Demo Experience (RDX) app
Networking and web services
Networking basics
Which networking technology?
Network communications in the background
Sockets
WebSockets
HttpClient
RSS/Atom feeds
Background transfers
Packaging apps
Package a UWP app with Visual Studio
Manual app packaging
App package architectures
UWP App Streaming Install
Optional packages and related set authoring
Install apps with the WinAppDeployCmd.exe tool
App capability declarations
Set up automated builds for your UWP app
Download and install package updates for your app
Porting apps to Windows 10
Move from Windows Phone Silverlight to UWP
Move from Windows Runtime 8.x to UWP
Desktop Bridge
Windows apps concept mapping for Android and iOS developers
Move from iOS to UWP
Hosted Web Apps
Security
Intro to secure Windows app development
Authentication and user identity
Cryptography
Threading and async programming
Asynchronous programming (UWP apps)
Asynchronous programming in C++ (UWP apps)
Best practices for using the thread pool
Call asynchronous APIs in C# or Visual Basic
Create a periodic work item
Submit a work item to the thread pool
Use a timer to submit a work item
Using Windows Runtime objects in a multithreaded environment
UWP on Xbox One
Getting started
What's new
Xbox best practices
Known issues
FAQ
Xbox One Developer Mode activation
Tools
Development environment setup
System resource allocation
Introduction to multi-user applications
Samples
Bringing existing games to Xbox
Disabling developer mode on Xbox One
API reference
Visual layer
Composition visual
Composition animations
Composition effects
Composition brushes
Composition native interoperation
Composition lighting
Using XAML
Windows Runtime components
Creating Windows Runtime components in C++
Walkthrough: Creating a basic Windows Runtime component in C++ and calling it
from JavaScript or C#
Creating Windows Runtime components in C# and Visual Basic
Walkthrough: Creating a Simple Windows Runtime component and calling it from
JavaScript
Raising events in Windows Runtime components
Brokered Windows Runtime components for side-loaded Windows Store apps
XAML platform
XAML overview
Dependency properties overview
Custom dependency properties
Attached properties overview
Custom attached properties
Events and routed events overview
Xbox Live
API reference
App development for Windows as a service
Choose a UWP version
Services
Windows 8.x guides
Windows Phone Silverlight 8.x guides
Publish Windows apps
Overview
Using the Windows Dev Center dashboard
Account types, locations, and fees
Opening a developer account
Managing your account settings and profile info
Trademark and copyright protection
Dev Center Insider Program
Manage account users
Associate Azure AD with your Dev Center account
Add users, groups, and Azure AD applications
Set roles and custom permissions
Create your app by reserving a name
App submissions
Set app pricing and availability
Enter app properties
Age ratings
Upload app packages
Create app Store listings
Notes for certification
The app certification process
Package flights
Gradual package rollout
Beta testing and targeted distribution
Distribute LOB apps to enterprises
Add-on submissions
Set your add-on product type and product ID
Enter add-on properties
Set add-on pricing and availability
Create add-on Store listings
Monetize with ads
About affiliate ads
App management and services
Use map services
View app identity details
Manage app names
Generate preinstall packages for OEMs
Attract and promote
Generate promotional codes
Create an ad campaign for your app
Create a custom app promotion campaign
Put apps and add-ons on sale
App marketing guidelines
Link to your app
Make your app easier to promote
Engage with your customers
Create customer groups
Respond to customer reviews
Respond to customer feedback
Send notifications to your app's customers
Use targeted offers to maximize engagement and conversions
Analyze app performance
Acquisitions report
Add-on acquisitions report
Usage report
Health report
Reviews report
Feedback report
Advertising performance report
Ad campaign report
Download analytics reports
Getting paid
Set up your payout account and tax forms
Payout thresholds, methods, and timeframes
Payout summary
Tax details for paid apps
Understand IRS tax forms
Mobile operator billing
VAT info
Store Policies and Code of Conduct
Windows Store Policies
App quality
Developer Code of Conduct
What's a Universal Windows Platform (UWP) app?
8/15/2017 5 min to read Edit Online

The Universal Windows Platform (UWP) is the app platform for Windows 10. You can develop apps for UWP with
just one API set, one app package, and one store to reach all Windows 10 devices PC, tablet, phone, Xbox,
HoloLens, Surface Hub and more. Its easier to support a number of screen sizes, and also a variety of interaction
models, whether it be touch, mouse and keyboard, a game controller, or a pen. At the core of UWP apps is the idea
that users want their experiences to be mobile across ALL their devices, and they want to use whatever device is
most convenient or productive for the task at hand.
UWP is also flexible: you don't have to use C# and XAML if you don't want to. Do you like developing in Unity or
MonoGame? Prefer JavaScript? Not a problem, use them all you want. Have a C++ desktop app that you want to
extend with UWP features and sell in the store? That's okay, too.
The bottom line: You can spend your time working with familiar programming languages, frameworks and APIs,
all in single project, and have the very same code run on the huge range of Windows hardware that exists today.
Once you've written your UWP app, you can then publish it to the store for the world to see.

So, what exactly is a UWP app?


What makes a UWP app special? Here are some of the characteristics that make UWP apps on Windows 10
different.
There's a common API surface across all devices.
The Universal Windows Platform (UWP) core APIs are the same for all classes of Windows device. If your
app uses only the core APIs, it will run on any Windows 10 device, no matter if you are targeting a desktop
PC, an Xbox or a Mixed Reality headset.
Extension SDKs let your app do cool stuff on specific device types.
Extension SDKs add specialized APIs for each device class. For example, if your UWP app targets HoloLens,
you can add HoloLens features in addition to the normal UWP core APIs. If you target the universal APIs,
your app package can run on all devices that run Windows 10. But if you want your UWP app to take
advantage of device specific APIs in the event it is running on a particular class of device, you can check at
run-time if an API exists before calling it.
Apps are packaged using the .AppX packaging format and distributed from the Store.
All UWP apps are distributed as an AppX package. This provides a trustworthy installation mechanism and
ensures that your apps can be deployed and updated seamlessly.
There's one store for all devices.
After you register as an app developer, you can submit your app to the store and make it available on all
types device, or only those you choose. You submit and manage all your apps for Windows devices in one
place.
Apps support adaptive controls and input
UI elements use effective pixels (see Responsive design 101 for UWP apps), so they can respond with a
layout that works based on the number of screen pixels available on the device. And they work well with
multiple types of input such as keyboard, mouse, touch, pen, and Xbox One controllers. If you need to
further tailor your UI to a specific screen size or device, new layout panels and tooling help you adapt your
UI to the devices your app may run on.

Use a language you already know


UWP apps use the Windows Runtime, a native API built into the operating system. This API is implemented in C++
and supported in C#, Visual Basic, C++, and JavaScript. Some options for writing apps in UWP include:
XAML UI and a C#, VB, or C++ backend
DirectX UI and a C++ backend
JavaScript and HTML
Microsoft Visual Studio 2017 provides a UWP app template for each language that lets you create a single project
for all devices. When your work is finished, you can produce an app package and submit it to the Windows Store
from within Visual Studio to get your app out to customers on any Windows 10 device.

UWP apps come to life on Windows


On Windows, your app can deliver relevant, real-time info to your users and keep them coming back for more. In
the modern app economy, your app has to be engaging to stay at the front of your users lives. Windows provides
you with lots of resources to help keep your users returning to your app:
Live tiles and the lock screen show contextually relevant and timely info at a glance.
Push notifications bring real-time, breaking alerts to your users attention when they're needed.
The Action Center is a place where you can organize and display notifications and content that users need
to take action on.
Background execution and triggers bring your app to life just when the user needs it.
Your app can use voice and Bluetooth LE devices to help users interact with the world around them.
Support for rich, digital ink and the innovative Dial.
Cortana adds personality to your software.
XAML provides you with the tools to create smooth, animated user interfaces.
Finally, you can use roaming data and the Windows Credential Locker to enable a consistent roaming experience
across all of the Windows screens where users run your app. Roaming data gives you an easy way to store a
users preferences and settings in the cloud, without having to build your own sync infrastructure. And you can
store user credentials in the Credential Locker, where security and reliability are the top priority.

Monetize your app


On Windows, you can choose how you'll monetize your appacross phones, tablets, PCs, and other devices. We
give you a number of ways to make money with your app and the services it delivers. All you need to do is choose
the one that works best for you:
A paid download is the simplest option. Just name your price.
Trials let users try your app before buying it, providing easier discoverability and conversion than the more
traditional "freemium" options.
Use sale prices for apps and add-ons.
In-app purchases and ads are also available.

Let's get started


For a more detailed look at the UWP, read the Guide to Universal Windows Platform apps. Then, check out Get set
up to download the tools you need to start creating apps, and then write your first app!

More advanced topics


.NET Native - What it means for Universal Windows Platform (UWP) developers
Universal Windows apps in .NET
.NET for UWP apps
Intro to the Universal Windows Platform
8/30/2017 19 min to read Edit Online

In this guide, you'll learn about the Universal Windows Platform (UWP) and Windows 10:
What a device family is and how to decide which one to target.
What an Extension SDK is and how it provides access to APIs specific to a class of devices.
New UI controls and panels for adapting your UI to different screen sizes or rotations.
How to understand and control the API surface that is available to your app.
Windows 10 introduces the Universal Windows Platform (UWP), which provides a common app platform available
on every device that runs Windows 10. The UWP provides a guaranteed core API across devices. This means you
can create a single app package that can be installed onto a wide range of devices. And, with that single app
package, the Windows Store provides a unified distribution channel to reach all the device types your app can run
on. Apps that target the UWP can call not only the WinRT APIs that are common to all devices, but also APIs
(including Win32 and .NET APIs) that are specific to the class of device that the app is running on.

Because your UWP app runs on a wide variety of devices with different form factors and types of input, you want it
to be tailored to each device and be able to unlock the unique capabilities of each device. In addition to the
guaranteed core API layer, you can write code to access device specific APIs so that your app lights up features
specific to one type of device while presenting a different experience on other devices. Adaptive UI controls and
new layout panels help you to tailor your UI across a broad range of device screen resolutions and sizes.

Device families
In order to understand how Windows 10 allows you to target different classes of devices, it's helpful to understand
a concept called device families. A device family identifies the APIs, system characteristics, and behaviors that you
can expect across a class of devices. It also determines the set of devices on which your app can be installed from
the Store. A device family (with the exception of the Universal device family) is implemented as an extension SDK,
which is covered in further detail in the Extension SDKs section. This diagram demonstrates the device family
hierarchy.
A device family defines a set of APIs, is versioned, and is the foundation of an OS. PCs and tablets run the desktop
OS, which is based on the desktop device family. Phones run the mobile OS, which is based on the mobile device
family.
Each child device family adds its own APIs to the ones it inherits. The resulting union of APIs in a child device family
is guaranteed to be present in the OS based on that device family, and on every device running that OS.
One benefit of the universal device family is that your app can run on a variety of devices; phones, tablets, desktop
computers, Surface Hubs, Xbox consoles, and HoloLens, to name a few. Your app can also use adaptive code to
dynamically detect and use features of a device that are outside of the universal device family.
The decision about which device family (or families) your app will target is yours to make. And that decision
impacts your app in these important ways. It determines:
The set of APIs that your app can assume to be present when it runs (and can therefore call freely).
The set of API calls that are safe only inside conditional statements.
The set of devices on which your app can be installed from the Store (and consequently the form factors that
you need to consider when you design the UI).
There are two main consequences of making a device family choice: the API surface that can be called
unconditionally by the app, and the number of devices the app can reach. These two factors involve tradeoffs and
are inversely related. For example, a UWP app is an app that specifically targets the universal device family, and
consequently is available to all devices. An app that targets the universal device family can assume the presence of
only the APIs in the universal device family. Other APIs must be called conditionally. Also, such an app must have a
highly adaptive UI and comprehensive input capabilities because it can run on a wide variety of devices. A
Windows mobile app is an app that specifically targets the mobile device family, and is available to devices whose
OS is based on the mobile device family (which includes phones, tablets, and similar devices). A mobile device
family app can assume the presence of all APIs in the mobile device family, and its UI has to be moderately
adaptive. An app that targets the IoT device family can be installed only on IoT devices and can assume the
presence of all APIs in the IoT device family. That app can be very specialized in its UI and input capabilities because
you know that it will run only on a specific type of device.
Here are some considerations to help you decide which device family to target:
Maximizing your app's reach
To reach the maximum range of devices with your app, and to have it run on as many devices as possible, your app
will target the universal device family. By doing so, the app automatically targets every device family that's based
on universal (in the diagram, all the children of universal). That means that the app runs on every OS based on
those device families, and on all the devices that run those operating systems. The only APIs that are guaranteed to
be available on all those devices is the set defined by the particular version of the universal device family that you
target. To find out how an app can call APIs outside of its target device family version, see Writing Code later in this
topic.
Limiting your app to one kind of device
You may not want your app to run on a wide range of devices; perhaps it's specialized for a desktop PC or for an
Xbox console. In that case you can choose to target your app at one of the child device families. For example, if you
target the desktop device family, the APIs guaranteed to be available to your app, include the APIs inherited from
the universal device family, as well as the APIs that are particular to the desktop device family.
Limiting your app to a subset of all possible devices
Instead of targeting the universal device family, or targeting one of the child device families, you can instead target
two (or more) child device families. Targeting desktop and mobile might make sense for your app. Or desktop and
HoloLens. Or desktop, Xbox and Surface Hub, and so on.
Excluding support for a particular version of a device family
In rare cases, you may want your app to run everywhere except on devices with a particular version of a particular
device family. For example, let's say your app targets version 10.0.x.0 of the universal device family. When the
operating system version changes in the future, say to 10.0.x.2, at that point you can specify that your app runs
everywhere except version 10.0.x.1 of Xbox by targeting your app to 10.0.x.0 of universal and 10.0.x.2 of Xbox. Your
app will then be unavailable to the set of device family versions within Xbox 10.0.x.1 (inclusive) and earlier.
By default, Microsoft Visual Studio specifies Windows.Universal as the target device family in the app package
manifest file. To specify the device family or device families that your app is offered to from within the Store,
manually configure the TargetDeviceFamily element in your Package.appxmanifest file.

Extension SDKs
Once you have decided on the device family that your app will target, add a reference to the Extension SDK(s) that
implement the APIs for that device family. If you are targeting the Universal device family, you don't need to
reference an extension SDK. But if you are targeting a device family besides Universal, in Visual Studio you will add
a reference to the extension SDK that matches the device family you have chosen. For example, if you are targeting
the mobile device family, you would add a reference to the Windows Mobile Extensions for the UWP in Visual
Studio's Reference Manager.
Selecting a device family does not prohibit you from adding extension SDKs for other types of devices. You will just
need to ensure that you test for the presence of APIs not included in the device family you have chosen as
described below in Writing Code.

UI and universal input


A UWP app can run on many devices that have different forms of input, screen resolutions, DPI density, and other
unique characteristics. Windows 10 provides new universal controls, layout panels, and tooling to help you adapt
your UI to the devices your app may run on. For example, you can tailor the UI to take advantage of the difference
in screen resolution when your app is running on a desktop computer versus on a mobile device.
Some aspects of your app's UI will automatically adapt across devices. Controls such as buttons and sliders
automatically adapt across device families and input modes. Your app's user-experience design, however, may
need to adapt depending on the device the app is running on. For example, a photo app should adapt to the UI
when running on a small, hand-held device to ensure that usage is ideal for single-hand use. When a photo app is
running on a desktop computer, the UI should adapt to take advantage of the additional screen space.
Windows helps you target your UI to multiple devices with the following features:
Universal controls and layout panels help you to optimize your UI for the screen resolution of the device.
Common input handling allows you to receive input through touch, a pen, a mouse, a keyboard, or a controller
such as a Microsoft Xbox controller.
Tooling helps you to design UI that can adapt to different screen resolutions.
Adaptive scaling adjusts to resolution and DPI differences across devices.
Universal controls and layout panels
Windows 10 includes new controls such as the calendar and split view. The pivot control, which was previously
available only for Windows Phone, is also now available for the universal device family.
Controls have been updated to work well on larger screens, adapt themselves based on the number of screen
pixels available on the device, and work well with multiple types of input such as keyboard, mouse, touch, pen, and
controllers such as the Xbox controller.
You may find that you need to adapt your overall UI layout based on the screen resolution of the device your app
will be running on. For example, a communication app running on the desktop may include a picture-in-picture of
the caller and controls well suited to mouse input:

However, when the app runs on a phone, because there is less screen real-estate to work with, your app may
eliminate the picture-in-picture view and make the call button larger to facilitate one-handed operation:

To help you adapt your overall UI layout based on the amount of available screen space, Windows 10 introduces
adaptive panels and design states.
Design adaptive UI with adaptive panels
Layout panels give sizes and positions to their children, depending on available space. For example, StackPanel
orders its children sequentially (horizontally or vertically). Grid is like a CSS grid that places its children into cells.
The new RelativePanel implements a style of layout that is defined by the relationships between its child
elements. It's intended for use in creating app layouts that can adapt to changes in screen resolution. The
RelativePanel eases the process of rearranging elements by defining relationships between elements, which
allows you to build more dynamic UI without using nested layouts.
In the following example, blueButton will appear to the right of textBox1 regardless of changes in orientation or
layout, and orangeButton will appear immediately below, and aligned with, blueButtoneven as the width of
textBox1 changes as text is typed into it. It would previously have required rows and columns in a Grid to achieve
this effect, but now it can be done using far less markup.

<RelativePanel>
<TextBox x:Name="textBox1" Text="textbox" Margin="5"/>
<Button x:Name="blueButton" Margin="5" Background="LightBlue" Content="ButtonRight" RelativePanel.RightOf="textBox1"/>
<Button x:Name="orangeButton" Margin="5" Background="Orange" Content="ButtonBelow" RelativePanel.RightOf="textBox1"
RelativePanel.Below="blueButton"/>
</RelativePanel>

Use visual state triggers to build UI that can adapt to available screen space
Your UI may need to adapt to changes in window size. Adaptive visual states allows you to change the visual state
in response to changes in the size of the window.
StateTriggers define a threshold at which a visual state is activated, which then sets layout properties as
appropriate for the window size that triggered the state change.
In the following example, when the window size is 720 pixels or more in width, the visual state named wideView
is triggered, which then arranges the Best-rated games panel to appear to the right of, and aligned with the top
of, the Top free games panel.

When the window is less than 720 pixels, the narrowView visual state is triggered because the wideView trigger
is no longer satisfied and so no longer in effect. The narrowView visual state positions the Best-rated games
panel below, and aligned with the left of, the Top paid games panel:
Here is the XAML for the visual state triggers described above. The definition of the panels, alluded to by " ... "
below, has been removed for brevity.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="wideView">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="best.(RelativePanel.RightOf)" Value="free"/>
<Setter Target="best.(RelativePanel.AlignTopWidth)" Value="free"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="narrowView">
<VisualState.Setters>
<Setter Target="best.(RelativePanel.Below)" Value="paid"/>
<Setter Target="best.(RelativePanel.AlignLeftWithPanel)" Value="true"/>
</VisualState.Setters>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
</Grid>

Tooling
By default, you'll probably want to target the broadest possible device family. When you're ready to see how your
app looks and lays out on a particular device, use the device preview toolbar in Visual Studio to preview your UI on
a small or medium mobile device, on a PC, or on a large TV screen. That way you can tailor and test your adaptive
visual states:
You dont have to make a decision up front about every device type that you'll support. You can add an additional
device size to your project later.
Adaptive scaling
Windows 10 introduces an evolution of the existing scaling model. In addition to scaling vector content, there is a
unified set of scale factors that provides a consistent size for UI elements across a variety of screen sizes and
display resolutions. The scale factors are also compatible with the scale factors of other operating systems such as
iOS and Android. This makes it easier to share assets between these platforms.
The Store picks the assets to download based in part of the DPI of the device. Only the assets that best match the
device are downloaded.
Common input handling
You can build a Universal Windows app using universal controls that handle various inputs such as mouse,
keyboard, touch, pen, and controller (such as the Xbox controller). Traditionally, inking has been associated only
with pen input, but with Windows 10, you can ink with touch on some devices, and with any pointer input. Inking is
supported on many devices (including mobile devices) and can easily be incorporated with a just few lines of code.
The following APIs provide access to input:
CoreIndependentInputSource is a new API that allows you to consume raw input on the main thread or a
background thread.
PointerPoint unifies raw touch, mouse, and pen data into a single, consistent set of interfaces and events that
can be consumed on the main thread or background thread by using CoreInput.
PointerDevice is a device API that supports querying device capabilities so that you can determine what kinds
of input are available on the device.
The new InkCanvas XAML control and InkPresenter Windows Runtime APIs allow you to access ink stroke
data.

Writing code
Your programming language options for your Windows 10 project in Visual Studio include Visual C++, C#, Visual
Basic, and JavaScript. For Visual C++, C#, and Visual Basic, you can use XAML for a full-fidelity, native UI
experience. For Visual C++ you can choose DirectX either instead of or as well as using XAML. For JavaScript, your
presentation layer will be HTML, and HTML is of course a cross-platform web standard. Much of your code and UI
will be universal and it will run the same way everywhere. But for code tailored to particular device families, and
for UI tailored to particular form factors, you'll have the option to use adaptive code and adaptive UI. Let's consider
these different cases:
Calling an API that's implemented by your target device family
Whenever you want to call an API in a UWP app, you'll want to know whether the API is implemented by the device
family that your app is targeting. Visual Studio Intellisense only shows you the APIs that are available for the
extension SDKs that you have chosen. If you have not selected an extension SDK, you'll see only the APIs available
to the Universal device family.
The API documentation also tells you which device family an API is part of. If you look at the Requirements section,
you'll see what the implementing device family is and which version of that device family the API appears in.
Calling an API that's NOT implemented by your target device family
There will be cases when you want to call an API in an extension SDK that you've referenced, but that API is not
part of the device family you are targeting. For example, you may be targeting the universal device family, but have
a desktop API that you'd like to use if the app happens to be running on a mobile device. In that case, you can opt
to write adaptive code in order to call that API.
Writing adaptive code with the ApiInformation class
There are two steps to write adaptive code. The first step is to make the APIs that you want to access available to
your project. To do that, add a reference to the extension SDK that represents the device family that owns the APIs
that you want to conditionally call. See Extension SDKs.
The second step is to use the Windows.Foundation.Metadata.ApiInformation class in a condition in your code
to test for the presence of the API you want to call. This condition is evaluated wherever your app runs, but it
evaluates to true only on devices where the API is present and therefore available to call.
If you want to call just a small number of APIs, you could use the ApiInformation.IsTypePresent method like
this.

// Note: Cache the value instead of querying it more than once.


bool isHardwareButtonsAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");

if (isHardwareButtonsAPIPresent)
{
Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
HardwareButtons_CameraPressed;
}

In this case, there is confidence that the presence of the HardwareButtons class implies the presence of the
CameraPressed event, because the class and the member have the same requirements info. But in time, new
members will be added to already-introduced classes, and those members will have later "introduced in" version
numbers. In such cases, instead of using IsTypePresent, you can test for the presence of individual members by
using IsEventPresent, IsMethodPresent, IsPropertyPresent, and similar methods. Here's an example.

bool isHardwareButtons_CameraPressedAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsEventPresent
("Windows.Phone.UI.Input.HardwareButtons", "CameraPressed");
The set of APIs within a device family is further broken down into subdivisions known as API contracts. You can use
the ApiInformation.IsApiContractPresent method to test for the presence of an API contract. This is useful if
you want to test for the presence of a large number of APIs that all exist in the same version of an API contract.

bool isWindows_Devices_Scanners_ScannerDeviceContract_1_0Present =
Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent
("Windows.Devices.Scanners.ScannerDeviceContract", 1, 0);

Win32 APIs in the UWP


A UWP app or Windows Runtime Component written in C++/CX has access to the Win32 APIs that are part of the
UWP. These Win32 APIs are implemented by all Windows 10 device families. Link your app with Windowsapp.lib.
Windowsapp.lib is an "umbrella" lib that provides the exports for the UWP APIs. Linking to Windowsapp.lib will
add to your app dependencies on dlls that are present on all Windows 10 device families.
For the full list of Win32 APIs available to UWP apps, see API Sets for UWP apps and Dlls for UWP apps.

User experience
A Universal Windows app allows you to take advantage of the unique capabilities of the device on which it is
running. Your app can make use of all of the power of a desktop device, the natural interaction of direct
manipulation on a tablet (including touch and pen input), the portability and convenience of mobile devices, the
collaborative power of Surface Hub, and other devices that support UWP apps.
Good design is the process of deciding how users will interact with your app, as well as how it will look and
function. User experience plays a huge part in determining how happy people will be with your app, so don't skimp
on this step. Design basics introduce you to designing a Universal Windows app. See the Introduction to Universal
Windows Platform (UWP) apps for designers for information on designing UWP apps that delight your users.
Before you start coding, see the device primer to help you think through the interaction experience of using your
app on all the different form factors you want to target.

In addition to interaction on different devices, plan your app to embrace the benefits of working across multiple
devices. For example:
Use cloud services to sync across devices. Learn how to connect to web services in support of your app
experience.
Consider how you can support users moving from one device to another, picking up where they left off.
Include notifications and in-app purchases in your planning. These features should work across devices.
Design your workflow using Navigation design basics for UWP apps to accommodate mobile, small-screen,
and large-screen devices. Lay out your user interface to respond to different screen sizes and resolutions.
Consider whether there are features of your app that dont make sense on a small mobile screen. There may
also be areas that dont make sense on a stationary desktop machine and require a mobile device to light
up. For example, most scenarios around location imply a mobile device.
Consider how you'll accommodate multiple kinds of input. See the Guidelines for interactions to learn how
users can interact with your app by using Cortana, Speech, Touch interactions, the Touch keyboard and
more.
See the Guidelines for text and text input for more traditional interaction experiences.

Submit a Universal Windows app through your Dashboard


The new unified Windows Dev Center dashboard lets you manage and submit all of your apps for Windows
devices in one place. New features simplify processes while giving you more control. You'll also find detailed
analytic reports combined payout details, ways to promote your app and engage with your customers, and much
more.
See Using the unified Windows Dev Center dashboard to learn how to submit your apps for publication in the
Windows Store.

See Also
For more introductory material, see Windows 10 - An Introduction to Building Windows Apps for Windows 10
Devices
Get set up
4/5/2017 1 min to read Edit Online

It's easier than you think to get going. Follow these instructions and start creating Universal Windows Platform
(UWP) apps for Windows 10.

1. Get Windows 10
To develop UWP apps, you need the latest version of Windows.
Get Windows 10 online
Are you an MSDN subscriber? You can get ISO downloads here:
Get Windows 10 from MSDN Subscriber Downloads

2. Download or update Visual Studio


Microsoft Visual Studio 2017 helps you design, code, test, and debug your apps.
If you don't already have Visual Studio 2017, you can install the free Microsoft Visual Studio Community 2017.
This download includes device simulators for testing your apps:
Download Windows 10 developer tools
When you install Visual Studio, make sure to select the Universal Windows App Development Tools option, as
shown here:
Need some help with Visual Studio? See Get Started with Visual Studio.
If you have already started using Visual Studio, but discover you are missing some components, you can launch
the installer again from the New project dialog:

3. Enable your device for development


Its important to test your UWP apps on a real PCs and phones. Before you can deploy apps to your PC or
Windows Phone, you have to enable it for development.
For detailed instructions, see Enable your device for development.

4. Register as an app developer


You can start developing apps now, but before you can submit them to the store, you need a developer account.
To get a developer account, go to the Sign up page.

What's next?
After you've installed the tools and gotten a developer license or a developer account, use our tutorials to create
your first app:
Create your first app tutorials

Want more tools and downloads?


For the complete list of tools and downloads, see Downloads.

See Also
Your first app
Publishing your Windows Store app.
How-to articles on developing UWP apps
Code Samples for UWP developers
What's a Universal Windows app?
Sign up for Windows account
Enable your device for development
8/7/2017 10 min to read Edit Online

Activate Developer Mode, sideload apps and access other developer


features

If you are using your computer for ordinary day-to-day activities such as games, web browsing, email or Office apps, you
do not need to activate Developer Mode and in fact, you shouldn't activate it. The rest of the information on this page
won't matter to you, and you can safely get back to whatever it is you were doing. Thanks for stopping by!
However, if you are writing software with Visual Studio on a computer for first time, you will need to enable Developer
Mode on both the development PC, and on any devices you'll use to test your code. Opening a UWP project when
Developer Mode is not enabled will either open the For developers settings page, or cause this dialog to appear in Visual
Studio:

When you see this dialog, click settings for developers to open the For developers settings page.

NOTE
You can go to the For developers page at any time to enable or disable Developer Mode: simply enter "for developers" into the
Cortana search box in the taskbar.

Accessing settings for Developers


To enable Developer mode, or access other settings:
1. From the For developers settings dialog, choose the level of access that you need.
2. Read the disclaimer for the setting you chose, then click Yes to accept the change.

NOTE
If your device is owned by an organization, some options might be disabled by your organization.

Here's the settings page on the desktop device family:

Here's the settings page on the mobile device family:


Which setting should I choose: sideload apps or Developer Mode?
You can enable a device for development, or just for sideloading.
Windows Store apps is the default setting. If you aren't developing apps, or using special internal apps issued by your
company, keep this setting active.
Sideloading is installing and then running or testing an app that has not been certified by the Windows Store. For
example, an app that is internal to your company only.
Developer mode lets you sideload apps, and also run apps from Visual Studio in debug mode.
By default, you can only install Universal Windows Platform (UWP) apps from the Windows Store. Changing these
settings to use developer features can change the level of security of your device. You should not install apps from
unverified sources.
Sideload apps
The Sideload apps setting is typically used by companies or schools that need to install custom apps on managed devices
without going through the Windows Store. In this case, it's common for the organization to enforce a policy that disables
the Windows Store apps setting, as shown previously in the image of the settings page. The organization also provides
the required certificate and install location to sideload apps. For more info, see the TechNet articles Sideload apps in
Windows 10 and Get started with app deployment in Microsoft Intune.
Device family specific info
On the desktop device family: You can install an app package (.appx) and any certificate that is needed to run the
app by running the Windows PowerShell script that is created with the package ("Add-AppDevPackage.ps1"). For
more info, see Packaging UWP apps.
On the mobile device family: If the required certificate is already installed, you can tap the file to install any .appx
sent to you via email or on an SD card.
Sideload apps is a more secure option than Developer Mode because you cannot install apps on the device without a
trusted certificate.
NOTE
If you sideload apps, you should still only install apps from trusted sources. When you install a sideloaded app that has not been
certified by the Windows Store, you are agreeing that you have obtained all rights necessary to sideload the app and that you are
solely responsible for any harm that results from installing and running the app. See the Windows > Windows Store section of this
privacy statement.

Developer Mode
Developer Mode replaces the Windows 8.1 requirements for a developer license. In addition to sideloading, the
Developer Mode setting enables debugging and additional deployment options. This includes starting an SSH service to
allow this device to be deployed to. In order to stop this service, you have to disable Developer Mode.
Device family specific info
On the desktop device family:
Enable Developer Mode to develop and debug apps in Visual Studio. As stated previously, you will be prompted in
Visual Studio if Developer Mode is not enabled.
On pre-Fall-Creators-Update PCs, this allows enabling of the Windows subsystem for Linux. For more info, see
About Bash on Ubuntu on Windows. Developer Mode is no longer required for WSL, as of the Fall Creators
Update.
On the mobile device family:
Enable developer mode to deploy apps from Visual Studio and debug them on the device.
You can tap the file to install any .appx sent to you via email or on an SD card. Do not install apps from unverified
sources.

Additional Developer Mode features


For each device family, additional developer features might be available. These features are available only when
Developer Mode is enabled on the device, and might vary depending on your OS version.
When you enable Developer Mode, a package of options is installed that includes:
Windows Device Portal. Device Portal is enabled and firewall rules are configured for it only when the Enable Device
Portal option is turned on.
Installs, enables, and configures firewall rules for SSH services that allow remote installation of apps.
This image shows developer features for the mobile device family on Windows 10:
Device Portal
To learn more about Device Portal, see Windows Device Portal overview.
For device specific setup instructions, see:
Device Portal for Desktop
Device Portal for HoloLens
Device Portal for IoT
Device Portal for Mobile
Device Portal for Xbox
If you encounter problems enabling Developer Mode or Device Portal, see the Known Issues forum to find workarounds
for these issues, or visit Failure to install the Developer Mode package for additional details and which WSUS KBs to allow
in order to unblock the Developer Mode package.
SSH
SSH services are enabled when you enable Developer Mode on your device. This is used when your device is a
deployment target for UWP applications. The names of the services are 'SSH Server Broker' and 'SSH Server Proxy'.

NOTE
This is not Microsoft's OpenSSH implementation, which you can find on GitHub.

In order to take advantage of the SSH services, you can enable device discovery to allow pin pairing. If you intend to run
another SSH service, you can set this up on a different port or turn off the Developer Mode SSH services. To turn off the
SSH services, simply disable Developer Mode.
Device Discovery
When you enable device discovery, you are allowing your device to be visible to other devices on the network through
mDNS. This feature also allows you to get the SSH PIN for pairing to this device.
You should enable device discovery only if you intend to make the device a deployment target. For example, if you use
Device Portal to deploy an app to a phone for testing, you need to enable device discovery on the phone, but not on your
development PC.
Error reporting (Mobile only)
Set this value to specify how many crash dumps are saved on your phone.
Collecting crash dumps on your phone gives you instant access to important crash information directly after the crash
occurs. Dumps are collected for developer-signed apps only. You can find the dumps in your phone's storage in the
Documents\Debug folder. For more info about dump files, see Using dump files.
Optimizations for Windows Explorer, Remote Desktop, and PowerShell (Desktop only)
On the desktop device family, the For developers settings page has shortcuts to settings that you can use to optimize
your PC for development tasks. For each setting, you can select the checkbox and click Apply, or click the Show settings
link to open the settings page for that option.
Tip
There are several tools you can use to deploy an app from a Windows 10 PC to a Windows 10 mobile device. Both
devices must be connected to the same subnet of the network by a wired or wireless connection, or they must be
connected by USB. Either of the ways listed installs only the app package (.appx); they do not install certificates.
Use the Windows 10 Application Deployment (WinAppDeployCmd) tool. Learn more about the WinAppDeployCmd
tool.
Starting in Windows 10, Version 1511, you can use Device Portal to deploy from your browser to a mobile device
running Windows 10, Version 1511 or later. Use the Apps page in Device Portal to upload an app package (.appx) and
install it on the device.

Failure to install Developer Mode package


Sometimes, due to network or administrative issues, Developer Mode won't install correctly. The Developer Mode
package is required for remote deployment to this PC -- using Device Portal from a browser or Device Discovery to
enable SSH -- but not for local development. Even if you encounter these issues, you can still deploy your app locally
using Visual Studio, or from this device to another device.
See the Known Issues forum to find workarounds to these issues and more.
Failed to locate the package
"Developer Mode package couldnt be located in Windows Update. Error Code 0x80004005 Learn more"
This error may occur due to a network connectivity problem, Enterprise settings, or the package may be missing.
To fix this issue:
1. Ensure your computer is connected to the Internet.
2. If you are on a domain-joined computer, speak to your network administrator. The Developer Mode package, like all
Features on Demand, is blocked by default in WSUS. 2.1. In order to unblock the Developer Mode package in the
current and previous releases, the following KBs should be allowed in WSUS: 4016509, 3180030, 3197985
3. Check for Windows updates in the Settings > Updates and Security > Windows Updates.
4. Verify that the Windows Developer Mode package is present in Settings > System > Apps & Features > Manage
optional features > Add a feature. If it is missing, Windows cannot find the correct package for your computer.
After doing any of the above steps, disable and then re-enable Developer Mode to verify the fix.
Failed to install the package
"Developer Mode package failed to install. Error code 0x80004005 Learn more"
This error may occur due to incompatibilities between your build of Windows and the Developer Mode package.
To fix this issue:
1. Check for Windows updates in the Settings > Updates and Security > Windows Updates.
2. Reboot your computer to ensure all updates are applied.

Use group policies or registry keys to enable a device


For most developers, you want to use the settings app to enable your device for debugging. In certain scenarios, such as
automated tests, you can use other ways to enable your Windows 10 desktop device for development.
You can use gpedit.msc to set the group policies to enable your device, unless you have Windows 10 Home. If you do
have Windows 10 Home, you need to use regedit or PowerShell commands to set the registry keys directly to enable
your device.
Use gpedit to enable your device
1. Run Gpedit.msc.
2. Go to Local Computer Policy > Computer Configuration > Administrative Templates > Windows Components > App
Package Deployment
3. To enable sideloading, edit the policies to enable:
Allow all trusted apps to install
OR -
To enable developer mode, edit the policies to enable both:
Allow all trusted apps to install
Allows development of Windows Store apps and installing them from an integrated development
environment (IDE)
4. Reboot your machine.
Use regedit to enable your device
1. Run regedit.
2. To enable sideloading, set the value of this DWORD to 1:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock\AllowAllTrustedApps
OR -
To enable developer mode, set the values of this DWORD to 1:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock\AllowDevelopmentWithoutDevLicense
Use PowerShell to enable your device
1. Run PowerShell with administrator privileges.
2. To enable sideloading, run this command:
PS C:\WINDOWS\system32> reg add
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t
REG_DWORD /f /v "AllowAllTrustedApps" /d "1"
OR -
To enable developer mode, run this command:
PS C:\WINDOWS\system32> reg add
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t
REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"

Upgrade your device from Windows 8.1 to Windows 10


When you create or sideload apps on your Windows 8.1 device, you have to install a developer license. If you upgrade
your device from Windows 8.1 to Windows 10, this information remains. Run the following command to remove this
information from your upgraded Windows 10 device. This step is not required if you upgrade directly from Windows 8.1
to Windows 10, Version 1511 or later.
To unregister a developer license
1. Run PowerShell with administrator privileges.
2. Run this command: unregister-windowsdeveloperlicense.
After this you need to enable your device for development as described in this topic so that you can continue to develop
on this device. If you don't do that, you might get an error when you debug your app, or you try to create a package for it.
Here is an example of this error:
Error : DEP0700 : Registration of the app failed.

See Also
Your first app
Publishing your Windows Store app.
How-to articles on developing UWP apps
Code Samples for UWP developers
What's a Universal Windows app?
Sign up for Windows account
Ready to sign up?
3/6/2017 1 min to read Edit Online

Register now for a developer account so you can get your apps into the Windows Store and participate in other
Microsoft programs.
Sign up now!

Opening your developer account


We offer individual and company accounts in locations around the world. Check out our overview of the sign-up
process to see how it works.

Have a name for your app?


As soon as you open your developer account, you can create your app by reserving a name.
Create your first app
8/28/2017 2 min to read Edit Online

Write a UWP app using your favorite programming language

Welcome to the UWP (what's UWP again?) platform! These tutorials will help you create your first UWP app in the
language of your choice. You'll learn how to:
Create UWP projects in Microsoft Visual Studio.
Add UI elements and code to your project.
Use Ink and the Dial in your apps.
Use third party libraries to add new functionality.
Build and debug your app on your local machine.
To get started, choose your favorite language!

C# and XAML
Use your .NET, WPF, or Silverlight skills to build apps using XAML with C#.
Create a "Hello, world" app using XAML with C#
If you want to learn the basics, or just refresh your memory, try reading these:
C# Fundamentals for Absolute Beginners
VB Fundamentals for Absolute Beginners
A Developer's Guide to Windows 10
Microsoft Virtual Academy
If you are ready to attempt something a little more fun than "Hello, World!", try this C# and MonoGame tutorial:
A simple 2D UWP game for the Windows Store, written in C# and MonoGame

JavaScript and HTML


Take advantage of your web skills to build apps using HTML5, CSS3, and JavaScript.
Create a "Hello, world" app using HTML and JavaScript
A simple 2D UWP game for the Windows Store, written in JavaScript and CreateJS
A 3D UWP game for the Windows Store, written in JavaScript and threeJS
A single-page web app with REST API
Need to brush up on your web skills?
JavaScript Fundamentals for Absolute Beginners
HTML5 & CSS3 Fundamentals for Absolute Beginners
Microsoft Virtual Academy

Visual C++ component extensions (C++/CX) and XAML


Take advantage of your C++ programming expertise to build apps using Visual C++ component extensions
(C++/CX) with XAML.
Create a "Hello, world" app using XAML with C++/CX
Learn more about C++ here:
C++: A General Purpose Language and Library Jump Start
Microsoft Virtual Academy

Using features unique to Windows 10


What makes Windows 10 special? Among other things, Ink and the Surface Dial controller.
Using ink in your UWP app
Support the Surface Dial

Cutting Edge ideas


Interested in exploring Virtual Reality?
Adding WebVR to a Babylon.js game

Objective-C
Are you more of an iOS developer?
Use the Windows Bridge for iOS to convert your existing code to a UWP app, and keep developing in
Objective-C.

Cross-platform and mobile development


Need to target Android and iOS? Check out Xamarin.

See Also
Publishing your Windows Store app.
How-to articles on developing UWP apps
Code Samples for UWP developers
What's a Universal Windows app?
Get set up
Sign up for Windows account
Create a "Hello, world" app (XAML)
4/5/2017 7 min to read Edit Online

This tutorial teaches you how to use XAML and C# to create a simple "Hello, world" app for the Universal Windows
Platform (UWP) on Windows 10. With a single project in Microsoft Visual Studio, you can build an app that runs on
any Windows 10 device.
Here you'll learn how to:
Create a new Visual Studio 2017 project that targets Windows 10 and the UWP.
Write XAML to change the UI on your start page.
Run the project on the local desktop in Visual Studio.
Use a SpeechSynthesizer to make the app talk when you press a button.

Before you start...


What's a Universal Windows app?
To complete this tutorial, you need Windows 10 and Visual Studio 2017. Get set up.
We also 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 using the Reset Window Layout command.

NOTE
This tutorial is using Visual Studio Community 2017. If you are using a different version of Visual Studio, it may look a little
different for you.

Video summary

Step 1: Create a new project in Visual Studio.


1. Launch Visual Studio 2017.
2. From the File menu, select New > Project... to open the New Project dialog.
3. From the list of templates on the left, open Installed > Templates > Visual C# > Windows, and then
choose Universal to see the list of UWP project templates.
(If you don't see any Universal templates, you might be missing the components for creating UWP apps. You
can repeat the installation process and add UWP support by clicking Open Visual Studio installer on the
New Project dialog. See Get set up

4. Choose the Blank App (Universal Windows) template, and enter "HelloWorld" as the Name. Select OK.

NOTE
If this is the first time you have used Visual Studio, you might see a Settings dialog asking you to enable Developer mode.
Developer mode is a special setting that enables certain features, such as permission to run apps directly, rather than only
from the Store. For more information, please read Enable your device for development. To continue with this guide, select
Developer mode, click Yes, and close the dialog.
1. The target version/minimum version dialog appears. The default settings are fine for this tutorial, so select
OK to create the project.

2. When your new project opens, its files are displayed in the Solution Explorer pane on the right. You may
need to choose the Solution Explorer tab instead of the Properties tab to see your files.
Although the Blank App (Universal Window) is a minimal template, it still contains a lot of files. These files are
essential to all UWP apps using C#. Every project that you create in Visual Studio contains them.
What's in the files?
To view and edit a file in your project, double-click the file in the Solution Explorer. Expand a XAML file just like a
folder to see its associated code file. XAML files open in a split view that shows both the design surface and the
XAML editor.

NOTE
What is XAML? Extensible Application Markup Language (XAML) is the language used to define your app's user interface. It
can be entered manually, or created using the Visual Studio design tools. A .xaml file has a .xaml.cs code-behind file which
contains the logic. Together, the XAML and code-behind make a complete class. For more information, see XAML overview.

App.xaml and App.xaml.cs


App.xaml is where you declare resources that are used across the app.
App.xaml.cs is the code-behind file for App.xaml. Like all code-behind pages, it contains a constructor that calls
the InitializeComponent method. You don't write the InitializeComponent method. It's generated by Visual Studio, and
its main purpose is to initialize the elements declared in the XAML file.
App.xaml.cs is the entry point for your app.
App.xaml.cs also contains methods to handle activation and suspension of the app.
MainPage.xaml
MainPage.xaml is where 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.
MainPage.xaml.cs is the code-behind page for MainPage.xaml. It's where you add your app logic and event
handlers.
Together these two files define a new class called MainPage , which inherits from Page, in the HelloWorld
namespace.
Package.appxmanifest
A manifest file that describes your app: its name, description, tile, start page, etc.
Includes a list of the files that your app contains.
A set of logo images
Assets/Square150x150Logo.scale-200.png represents your app in the start menu.
Assets/StoreLogo.png represents your app in the Windows Store.
Assets/SplashScreen.scale-200.png is the splash screen that appears when your app starts.

Step 2: Adding a button


Using the designer view
Let's add a button to our page. In this tutorial, you work with just a few of the files listed previously: App.xaml,
MainPage.xaml, and MainPage.xaml.cs.
1. Double-click on MainPage.xaml to open it in the Design view.
You'll notice there is a graphical view on the top part of the screen, and the XAML code view underneath.
You can make changes to either, but for now we'll use the graphical view.

2. Click on the vertical Toolbox tab on the left to open the list of UI controls. (You can click the pin icon in its
title bar to keep it visible.)
3. Expand Common XAML Controls, and drag the Button out to the middle of the design canvas.

If you look at the XAML code window, you'll see that the Button has been added there too:
<Button x:name="button" Content="Button" HorizontalAlignment="Left" Margin = "152,293,0,0" VerticalAlignment="Top"/>

4. Change the button's text.


Click in the XAML code view, and change the Content from "Button" to "Hello, world!".

<Button x:name="button" Content="Hello, world!" HorizontalAlignment="Left" Margin = "152,293,0,0" VerticalAlignment="Top"/>

Notice how the button displayed in the design canvas updates to display the new text.

Step 3: Start the app


At this point, you've created a very simple app. This is a good time to build, deploy, and launch your app and see
what it looks like. You can debug your app on the local machine, in a simulator or emulator, or on a remote device.
Here's the target device menu in Visual Studio.

Start the app on a Desktop device


By default, the app runs on the local machine. The target device menu provides several options for debugging your
app on devices from the desktop device family.
Simulator
Local Machine
Remote Machine
To start debugging on the local machine

1. In the target device menu ( ) on the Standard toolbar, make sure that Local Machine is
selected. (It's the default selection.)
2. Click the Start Debugging button ( ) on the toolbar.
or
From the Debug menu, click Start Debugging.
or
Press F5.
The app opens in a window, and a default splash screen appears first. The splash screen is defined by an image
(SplashScreen.png) and a background color (specified in your app's manifest file).
The splash screen disappears, and then your app appears. It looks like this.

Press the Windows key to open the Start menu, then show all apps. Notice that deploying the app locally adds its
tile to the Start menu. To run the app again later (not in debugging mode), tap or click its tile in the Start menu.
It doesn't do muchyetbut congratulations, you've built your first UWP app!
To stop debugging

Click the Stop Debugging button ( ) in the toolbar.


or
From the Debug menu, click Stop debugging.
or
Close the app window.
Step 3: Event handlers
An "event handler" sounds complicated, but it's just another name for the code that is called when an event
happens (such as the user clicking on your button).
1. Stop the app from running, if you haven't already.
2. Double-click on the button control on the design canvas to make Visual Studio create an event handler for
your button.
You can of course, create all the code manually too. Or you can click on the button to select it, and look in
the Properties pane on the lower right. If you switch to Events (the little lightning bolt) you can add the
name of your event handler.
3. Edit the event handler code in MainPage.xaml.cs, the code-behind page. This is where things get interesting.
The default event handler looks like this:

private void Button_Click(object sender, RouteEventArgs e)


{

Let's change it, so it looks like this:

private async void Button_Click(object sender, RoutedEventArgs e)


{
MediaElement mediaElement = new MediaElement();
var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
Windows.Media.SpeechSynthesis.SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("Hello, World!");
mediaElement.SetSource(stream, stream.ContentType);
mediaElement.Play();
}

Make sure you include the async keyword as well, or you'll get an error when you try to run the app.
What did we just do?
This code uses some Windows APIs to create a speech synthesis object, and then gives it some text to say. (For
more information on using SpeechSynthesis, see the SpeechSynthesis namespace docs.)
When you run the app and click on the button, your computer (or phone) will literally say "Hello, World!".

Summary
Congratulations, you've created your first app for Windows 10 and the UWP!
To learn how to use XAML for laying out the controls your app will use, try the grid tutorial, or jump straight to next
steps?

See Also
Your first app
Publishing your Windows Store app.
How-to articles on developing UWP apps
Code Samples for UWP developers
What's a Universal Windows app?
Sign up for Windows account
Create a "Hello, world" app (JS)
7/3/2017 4 min to read Edit Online

This tutorial teaches you how to use JavaScript and HTML to create a simple "Hello, world" app that targets the
Universal Windows Platform (UWP) on Windows 10. With a single project in Microsoft Visual Studio, you can build
an app that runs on any Windows 10 device.

NOTE
This tutorial is using Visual Studio Community 2017. If you are using a different version of Visual Studio, it may look a little
different for you.

Here you'll learn how to:


Create a new Visual Studio 2017 project that targets Windows 10 and the UWP.
Add HTML and JavaScript content
Run the project on the local desktop in Visual Studio

Before you start...


What's a Universal Windows app?
To complete this tutorial, you need Windows 10 and Visual Studio 2017. Get set up.
We also 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 using the Reset Window Layout command.

Step 1: Create a new project in Visual Studio.


1. Launch Visual Studio 2017.
2. From the File menu, select New > Project... to open the New Project dialog.
3. From the list of templates on the left, open Installed > Templates > JavaScript, and then choose
Windows Universal to see the list of UWP project templates.
(If you don't see any Universal templates, you might be missing the components for creating UWP apps. You
can repeat the installation process and add UWP support by clicking Open Visual Studio installer on the
New Project dialog. See Get set up
4. Choose the Blank App (Universal Windows) template, and enter "HelloWorld" as the Name. Select OK.
NOTE
If this is the first time you have used Visual Studio, you might see a Settings dialog asking you to enable Developer mode.
Developer mode is a special setting that enables certain features, such as permission to run apps directly, rather than only
from the Store. For more information, please read Enable your device for development. To continue with this guide, select
Developer mode, click Yes, and close the dialog.
1. The target version/minimum version dialog appears. The default settings are fine for this tutorial, so select
OK to create the project.

2. When your new project opens, its files are displayed in the Solution Explorer pane on the right. You may
need to choose the Solution Explorer tab instead of the Properties tab to see your files.

Although the Blank App (Universal Window) is a minimal template, it still contains a lot of files. These files are
essential to all UWP apps using JavaScript. Every project that you create in Visual Studio contains them.
What's in the files?
To view and edit a file in your project, double-click the file in the Solution Explorer.
default.css
The default stylesheet used by the app.
main.js
The default JavaScript file. It's referenced in the index.html file.
index.html
The app's web page, loaded and displayed when the app is launched.
A set of logo images
Assets/Square150x150Logo.scale-200.png represents your app in the start menu.
Assets/StoreLogo.png represents your app in the Windows Store.
Assets/SplashScreen.scale-200.png is the splash screen that appears when your app starts.
Step 2: Adding a button
Click on index.html to select it in the editor, and change the HTML it contains to read:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8" />
<title>Hello World</title>
<script src="js/main.js"></script>
<link href="css/default.css" rel="stylesheet" />
</head>

<body>
<p>Click the button..</p>
<button id="button">Hello world!</button>
</body>

</html>

It should look like this:

This HTML references the main.js that will contain our JavaScript, and then adds a single line of text and a single
button to the body of the web page. The button is given an ID so the JavaScript will be able to reference it.

Step 3: Adding some JavaScript


Now we'll add the JavaScript. Click on main.js to select it, and add the following:
// Your code here!

window.onload = function () {
document.getElementById("button").onclick = function (evt) {
sayHello()
}
}

function sayHello() {
var messageDialog = new Windows.UI.Popups.MessageDialog("Hello, world!", "Alert");
messageDialog.showAsync();
}

It should look like this:

This JavaScript declares two functions. The window.onload function is called automatically when index.html is
displayed. It finds the button (using the ID we declared) and adds an onclick handler: the method that will be called
when the button is clicked.
The second function, sayHello(), creates and displays a dialog. This is very similar to the Alert() function you may
know from previous JavaScript development.

Step 4: Run the app!


Now you can run the app by pressing F5. The app will load, the web page will be displayed. Click on the button, and
the message dialog will pop-up.
Summary
Congratulations, you've created a JavaScript app for Windows 10 and the UWP! This is a ridiculously simple
example, however, you can now start adding your favorite JavaScript libraries and frameworks to create your own
app. And as it's a UWP app, you can publish it to the Store. For example of how third party frameworks can be
added, see these projects:
A simple 2D UWP game for the Windows Store, written in JavaScript and CreateJS
A 3D UWP game for the Windows Store, written in JavaScript and threeJS
Create a "Hello world" app in C++
9/1/2017 16 min to read Edit Online

With Microsoft Visual Studio 2017, you can use C++ to develop an app that runs on Windows 10 with a UI that's
defined in Extensible Application Markup Language (XAML).

NOTE
This tutorial is using Visual Studio Community 2017. If you are using a different version of Visual Studio, it may look a little
different for you.

Before you start...


To complete this tutorial, you must use Visual Studio Community 2017, or one of the non-Community versions
of Visual Studio 2017, on a computer that's running Windows 10. To download, see Get the tools.
We assume you have a basic understanding of standard C++, XAML, and the concepts in the XAML overview.
We assume you're using the default window layout in Visual Studio. To reset to the default layout, on the menu
bar, choose Window > Reset Window Layout.

Comparing C++ desktop apps to Windows apps


If you're coming from a background in Windows desktop programming in C++, you'll probably find that some
aspects of writing apps for the UWP are familiar, but other aspects require some learning.
What's the same?
You can use the STL, the CRT (with some exceptions), and any other C++ library as long as the code does
not attempt to call Windows functions that are not accessible from the Windows Runtime environment.
If you're accustomed to visual designers, you can still use the designer built into Microsoft Visual Studio, or
you can use the more full-featured Blend for Visual Studio. If you're accustomed to coding UI by hand, you
can hand-code your XAML.
You're still creating apps that use Windows operating system types and your own custom types.
You're still using the Visual Studio debugger, profiler, and other development tools.
You're still creating apps that are compiled to native machine code by the Visual C++ compiler. Windows
Store apps in C++ don't execute in a managed runtime environment.
What's new?
The design principles for Windows Store apps and Universal Windows apps are very different from those
for desktop apps. Window borders, labels, dialog boxes, and so on, are de-emphasized. Content is foremost.
Great Universal Windows apps incorporate these principles from the very beginning of the planning stage.
You're using XAML to define the entire UI. The separation between UI and core program logic is much
clearer in a Windows Universal app than in an MFC or Win32 app. Other people can work on the
appearance of the UI in the XAML file while you're working on the behavior in the code file.
You're primarily programming against a new, easy-to-navigate, object-oriented API, the Windows Runtime,
although on Windows devices Win32 is still available for some functionality.
You use C++/CX to consume and create Windows Runtime objects. C++/CX enables C++ exception
handling, delegates, events, and automatic reference counting of dynamically created objects. When you use
C++/CX, the details of the underlying COM and Windows architecture are hidden from your app code. For
more information, see C++/CX Language Reference.
Your app is compiled into a package that also contains metadata about the types that your app contains, the
resources that it uses, and the capabilities that it requires (file access, internet access, camera access, and so
forth).
In the Windows Store and Windows Phone Store your app is verified as safe by a certification process and
made discoverable to millions of potential customers.

Hello World Store app in C++


Our first app is a "Hello World" that demonstrates some basic features of interactivity, layout, and styles. We'll
create an app from the Windows Universal app project template. If you've developed apps for Windows 8.1 and
Windows Phone 8.1 before, you might remember that you had to have three projects in Visual Studio, one for the
Windows app, one for the phone app, and another with shared code. The Windows 10 Universal Windows Platform
(UWP) makes it possible to have just one project, which runs on all devices, including desktop and laptop
computers running Windows 10, devices such as tablets, mobile phones, VR devices and so on.
We'll start with the basics:
How to create a Universal Windows project in Visual Studio 2017.
How to understand the projects and files that are created.
How to understand the extensions in Visual C++ component extensions (C++/CX), and when to use them.
First, create a solution in Visual Studio
1. In Visual Studio, on the menu bar, choose File > New > Project.
2. In the New Project dialog box, in the left pane, expand Installed > Visual C++ > Windows Universal.

NOTE
You may be prompted to install the Windows Universal tools for C++ development.

1. In the center pane, select Blank App (Universal Windows).


(If you don't see these options, make sure you have the Universal Windows App Development Tools
installed. See Get set up for more info.)
2. Enter a name for the project. We'll name it HelloWorld.
3. Choose the OK button.

NOTE
If this is the first time you have used Visual Studio, you might see a Settings dialog asking you to enable Developer mode.
Developer mode is a special setting that enables certain features, such as permission to run apps directly, rather than only
from the Store. For more information, please read Enable your device for development. To continue with this guide, select
Developer mode, click Yes, and close the dialog.

Your project files are created.


Before we go on, lets look at what's in the solution.
About the project files
Every .xaml file in a project folder has a corresponding .xaml.h file and .xaml.cpp file in the same folder and a .g file
and a .g.hpp file in the Generated Files folder, which is on disk but not part of the project. You modify the XAML
files to create UI elements and connect them to data sources (DataBinding). You modify the .h and .cpp files to add
custom logic for event handlers. The auto-generated files represent the transformation of the XAML markup into
C++. Don't modify these files, but you can study them to better understand how the code-behind works. Basically,
the generated file contains a partial class definition for a XAML root element; this class is the same class that you
modify in the *.xaml.h and .cpp files. The generated files declare the XAML UI child elements as class members so
that you can reference them in the code you write. At build time, the generated code and your code are merged
into a complete class definition and then compiled.
Let's look first at the project files.
App.xaml, App.xaml.h, App.xaml.cpp: Represent the Application object, which is an app's entry point.
App.xaml contains no page-specific UI markup, but you can add UI styles and other elements that you want to
be accessible from any page. The code-behind files contain handlers for the OnLaunched and OnSuspending
events. Typically, you add custom code here to initialize your app when it starts and perform cleanup when it's
suspended or terminated.
MainPage.xaml, MainPage.xaml.h, MainPage.xaml.cpp:Contain the XAML markup and code-behind for
the default "start" page in an app. It has no navigation support or built-in controls.
pch.h, pch.cpp: A precompiled header file and the file that includes it in your project. In pch.h, you can include
any headers that do not change often and are included in other files in the solution.
Package.appxmanifest: An XML file that describes the device capabilities that your app requires, and the app
version info and other metadata. To open this file in the Manifest Designer, just double-click it.
HelloWorld_TemporaryKey.pfx:A key that enables deployment of the app on this machine, from Visual
Studio.

A first look at the code


If you examine the code in App.xaml.h, App.xaml.cpp in the shared project, you'll notice that it's mostly C++ code
that looks familiar. However, some syntax elements might not be as familiar if you are new to Windows Runtime
apps, or you've worked with C++/CLI. Here are the most common non-standard syntax elements you'll see in
C++/CX:
Ref classes
Almost all Windows Runtime classes, which includes all the types in the Windows API--XAML controls, the pages in
your app, the App class itself, all device and network objects, all container types--are declared as a ref class. (A few
Windows types are value class or value struct). A ref class is consumable from any language. In C++, the lifetime
of these types is governed by automatic reference counting (not garbage collection) so that you never explicitly
delete these objects. You can create your own ref classes as well.

namespace HelloWorld
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public ref class MainPage sealed
{
public:
MainPage();
};
}

All Windows Runtime types must be declared within a namespace and unlike in ISO C++ the types themselves
have an accessibility modifier. The public modifier makes the class visible to Windows Runtime components
outside the namespace. The sealed keyword means the class cannot serve as a base class. Almost all ref classes are
sealed; class inheritance is not broadly used because Javascript does not understand it.
ref new and ^ (hats)
You declare a variable of a ref class by using the ^ (hat) operator, and you instantiate the object with the ref new
keyword. Thereafter you access the object's instance methods with the -> operator just like a C++ pointer. Static
methods are accessed with the :: operator just as in ISO C++.
In the following code, we use the fully qualified name to instantiate an object, and use the -> operator to call an
instance method.

Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapImage =
ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();

bitmapImage->SetSource(fileStream);

Typically, in a .cpp file we would add a using namespace Windows::UI::Xaml::Media::Imaging directive and the auto keyword,
so that the same code would look like this:

auto bitmapImage = ref new BitmapImage();


bitmapImage->SetSource(fileStream);

Properties
A ref class can have properties, which, just as in managed languages, are special member functions that appear as
fields to consuming code.

public ref class SaveStateEventArgs sealed


{
public:
// Declare the property
property Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ PageState
{
Windows::Foundation::Collections::IMap<Platform::String^, Platform::Object^>^ get();
}
...
};

...
// consume the property like a public field
void PhotoPage::SaveState(Object^ sender, Common::SaveStateEventArgs^ e)
{
if (mruToken != nullptr && !mruToken->IsEmpty())
{
e->PageState->Insert("mruToken", mruToken);
}
}

Delegates
Just as in managed languages, a delegate is a reference type that encapsulates a function with a specific signature.
They are most often used with events and event handlers

// Delegate declaration (within namespace scope)


public delegate void LoadStateEventHandler(Platform::Object^ sender, LoadStateEventArgs^ e);

// Event declaration (class scope)


public ref class NavigationHelper sealed
{
public:
event LoadStateEventHandler^ LoadState;
};

// Create the event handler in consuming class


MainPage::MainPage()
{
auto navigationHelper = ref new Common::NavigationHelper(this);
navigationHelper->LoadState += ref new Common::LoadStateEventHandler(this, &MainPage::LoadState);
}

Adding content to the app


Let's add some content to the app.
Step 1: Modify your start page
1. In Solution Explorer, open MainPage.xaml.
2. Create controls for the UI by adding the following XAML to the root Grid, immediately before its closing tag.
It contains a StackPanel that has a TextBlock that asks the user's name, a TextBox element that accepts
the user's name, a Button, and another TextBlock element.

<StackPanel x:Name="contentPanel" Margin="120,30,0,0">


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

3. At this point, you have created a very basic Universal Windows app. To see what the UWP app looks like,
press F5 to build, deploy, and run the app in debugging mode.
The default splash screen appears first. It has an imageAssets\SplashScreen.scale-100.pngand a background
color that are specified in the app's manifest file. To learn how to customize the splash screen, see Adding a splash
screen.
When the splash screen disappears, your app appears. It displays the main page of the App.

It doesn't do muchyetbut congratulations, you've built your first Universal Windows Platform app!
To stop debugging and close the app, return to Visual Studio and press Shift+F5.
For more information, see Run a Store app from Visual Studio.
In the app, you can type in the TextBox, but clicking the Button doesn't do anything. In later steps, you create an
event handler for the button's Click event, which displays a personalized greeting.

Step 2: Create an event handler


1. In MainPage.xaml, in either XAML or design view, select the "Say Hello" Button in the StackPanel you added
earlier.
2. Open the Properties Window by pressing F4, and then choose the Events button ( ).
3. Find the Click event. In its text box, type the name of the function that handles the Click event. For this
example, type "Button_Click".
4. Press Enter. The event handler method is created in MainPage.xaml.cpp and opened so that you can add the
code that's executed when the event occurs.
At the same time, in MainPage.xaml, the XAML for the Button is updated to declare the Click event handler,
like this:

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

You could also have simply added this to the xaml code manually, which can be helpful if the designer
doesn't load. If you enter this manually, type "Click" and then let IntelliSense pop up the option to add a new
event handler. That way, Visual Studio creates the necessary method declaration and stub.
The designer fails to load if an unhandled exception occurs during rendering. Rendering in the designer
involves running a design-time version of the page. It can be helpful to disable running user code. You can
do this by changing the setting in the Tools, Options dialog box. Under XAML Designer, uncheck Run
project code in XAML designer (if supported).
5. In MainPage.xaml.cpp, add the following code to the Button_Click event handler that you just created. This
code retrieves the user's name from the nameInput TextBox control and uses it to create a greeting. The
greetingOutput TextBlock displays the result.

void HelloWorld::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)


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

6. Set the project as the startup, and then press F5 to build and run the app. When you type a name in the text
box and click the button, the app displays a personalized greeting.
Step 3: 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 that have a light style. The
system resources also include a light theme. Let's try it out and see what it looks like.
To switch to the dark theme
1. Open App.xaml.
2. In the opening Application tag, edit the RequestedTheme property and set its value to Dark:

RequestedTheme="Dark"

Here's the full Application tag with the dark theme :

<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="Dark">

3. Press F5 to build and run it. Notice that it uses the dark theme.
Which theme should you use? Whichever one you want. Here's our take: for apps that mostly display images or
video, we recommend the dark theme; for apps that contain a lot of text, we recommend the light theme. If you're
using a custom color scheme, use the theme that goes best with your app's look and feel. In the rest of this tutorial,
we use the Light theme in screenshots.
Note The theme is applied when the app is started and can't be changed while the app is running.
Using system styles
Right now, in the Windows app the text is very small and difficult to read. Let's fix that by applying a system style.
To change the style of an element
1. In the Windows project, open MainPage.xaml.
2. In either XAML or design view, select the "What's your name?"TextBlock that you added earlier.
3. In the Properties window (F4), choose the Properties button ( ) in the upper right.
4. Expand the Text group and set the font size to 18 px.
5. Expand the Miscellaneous group and find the Style property.
6. Click the property marker (the green box to the right of the Style property), and then, on the menu, choose
System Resource > BaseTextBlockStyle.
BaseTextBlockStyle is a resource that's defined in the ResourceDictionary in \Program Files\Windows
Kits\10\Include\winrt\xaml\design\generic.xaml.
On the XAML design surface, the appearance of the text changes. In the XAML editor, the XAML for the
TextBlock is updated:

<TextBlock Text="What's your name?" Style="{StaticResource BaseTextStyle}"/>

7. Repeat the process to set the font size and assign the BaseTextBlockStyle to the greetingOutput TextBlock
element.
Tip Although there's no text in this TextBlock, when you move the pointer over the XAML design surface, a
blue outline shows where it is so that you can select it.
Your XAML now looks like this:

<StackPanel x:Name="contentPanel" Margin="120,30,0,0">


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

8. Press F5 to build and run the app. It now looks like this:
Step 4: Adapt the UI to different window sizes
Now we'll make the UI adapt to different screen sizes so it looks good on mobile devices. To do this, you add a
VisualStateManager and set properties that are applied for different visual states.
To adjust the UI layout
1. In the XAML editor, add this block of XAML after the opening tag of the root Grid element.

<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="wideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="641" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="narrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="contentPanel.Margin" Value="20,30,0,0"/>
<Setter Target="inputPanel.Orientation" Value="Vertical"/>
<Setter Target="inputButton.Margin" Value="0,4,0,0"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

2. Debug the app on the local machine. Notice that the UI looks the same as before unless the window gets
narrower than 641 device-independent pixels (DIPs).
3. Debug the app on the mobile device emulator. Notice that the UI uses the properties you defined in the
narrowState and appears correctly on the small screen.
If you've used a VisualStateManager in previous versions of XAML, you might notice that the XAML here uses a
simplified syntax.
The VisualState named wideState has an AdaptiveTrigger with its MinWindowWidth property set to 641. This
means that the state is to be applied only when the window width is not less than the minimum of 641 DIPs. You
don't define any Setter objects for this state, so it uses the layout properties you defined in the XAML for the page
content.
The second VisualState, narrowState , has an AdaptiveTrigger with its MinWindowWidth property set to 0. This
state is applied when the window width is greater than 0, but less than 641 DIPs. (At 641 DIPs, the wideState is
applied.) In this state, you do define some Setter objects to change the layout properties of controls in the UI:
You reduce the left margin of the contentPanel element from 120 to 20.
You change the Orientation of the inputPanel element from Horizontal to Vertical.
You add a top margin of 4 DIPs to the inputButton element.
Summary
Congratulations, you've completed the first tutorial! It taught how to add content to Windows Universal apps, how
to add interactivity to them, and how to change their appearance.

Next steps
If you have a Windows Universal app project that targets Windows 8.1 and/or Windows Phone 8.1, you can port it
to Windows 10. There is no automatic process for this, but you can do it manually. Start with a new Windows
Universal project to get the latest project system structure and manifest files, copy your code files into the project's
directory structure, add the items to your project, and rewrite your XAML using the VisualStateManager
according to the guidance in this topic. For more information, see Porting a Windows Runtime 8 project to a
Universal Windows Platform (UWP) project and Porting to the Universal Windows Platform (C++).
If you have existing C++ code that you want to integrate with a UWP app, such as to create a new UWP UI for an
existing application, see How to: Use existing C++ code in a Universal Windows project.
Support ink in your UWP app
8/28/2017 11 min to read Edit Online

Surface Pen (available for purchase at the Microsoft Store).


This tutorial steps through how to create a basic Universal Windows Platform (UWP) app that supports writing and
drawing with Windows Ink. We use snippets from a sample app, which you can download from GitHub (see
Sample code), to demonstrate the various features and associated Windows Ink APIs (see Components of the
Windows Ink platform) discussed in each step.
We focus on the following:
Adding basic ink support
Adding an ink toolbar
Supporting handwriting recognition
Supporting basic shape recognition
Saving and loading ink
For more detail about implementing these features, see Pen interactions and Windows Ink in UWP apps.

Introduction
With Windows Ink, you can provide your customers with the digital equivalent of almost any pen-and-paper
experience imaginable, from quick, handwritten notes and annotations to whiteboard demos, and from
architectural and engineering drawings to personal masterpieces.

Prerequisites
A computer (or a virtual machine) running the current version of Windows 10
Visual Studio 2017 and the RS2 SDK
Windows 10 SDK (10.0.15063.0)
If you're new to Universal Windows Platform (UWP) app development with Visual Studio, have a look through
these topics before you start this tutorial:
Get set up
Create a "Hello, world" app (XAML)
[OPTIONAL] A digital pen and a computer with a display that supports input from that digital pen.
> [!NOTE] > While Windows Ink can support drawing with a mouse and touch (we show how to do this in Step
3 of this tutorial) for an optimal Windows Ink experience, we recommend that you have a digital pen and a
computer with a display that supports input from that digital pen.

Sample code
Throughout this tutorial, we use a sample ink app to demonstrate the concepts and functionality discussed.
Download this Visual Studio sample and source code from GitHub at windows-appsample-get-started-ink sample:
1. Select the green Clone or download button

2. If you have a GitHub account, you can clone the repo to your local machine by choosing Open in Visual
Studio
3. If you don't have a GitHub account, or you just want a local copy of the project, choose Download ZIP (you'll
have to check back regularly to download the latest updates)

IMPORTANT
Most of the code in the sample is commented out. As we go through each step, you'll be asked to uncomment various
sections of the code. In Visual Studio, just highlight the lines of code, and press CTRL-K and then CTRL-U.

Components of the Windows Ink platform


These objects provide the bulk of the inking experience for UWP apps.

COMPONENT DESCRIPTION

InkCanvas A XAML UI platform control that, by default, receives and


displays all input from a pen as either an ink stroke or an
erase stroke.

InkPresenter A code-behind object, instantiated along with an InkCanvas


control (exposed through the InkCanvas.InkPresenter
property). This object provides all default inking functionality
exposed by the InkCanvas, along with a comprehensive set of
APIs for additional customization and personalization.

InkToolbar A XAML UI platform control containing a customizable and


extensible collection of buttons that activate ink-related
features in an associated InkCanvas.

IInkD2DRenderer Enables the rendering of ink strokes onto the designated


We do not cover this functionality here, for more information, Direct2D device context of a Universal Windows app, instead
see the Complex ink sample. of the default InkCanvas control.
Step 1: Run the sample
After you've downloaded the RadialController sample app, verify that it runs:
1. Open the sample project in Visual Studio.
2. Set the Solution Platforms dropdown to a non-ARM selection.
3. Press F5 to compile, deploy, and run.

NOTE
Alternatively, you can select Debug > Start debugging menu item, or select the Local Machine Run button shown
here.

The app window opens, and after a splash screen appears for a few seconds, youll see this initial screen.

Okay, we now have the basic UWP app that well use throughout the rest of this tutorial. In the following steps, we
add our ink functionality.

Step 2: Use InkCanvas to support basic inking


Perhaps you've probably already noticed that the app, in it's initial form, doesn't let you draw anything with the
pen (although you can use the pen as a standard pointer device to interact with the app).
Let's fix that little shortcoming in this step.
To add basic inking functionality, just place an InkCanvas UWP platform control on the appropriate page in your
app.

NOTE
An InkCanvas has default Height and Width properties of zero, unless it is the child of an element that automatically sizes
its child elements.

In the sample:
1. Open the MainPage.xaml.cs file.
2. Find the code marked with the title of this step ("// Step 2: Use InkCanvas to support basic inking").
3. Uncomment the following lines. (These references are required for the functionality used in the subsequent
steps).

using Windows.UI.Input.Inking;
using Windows.UI.Input.Inking.Analysis;
using Windows.UI.Xaml.Shapes;
using Windows.Storage.Streams;

1. Open the MainPage.xaml file.


2. Find the code marked with the title of this step ("<!-- Step 2: Basic inking with InkCanvas -->").
3. Uncomment the following line.

<InkCanvas x:Name="inkCanvas" />

That's it!
Now run the app again. Go ahead and scribble, write your name, or (if you're holding a mirror or have a very good
memory) draw your self-portrait.
Step 3: Support inking with touch and mouse
You'll notice that, by default, ink is supported for pen input only. If you try to write or draw with your finger, your
mouse, or your touchpad, you'll be disappointed.
To turn that frown upside down , you need to add a second line of code. This time its in the code-behind for the
XAML file in which you declared your InkCanvas.
In this step, we introduce the InkPresenter object, which provides finer-grained management of the input,
processing, and rendering of ink input (standard and modified) on your InkCanvas.

NOTE
Standard ink input (pen tip or eraser tip/button) is not modified with a secondary hardware affordance, such as a pen barrel
button, right mouse button, or similar mechanism.

To enable mouse and touch inking, set the InputDeviceTypes property of the InkPresenter to the combination of
CoreInputDeviceTypes values that you want.
In the sample:
1. Open the MainPage.xaml.cs file.
2. Find the code marked with the title of this step ("// Step 3: Support inking with touch and mouse").
3. Uncomment the following lines.
inkCanvas.InkPresenter.InputDeviceTypes =
Windows.UI.Core.CoreInputDeviceTypes.Mouse |
Windows.UI.Core.CoreInputDeviceTypes.Touch |
Windows.UI.Core.CoreInputDeviceTypes.Pen;

Run the app again and you'll find that all your finger-painting-on-a-computer-screen dreams have come true!

NOTE
When specifying input device types, you must indicate support for each specific input type (including pen), because setting
this property overrides the default InkCanvas setting.

Step 4: Add an ink toolbar


The InkToolbar is a UWP platform control that provides a customizable and extensible collection of buttons for
activating ink-related features.
By default, the InkToolbar includes a basic set of buttons that let users quickly select between a pen, a pencil, a
highlighter, or an eraser, any of which can be used together with a stencil (ruler or protractor). The pen, pencil, and
highlighter buttons each also provide a flyout for selecting ink color and stroke size.
To add a default InkToolbar to an inking app, just place it on the same page as your InkCanvas and associate the
two controls.
In the sample
1. Open the MainPage.xaml file.
2. Find the code marked with the title of this step ("<!-- Step 4: Add an ink toolbar -->").
3. Uncomment the following lines.

<InkToolbar x:Name="inkToolbar"
VerticalAlignment="Top"
Margin="10,0,10,0"
TargetInkCanvas="{x:Bind inkCanvas}">
</InkToolbar>

NOTE
To keep the UI and code as uncluttered and simple as possible, we use a basic Grid layout and declare the InkToolbar after
the InkCanvas in a grid row. If you declare it before the InkCanvas, the InkToolbar is rendered first, below the canvas and
inaccessible to the user.

Now run the app again to see the InkToolbar and try out some of the tools.
Challenge: Add a custom button

Here's an example of a custom InkToolbar (from Sketchpad in the Windows Ink Workspace).

For more details about customizing an InkToolbar, see Add an InkToolbar to a Universal Windows
Platform (UWP) inking app.

Step 5: Support handwriting recognition


Now that you can write and draw in your app, let's try to do something useful with those scribbles.
In this step, we use the handwriting recognition features of Windows Ink to try to decipher what you've written.

NOTE
Handwriting recognition can be improved through the Pen & Windows Ink settings:
1. Open the Start menu and select Settings.
2. From the Settings screen select Devices > Pen & Windows Ink.
3. Select Get to know my handwriting to open the Handwriting Personalization dialog.

In the sample:
1. Open the MainPage.xaml file.
2. Find the code marked with the title of this step ("<!-- Step 5: Support handwriting recognition -->").
3. Uncomment the following lines.

<Button x:Name="recognizeText"
Content="Recognize text"
Grid.Row="0" Grid.Column="0"
Margin="10,10,10,10"
Click="recognizeText_ClickAsync"/>
<TextBlock x:Name="recognitionResult"
Text="Recognition results: "
VerticalAlignment="Center"
Grid.Row="0" Grid.Column="1"
Margin="50,0,0,0" />

1. Open the MainPage.xaml.cs file.


2. Find the code marked with the title of this step (" Step 5: Support handwriting recognition").
3. Uncomment the following lines.
These are the global variables required for this step.

InkAnalyzer analyzerText = new InkAnalyzer();


IReadOnlyList<InkStroke> strokesText = null;
InkAnalysisResult resultText = null;
IReadOnlyList<IInkAnalysisNode> words = null;

This is the handler for the Recognize text button, where we do the recognition processing.

private async void recognizeText_ClickAsync(object sender, RoutedEventArgs e)


{
strokesText = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
// Ensure an ink stroke is present.
if (strokesText.Count > 0)
{
analyzerText.AddDataForStrokes(strokesText);

resultText = await analyzerText.AnalyzeAsync();

if (resultText.Status == InkAnalysisStatus.Updated)
{
words = analyzerText.AnalysisRoot.FindNodes(InkAnalysisNodeKind.InkWord);
foreach (var word in words)
{
InkAnalysisInkWord concreteWord = (InkAnalysisInkWord)word;
foreach (string s in concreteWord.TextAlternates)
{
recognitionResult.Text += s;
}
}
}
analyzerText.ClearDataForAllStrokes();
}
}

1. Run the app again, write something, and then click the Recognize text button
2. The results of the recognition are displayed beside the button
Challenge 1: International recognition
Windows Ink supports text recognition for many of the of the languages supported by Windows.
Each language pack includes a handwriting recognition engine that can be installed with the
language pack.
Target a specific language by querying the installed handwriting recognition engines.
For more details about international handwriting recognition, see Recognize Windows Ink strokes
as text.

Challenge 2: Dynamic recognition

For this tutorial, we require that a button be pressed to initiate recognition. You can also perform
dynamic recognition by using a basic timing function.
For more details about dynamic recognition, see Recognize Windows Ink strokes as text.

Step 6: Recognize shapes


Ok, so now you can convert your handwritten notes into something a little more legible. But what about those
shaky, caffeinated doodles from your morning Flowcharters Anonymous meeting?
Using ink analysis, your app can also recognize a set of core shapes, including:
Circle
Diamond
Drawing
Ellipse
EquilateralTriangle
Hexagon
IsoscelesTriangle
Parallelogram
Pentagon
Quadrilateral
Rectangle
RightTriangle
Square
Trapezoid
Triangle
In this step, we use the shape-recognition features of Windows Ink to try to clean up your doodles.
For this example, we don't attempt to redraw ink strokes (although that's possible). Instead, we add a standard
canvas under the InkCanvas where we draw equivalent Ellipse or Polygon objects derived from the original ink. We
then delete the corresponding ink strokes.
In the sample:
1. Open the MainPage.xaml file
2. Find the code marked with the title of this step ("<!-- Step 6: Recognize shapes -->")
3. Uncomment this line.
<Canvas x:Name="canvas" />

And these lines.

<Button Grid.Row="1" x:Name="recognizeShape" Click="recognizeShape_ClickAsync"


Content="Recognize shape"
Margin="10,10,10,10" />

1. Open the MainPage.xaml.cs file


2. Find the code marked with the title of this step ("// Step 6: Recognize shapes")
3. Uncomment these lines:

private async void recognizeShape_ClickAsync(object sender, RoutedEventArgs e)


{
...
}

private void DrawEllipse(InkAnalysisInkDrawing shape)


{
...
}

private void DrawPolygon(InkAnalysisInkDrawing shape)


{
...
}

1. Run the app, draw some shapes, and click the Recognize shape button
Here's an example of a rudimentary flowchart from a digital napkin.
Here's the same flowchart after shape recognition.

Step 7: Save and load ink


So, you're done doodling and you like what you see, but think you might like to tweak a couple of things later? You
can save your ink strokes to an Ink Serialized Format (ISF) file and load them for editing whenever the inspiration
strikes.
The ISF file is a basic GIF image that includes additional metadata describing ink-stroke properties and behaviors.
Apps that are not ink enabled can ignore the extra metadata and still load the basic GIF image (including alpha-
channel background transparency).
In this step, we hook up the Save and Load buttons located beside the ink toolbar.
In the sample:
1. Open the MainPage.xaml file.
2. Find the code marked with the title of this step ("<!-- Step 7: Saving and loading ink -->").
3. Uncomment the following lines.

<Button x:Name="buttonSave"
Content="Save"
Click="buttonSave_ClickAsync"
Width="100"
Margin="5,0,0,0"/>
<Button x:Name="buttonLoad"
Content="Load"
Click="buttonLoad_ClickAsync"
Width="100"
Margin="5,0,0,0"/>

1. Open the MainPage.xaml.cs file.


2. Find the code marked with the title of this step ("// Step 7: Save and load ink").
3. Uncomment the following lines.

private async void buttonSave_ClickAsync(object sender, RoutedEventArgs e)


{
...
}

private async void buttonLoad_ClickAsync(object sender, RoutedEventArgs e)


{
...
}

1. Run the app and draw something.


2. Select the Save button and save your drawing.
3. Erase the ink or restart the app.
4. Select the Load button and open the ink file you just saved.
Challenge: Use the clipboard to copy and paste ink strokes

Windows ink also supports copying and pasting ink strokes to and from the clipboard. For more
details about using the clipboard with ink, see Store and retrieve Windows Ink stroke data.

Summary
Congratulations, you've completed the Input: Support ink in your UWP app tutorial ! We showed you the basic
code required for supporting ink in your UWP apps, and how to provide some of the richer user experiences
supported by the Windows Ink platform.

Related articles
Pen interactions and Windows Ink in UWP apps
Samples
Simple ink sample (C#/C++)
Complex ink sample (C++)
Ink sample (JavaScript)
Get Started Tutorial: Support ink in your UWP app
Coloring book sample
Family notes sample
Support the Surface Dial (and other wheel devices) in
your UWP app
8/28/2017 14 min to read Edit Online

Surface Dial with Surface Studio and Surface Pen (available for purchase at the Microsoft Store).
This tutorial steps through how to customize the user interaction experiences supported by wheel devices such as
the Surface Dial. We use snippets from a sample app, which you can download from GitHub (see Sample code), to
demonstrate the various features and associated RadialController APIs discussed in each step.
We focus on the following:
Specifying which built-in tools are displayed on the RadialController menu
Adding a custom tool to the menu
Controlling haptic feedback
Customizing click interactions
Customizing rotation interactions
For more about implementing these and other features, see Surface Dial interactions in UWP apps.

Introduction
The Surface Dial is a secondary input device that helps users to be more productive when used together with a
primary input device such as pen, touch, or mouse. As a secondary input device, the Dial is typically used with the
non-dominant hand to provide access both to system commands and to other, more contextual, tools and
functionality.
The Dial supports three basic gestures:
Press and hold to display the built-in menu of commands.
Rotate to highlight a menu item (if the menu is active) or to modify the current action in the app (if the menu is
not active).
Click to select the highlighted menu item (if the menu is active) or to invoke a command in the app (if the menu
is not active).

Prerequisites
A computer (or a virtual machine) running Windows 10 Creators Update, or newer
Visual Studio 2017 (10.0.15063.0)
Windows 10 SDK (10.0.15063.0)
A wheel device (only the Surface Dial at this time)
If you're new to Universal Windows Platform (UWP) app development with Visual Studio, have a look through
these topics before you start this tutorial:
Get set up
Create a "Hello, world" app (XAML)

Set up your devices


1. Make sure your Windows device is on.
2. Go to Start, select Settings > Devices > Bluetooth & other devices, and then turn Bluetooth on.
3. Remove the bottom of the Surface Dial to open the battery compartment, and make sure that there are two AAA
batteries inside.
4. If the battery tab is present on the underside of the Dial, remove it.
5. Press and hold the small, inset button next to the batteries until the Bluetooth light flashes.
6. Go back to your Windows device and select Add Bluetooth or other device.
7. In the Add a device dialog, select Bluetooth > Surface Dial. Your Surface Dial should now connect and be
added to the list of devices under Mouse, keyboard, & pen on the Bluetooth & other devices settings page.
8. Test the Dial by pressing and holding it down for a few seconds to display the built-in menu.
9. If the the menu isn't displayed on your screen (the Dial should also vibrate), go back to the Bluetooth settings,
remove the device, and try connecting the device again.

NOTE
Wheel devices can be configured through the Wheel settings:
1. On the Start menu, select Settings. Select Devices > Wheel.

Now youre ready to start this tutorial.

Sample code
Throughout this tutorial, we use a sample app to demonstrate the concepts and functionality discussed.
Download this Visual Studio sample and source code from GitHub at windows-appsample-get-started-
radialcontroller sample:
1. Select the green Clone or download button.

2. If you have a GitHub account, you can clone the repo to your local machine by choosing Open in Visual
Studio.
3. If you don't have a GitHub account, or you just want a local copy of the project, choose Download ZIP (you'll
have to check back regularly to download the latest updates).

IMPORTANT
Most of the code in the sample is commented out. As we go through each step in this topic, you'll be asked to uncomment
various sections of the code. In Visual Studio, just highlight the lines of code, and press CTRL-K and then CTRL-U.

Components that support wheel functionality


These objects provide the bulk of the wheel device experience for UWP apps.

COMPONENT DESCRIPTION

RadialController class and related Represents a wheel input device or accessory such as the
Surface Dial.

IRadialControllerConfigurationInterop / Enables interoperability with a UWP app.


IRadialControllerInterop
We do not cover this functionality here, for more information,
see the Windows classic desktop sample.

Step 1: Run the sample


After you've downloaded the RadialController sample app, verify that it runs:
1. Open the sample project in Visual Studio .
2. Set the Solution Platforms dropdown to a non-ARM selection.
3. Press F5 to compile, deploy, and run.
NOTE
Alternatively, you can select Debug > Start debugging menu item, or select the Local Machine Run button shown here:

The app window opens, and after a splash screen appears for a few seconds, youll see this initial screen.

Okay, we now have the basic UWP app that well use throughout the rest of this tutorial. In the following steps, we
add our RadialController functionality.

Step 2: Basic RadialController functionality


With the app running and in the foreground, press and hold the Surface Dial to display the **RadialController **
menu.
We haven't done any customization for our app yet, so the menu contains a default set of contextual tools.
These images show two variations of the default menu. (There are many others, including just basic system tools
when the Windows Desktop is active and no apps are in the foreground, additional inking tools when an
InkToolbar is present, and mapping tools when youre using the Maps app.
RADIALCONTROLLER MENU (DEFAULT) RADIALCONTROLLER MENU (DEFAULT WITH MEDIA PLAYING)

Now we'll start with some basic customization.

Step 3: Add controls for wheel input


First, let's add the UI for our app:
1. Open the MainPage_Basic.xaml file.
2. Find the code marked with the title of this step ("<!-- Step 3: Add controls for wheel input -->").
3. Uncomment the following lines.

<Button x:Name="InitializeSampleButton"
HorizontalAlignment="Center"
Margin="10"
Content="Initialize sample" />
<ToggleButton x:Name="AddRemoveToggleButton"
HorizontalAlignment="Center"
Margin="10"
Content="Remove Item"
IsChecked="True"
IsEnabled="False"/>
<Button x:Name="ResetControllerButton"
HorizontalAlignment="Center"
Margin="10"
Content="Reset RadialController menu"
IsEnabled="False"/>
<Slider x:Name="RotationSlider" Minimum="0" Maximum="10"
Width="300"
HorizontalAlignment="Center"/>
<TextBlock Text="{Binding ElementName=RotationSlider, Mode=OneWay, Path=Value}"
Margin="0,0,0,20"
HorizontalAlignment="Center"/>
<ToggleSwitch x:Name="ClickToggle"
MinWidth="0"
Margin="0,0,0,20"
HorizontalAlignment="center"/>

At this point, only the Initialize sample button, slider, and toggle switch are enabled. The other buttons are
used in later steps to add and remove RadialController menu items that provide access to the slider and
toggle switch.
Step 4: Customize the basic RadialController menu
Now let's add the code required to enable RadialController access to our controls.
1. Open the MainPage_Basic.xaml.cs file.
2. Find the code marked with the title of this step ("// Step 4: Basic RadialController menu customization").
3. Uncomment the following lines:
The Windows.UI.Input and Windows.Storage.Streams type references are used for functionality in
subsequent steps:

// Using directives for RadialController functionality.


using Windows.UI.Input;

These global objects (RadialController, RadialControllerConfiguration, RadialControllerMenuItem) are


used throughout our app.

private RadialController radialController;


private RadialControllerConfiguration radialControllerConfig;
private RadialControllerMenuItem radialControllerMenuItem;

Here, we specify the Click handler for the button that enables our controls and initializes our custom
RadialController menu item.

InitializeSampleButton.Click += (sender, args) =>


{ InitializeSample(sender, args); };

Next, we initialize our RadialController object and set up handlers for the RotationChanged and
ButtonClicked events.
// Set up the app UI and RadialController.
private void InitializeSample(object sender, RoutedEventArgs e)
{
ResetControllerButton.IsEnabled = true;
AddRemoveToggleButton.IsEnabled = true;

ResetControllerButton.Click += (resetsender, args) =>


{ ResetController(resetsender, args); };
AddRemoveToggleButton.Click += (togglesender, args) =>
{ AddRemoveItem(togglesender, args); };

InitializeController(sender, e);
}

Here, we initialize our custom RadialController menu item. We use CreateForCurrentView to get a
reference to our RadialController object, we set the rotation sensitivity to "1" by using the
RotationResolutionInDegrees property, we then create our RadialControllerMenuItem by using
CreateFromFontGlyph, we add the menu item to the RadialController menu item collection, and
finally, we use SetDefaultMenuItems to clear the default menu items and leave only our custom tool.
// Configure RadialController menu and custom tool.
private void InitializeController(object sender, RoutedEventArgs args)
{
// Create a reference to the RadialController.
radialController = RadialController.CreateForCurrentView();
// Set rotation resolution to 1 degree of sensitivity.
radialController.RotationResolutionInDegrees = 1;

// Create the custom menu items.


// Here, we use a font glyph for our custom tool.
radialControllerMenuItem =
RadialControllerMenuItem.CreateFromFontGlyph("SampleTool", "\xE1E3", "Segoe MDL2 Assets");

// Add the item to the RadialController menu.


radialController.Menu.Items.Add(radialControllerMenuItem);

// Remove built-in tools to declutter the menu.


// NOTE: The Surface Dial menu must have at least one menu item.
// If all built-in tools are removed before you add a custom
// tool, the default tools are restored and your tool is appended
// to the default collection.
radialControllerConfig =
RadialControllerConfiguration.GetForCurrentView();
radialControllerConfig.SetDefaultMenuItems(
new RadialControllerSystemMenuItemKind[] { });

// Declare input handlers for the RadialController.


// NOTE: These events are only fired when a custom tool is active.
radialController.ButtonClicked += (clicksender, clickargs) =>
{ RadialController_ButtonClicked(clicksender, clickargs); };
radialController.RotationChanged += (rotationsender, rotationargs) =>
{ RadialController_RotationChanged(rotationsender, rotationargs); };
}

// Connect wheel device rotation to slider control.


private void RadialController_RotationChanged(
object sender, RadialControllerRotationChangedEventArgs args)
{
if (RotationSlider.Value + args.RotationDeltaInDegrees >= RotationSlider.Maximum)
{
RotationSlider.Value = RotationSlider.Maximum;
}
else if (RotationSlider.Value + args.RotationDeltaInDegrees < RotationSlider.Minimum)
{
RotationSlider.Value = RotationSlider.Minimum;
}
else
{
RotationSlider.Value += args.RotationDeltaInDegrees;
}
}

// Connect wheel device click to toggle switch control.


private void RadialController_ButtonClicked(
object sender, RadialControllerButtonClickedEventArgs args)
{
ClickToggle.IsOn = !ClickToggle.IsOn;
}

4. Now, run the app again.


5. Select the Initialize radial controller button.
6. With the app in the foreground, press and hold the Surface Dial to display the menu. Notice that all default
tools have been removed (by using the RadialControllerConfiguration.SetDefaultMenuItems method),
leaving only the custom tool. Heres the menu with our custom tool.
RADIALCONTROLLER MENU (CUSTOM)

7. Select the custom tool and try out the interactions now supported through the Surface Dial:
A rotate action moves the slider.
A click sets the toggle to on or off.
Ok, let's hook up those buttons.

Step 5: Configure menu at runtime


In this step, we hook up the Add/Remove item and Reset RadialController menu buttons to show how you can
dynamically customize the menu.
1. Open the MainPage_Basic.xaml.cs file.
2. Find the code marked with the title of this step ("// Step 5: Configure menu at runtime").
3. Uncomment the code in the following methods and run the app again, but don't select any buttons (save
that for the next step).
// Add or remove the custom tool.
private void AddRemoveItem(object sender, RoutedEventArgs args)
{
if (AddRemoveToggleButton?.IsChecked == true)
{
AddRemoveToggleButton.Content = "Remove item";
if (!radialController.Menu.Items.Contains(radialControllerMenuItem))
{
radialController.Menu.Items.Add(radialControllerMenuItem);
}
}
else if (AddRemoveToggleButton?.IsChecked == false)
{
AddRemoveToggleButton.Content = "Add item";
if (radialController.Menu.Items.Contains(radialControllerMenuItem))
{
radialController.Menu.Items.Remove(radialControllerMenuItem);
// Attempts to select and activate the previously selected tool.
// NOTE: Does not differentiate between built-in and custom tools.
radialController.Menu.TrySelectPreviouslySelectedMenuItem();
}
}
}

// Reset the RadialController to initial state.


private void ResetController(object sender, RoutedEventArgs arg)
{
if (!radialController.Menu.Items.Contains(radialControllerMenuItem))
{
radialController.Menu.Items.Add(radialControllerMenuItem);
}
AddRemoveToggleButton.Content = "Remove item";
AddRemoveToggleButton.IsChecked = true;
radialControllerConfig.SetDefaultMenuItems(
new RadialControllerSystemMenuItemKind[] { });
}

4. Select the Remove item button and then press and hold the Dial to display the menu again.
Notice that the menu now contains the default collection of tools. Recall that, in Step 3, while setting up our
custom menu, we removed all the default tools and added just our custom tool. We also noted that, when
the menu is set to an empty collection, the default items for the current context are reinstated. (We added
our custom tool before removing the default tools.)
5. Select the Add item button and then press and hold the Dial.
Notice that the menu now contains both the default collection of tools and our custom tool.
6. Select the Reset RadialController menu button and then press and hold the Dial.
Notice that the menu is back to its original state.

Step 6: Customize the device haptics


The Surface Dial, and other wheel devices, can provide users with haptic feedback corresponding to the current
interaction (based on either click or rotation).
In this step, we show how you can customize haptic feedback by associating our slider and toggle switch controls
and using them to dynamically specify haptic feedback behavior. For this example, the toggle switch must be set to
on for feedback to be enabled while the slider value specifies how often the click feedback is repeated.
NOTE
Haptic feedback can be disabled by the user in the Settings > Devices > Wheel page.

1. Open the App.xaml.cs file.


2. Find the code marked with the title of this step ("Step 6: Customize the device haptics").
3. Comment the first and third lines ("MainPage_Basic" and "MainPage") and uncomment the second
("MainPage_Haptics").

rootFrame.Navigate(typeof(MainPage_Basic), e.Arguments);
rootFrame.Navigate(typeof(MainPage_Haptics), e.Arguments);
rootFrame.Navigate(typeof(MainPage), e.Arguments);

4. Open the MainPage_Haptics.xaml file.


5. Find the code marked with the title of this step ("<!-- Step 6: Customize the device haptics -->").
6. Uncomment the following lines. (This UI code simply indicates what haptics features are supported by the
current device.)

<StackPanel x:Name="HapticsStack"
Orientation="Vertical"
HorizontalAlignment="Center"
BorderBrush="Gray"
BorderThickness="1">
<TextBlock Padding="10"
Text="Supported haptics properties:" />
<CheckBox x:Name="CBDefault"
Content="Default"
Padding="10"
IsEnabled="False"
IsChecked="True" />
<CheckBox x:Name="CBIntensity"
Content="Intensity"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBPlayCount"
Content="Play count"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBPlayDuration"
Content="Play duration"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBReplayPauseInterval"
Content="Replay/pause interval"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBBuzzContinuous"
Content="Buzz continuous"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBClick"
Content="Click"
Content="Click"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBPress"
Content="Press"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBRelease"
Content="Release"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
<CheckBox x:Name="CBRumbleContinuous"
Content="Rumble continuous"
Padding="10"
IsEnabled="False"
IsThreeState="True"
IsChecked="{x:Null}" />
</StackPanel>

7. Open the MainPage_Haptics.xaml.cs file


8. Find the code marked with the title of this step ("Step 6: Haptics customization")
9. Uncomment the following lines:
The Windows.Devices.Haptics type reference is used for functionality in subsequent steps.

using Windows.Devices.Haptics;

Here, we specify the handler for the ControlAcquired event that is triggered when our custom
RadialController menu item is selected.

radialController.ControlAcquired += (rc_sender, args) =>


{ RadialController_ControlAcquired(rc_sender, args); };

Next, we define the ControlAcquired handler, where we disable default haptic feedback and initialize
our haptics UI.
private void RadialController_ControlAcquired(
RadialController rc_sender,
RadialControllerControlAcquiredEventArgs args)
{
// Turn off default haptic feedback.
radialController.UseAutomaticHapticFeedback = false;

SimpleHapticsController hapticsController =
args.SimpleHapticsController;

// Enumerate haptic support.


IReadOnlyCollection<SimpleHapticsControllerFeedback> supportedFeedback =
hapticsController.SupportedFeedback;

foreach (SimpleHapticsControllerFeedback feedback in supportedFeedback)


{
if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.BuzzContinuous)
{
CBBuzzContinuous.IsEnabled = true;
CBBuzzContinuous.IsChecked = true;
}
else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click)
{
CBClick.IsEnabled = true;
CBClick.IsChecked = true;
}
else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press)
{
CBPress.IsEnabled = true;
CBPress.IsChecked = true;
}
else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Release)
{
CBRelease.IsEnabled = true;
CBRelease.IsChecked = true;
}
else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.RumbleContinuous)
{
CBRumbleContinuous.IsEnabled = true;
CBRumbleContinuous.IsChecked = true;
}
}

if (hapticsController?.IsIntensitySupported == true)
{
CBIntensity.IsEnabled = true;
CBIntensity.IsChecked = true;
}
if (hapticsController?.IsPlayCountSupported == true)
{
CBPlayCount.IsEnabled = true;
CBPlayCount.IsChecked = true;
}
if (hapticsController?.IsPlayDurationSupported == true)
{
CBPlayDuration.IsEnabled = true;
CBPlayDuration.IsChecked = true;
}
if (hapticsController?.IsReplayPauseIntervalSupported == true)
{
CBReplayPauseInterval.IsEnabled = true;
CBReplayPauseInterval.IsChecked = true;
}
}

In our RotationChanged and ButtonClicked event handlers, we connect the corresponding slider and
toggle button controls to our custom haptics.

// Connect wheel device rotation to slider control.


private void RadialController_RotationChanged(
object sender, RadialControllerRotationChangedEventArgs args)
{
...
if (ClickToggle.IsOn &&
(RotationSlider.Value > RotationSlider.Minimum) &&
(RotationSlider.Value < RotationSlider.Maximum))
{
SimpleHapticsControllerFeedback waveform =
FindWaveform(args.SimpleHapticsController,
KnownSimpleHapticsControllerWaveforms.BuzzContinuous);
if (waveform != null)
{
args.SimpleHapticsController.SendHapticFeedback(waveform);
}
}
}

private void RadialController_ButtonClicked(


object sender, RadialControllerButtonClickedEventArgs args)
{
...

if (RotationSlider?.Value > 0)
{
SimpleHapticsControllerFeedback waveform =
FindWaveform(args.SimpleHapticsController,
KnownSimpleHapticsControllerWaveforms.Click);

if (waveform != null)
{
args.SimpleHapticsController.SendHapticFeedbackForPlayCount(
waveform, 1.0,
(int)RotationSlider.Value,
TimeSpan.Parse("1"));
}
}
}

Finally, we get the requested Waveform (if supported) for the haptic feedback.

// Get the requested waveform.


private SimpleHapticsControllerFeedback FindWaveform(
SimpleHapticsController hapticsController,
ushort waveform)
{
foreach (var hapticInfo in hapticsController.SupportedFeedback)
{
if (hapticInfo.Waveform == waveform)
{
return hapticInfo;
}
}
return null;
}

Now run the app again to try out the custom haptics by changing the slider value and toggle-switch state.

Step 7: Define on-screen interactions for Surface Studio and similar


devices
Paired with the Surface Studio, the Surface Dial can provide an even more distinctive user experience.
In addition to the default press and hold menu experience described, the Surface Dial can also be placed directly on
the screen of the Surface Studio. This enables a special "on-screen" menu.
By detecting both the contact location and bounds of the Surface Dial, the system handles occlusion by the device
and displays a larger version of the menu that wraps around the outside of the Dial. This same info can also be
used by your app to adapt the UI for both the presence of the device and its anticipated usage, such as the
placement of the user's hand and arm.
The sample that accompanies this tutorial includes a slightly more complex example that demonstrates some of
these capabilities.
To see this in action (you'll need a Surface Studio):
1. Download the sample on a Surface Studio device (with Visual Studio installed)
2. Open the sample in Visual Studio
3. Open the App.xaml.cs file
4. Find the code marked with the title of this step ("Step 7: Define on-screen interactions for Surface Studio and
similar devices")
5. Comment the first and second lines ("MainPage_Basic" and "MainPage_Haptics") and uncomment the third
("MainPage")

rootFrame.Navigate(typeof(MainPage_Basic), e.Arguments);
rootFrame.Navigate(typeof(MainPage_Haptics), e.Arguments);
rootFrame.Navigate(typeof(MainPage), e.Arguments);

6. Run the app and place the Surface Dial in each of the two control regions, alternating between them.

Here's a video of this sample in action:


Summary
Congratulations, you've completed the Get Started Tutorial: Support the Surface Dial (and other wheel devices) in
your UWP app! We showed you the basic code required for supporting a wheel device in your UWP apps, and how
to provide some of the richer user experiences supported by the RadialController APIs.
Get Started Tutorial - Single-page web app with
REST API backend
6/2/2017 21 min to read Edit Online

Build a Hosted Web App for the Windows Store with popular fullstack web technologies

This two-part tutorial provides a quick tour of modern fullstack web development as you build a simple memory
game that works both in the browser and as a Hosted Web App for the Windows Store. In Part I you'll build a
simple REST API service for the game's backend. By hosting the game logic in the cloud as an API service, you
preserve the game state so your user can keep playing their same game instance across different devices. In Part II
you'll build the front-end UI as a single-page web app with responsive layout.
We'll be using some of the most popular web technologies, including the Node.js runtime and Express for server-
side development, the Bootstrap UI framework, the Pug template engine, and Swagger for building RESTful APIs.
You'll also gain experience with the Azure Portal for cloud hosting and working with the Visual Studio Code editor.

Prerequisites
If you don't already have these resources on your machine, follow these download links:
Node.js - Be sure to select the option to add Node to your PATH.
Express generator- After you install Node, install Express by running npm install express-generator -g

Visual Studio Code


If you want to complete the final steps of hosting your API service and memory game app on Microsoft Azure,
you'll need to create a free Azure account if you haven't already done so.
If you decide to bail on (or postpone) the Azure part, simply skip the final sections of parts I and II, which cover
Azure hosting and packaging your app for the Windows Store. The API service and web app you build will still run
locally (from http://localhost:8000 and http://localhost:3000 , respectively) on your machine.

Part I: Build a REST API backend


We'll first build a simple memory game API to power our memory game web app. We'll use Swagger to define our
API and generate scaffolding code and a web UI for manual testing.
If you'd like to skip this part and move straight to Part II: Build a single-page web application, here's the finished
code for Part I. Follow the README instructions to get the code up and running locally, or see 5. Host your API
service on Azure and enable CORS to run it from Azure.
Game overview
Memory (also known as Concentration and Pelmanism), is a simple game consisting of a deck of card pairs. The
cards are placed face-down on the table, and the player inspects the card values, two at a time, looking for matches.
After each turn the cards are again placed face-down, unless a matching pair is found, in which case those two
cards are cleared from the game. The game objective is to find all card pairs in the fewest amount of turns.
For instructional purposes, the game structure we'll use is very simple: it's single game, single player. However, the
game logic is server-side (rather than on the client) to preserve the game state, so that you could keep playing the
same game across different devices.
The data structure for a memory game consists simply of an array of JavaScript objects, each representing a single
card, with indices in the array acting as card IDs. On the server, each card object has a value and a cleared flag. For
example, a board of 2-matches (4 cards) might be randomly generated and serialized like this.

[
{ "cleared":"false",
"value":"0",
},
{ "cleared":"false",
"value":"1",
},
{ "cleared":"false",
"value":"1",
},
{ "cleared":"false",
"value":"0",
}
]

When the board array is passed to the client, value keys are removed from the array to prevent cheating (for
example, inspecting the HTTP response body by using F12 browser tools). Here's how that same new game would
look to a client calling the GET /game REST endpoint:

[{ "cleared":"false"},{ "cleared":"false"},{ "cleared":"false"},{ "cleared":"false"}]

Speaking of endpoints, the memory game service will consist of three REST APIs.
POST /new
Initializes a new game board of the specified size (# of matches).

PARAMETER DESCRIPTION

int size Number of matching pairs to be shuffled into the game


"board". Example: http://memorygameapisample/new?size=2

RESPONSE DESCRIPTION

200 OK New memory game of requested size is ready.

400 BAD REQUEST Requested size is outside of acceptable range.


GET /game
Retrieves the current state of the memory game board.
No parameters

RESPONSE DESCRIPTION

200 OK Returns JSON array of card objects. Each card has a cleared
property indicating whether its match has already been found.
Matched cards also report their value. Example:
[{"cleared":"false"},{"cleared":"false"},
{"cleared":"true","value":1},
{"cleared":"true","value":1}]

PUT /guess
Specifies a card to reveal and checks for a match to the previously revealed card.

PARAMETER DESCRIPTION

int card Card ID (index in game board array) of the card to reveal. Each
complete "guess" consists of two specified cards (i.e., two calls
to /guess with valid and unique card values). Example:
http://memorygameapisample/guess?card=0

RESPONSE DESCRIPTION

200 OK Returns JSON with the id and value of the specified card.
Example: [{"id":0,"value":1}]

400 BAD REQUEST Error with the specified card. See HTTP response body for
further details.

1. Spec out the API and generate code stubs


We'll use Swagger to transform the design of our memory game API into working Node.js server code. Here's how
you might define our memory game APIs as Swagger metadata. We'll use this to generate server code stubs.
1. Create a new folder (in your local GitHub directory, for example), and download the api.json file containing
our memory game API definitions. Make sure your folder name doesn't contain any spaces.
2. Open your favorite shell (or use Visual Studio Code's integrated terminal!) to that folder and run the
following Node Package Manager (NPM) command to install the Yeoman (yo) code-scaffolding tool and
Swagger generator for your global (-g) Node environment:

npm install -g yo
npm install -g generator-swaggerize

3. Now we can generate the server scaffolding code by using Swagger:

yo swaggerize

4. The swaggerize command will ask you several questions.


Path (or URL) to swagger document: api.json
Framework: express
What would you like to call this project (YourFolderNameHere): [enter]
Answer everything else as you like; the information is mostly to supply the package.json file with
your contact info so you can distribute your code as an NPM package.
5. Finally, install all the dependencies (listed in package.json) for your new project and Swagger UI support.

npm install
npm install swaggerize-ui

Now start VS Code and File > Open Folder..., and move to the MemoryGameAPI directory. This is the
Node.js API server you just created! It uses the popular ExpressJS web application framework to structure
and run your project.
2. Customize the server code and setup debugging
The server.js file in your project root acts as the "main" function of your server. Open it in VS Code and copy the
following into it. The lines modified from the generated code are commented with further explanation.

'use strict';

var port = process.env.PORT || 8000; // Better flexibility than hardcoding the port

var Http = require('http');


var Express = require('express');
var BodyParser = require('body-parser');
var Swaggerize = require('swaggerize-express');
var SwaggerUi = require('swaggerize-ui'); // Provides UI for testing our API
var Path = require('path');

var App = Express();


var Server = Http.createServer(App);

App.use(function(req, res, next) { // Enable cross origin resource sharing (for app frontend)
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

// Prevents CORS preflight request (for PUT game_guess) from redirecting


if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next(); // Passes control to next (Swagger) handler
}
});

App.use(BodyParser.json());
App.use(BodyParser.urlencoded({
extended: true
}));

App.use(Swaggerize({
api: Path.resolve('./config/swagger.json'),
handlers: Path.resolve('./handlers'),
docspath: '/swagger' // Hooks up the testing UI
}));

App.use('/', SwaggerUi({ // Serves the testing UI from our base URL


docs: '/swagger' //
}));

Server.listen(port, function () { // Starts server with our modfied port settings


});

With that, it's time to run your server! Let's set up Visual Studio Code for Node debugging while we're at it. Select
on the Debug panel icon (Ctrl+Shift+D) and then the gear icon (Open launch.json), and modify "configurations" to
this:

"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/server.js"
}
]

Now press F5 and open your browser to http://localhost:8000. The page should open to the Swagger UI for our
memory game API, and from there you can expand the details and input fields for each of the methods. You can
even try calling the APIs, although their responses will contain only mocked-up data (provided by the Swagmock
module). It's time to add our game logic to make these APIs real.
3. Set up your route handlers
The Swagger file (config\swagger.json) instructs our server how to handle various client HTTP requests by
mapping each URL path it defines to a handler file (in \handlers), and each method defined for that path (e.g., GET,
POST) to an operationId (function) within that handler file.
In this layer of our program we'll add some input checking before passing the various client requests to our data
model. Download (or copy and paste):
This game.js code to your handlers\game.js file
This guess.js code to your handlers\guess.js file
This new.js code to your handlers\new.js file
You can skim the comments in those files for more details about the changes, but in essence they check for
basic input errors (for example, the client requests a new game with less than one match) and send
descriptive error messages as needed. The handlers also route valid client requests through to their
corresponding data files (in \data) for further processing. Let's work on those next.
4. Set up your data model
It's time to swap out the placeholder data-mocking service with a real data model of our memory game board.
This layer of our program represents the memory cards themselves and provides the bulk of the game logic,
including "shuffling" the deck for a new game, identifying pairs of matched cards, and keeping track of game state.
Copy and paste:
This game.js code to your data\game.js file
This guess.js code to your data\guess.js file
This new.js code to your data\new.js file
For simplicity, we're storing our game board in a global variable ( global.board ) on our Node server. But realistically
you'd use cloud storage (like Google Cloud Datastore or Azure DocumentDB) to make this into a viable memory-
game API service that concurrently supports multiple games and players.
Make sure you've saved all the changes in VS Code, fire up your server again (F5 in VS Code or npm start from
shell, and then browse to http://localhost:8000) to test out the game API.
Each time you press the Try it out! button on one of the /game, /guess, or /new operations, check the resulting
Response Body and Response Code below to verify that everything's working as expected.
Try:
1. Creating a new size=2 game.

2. Guessing a couple of values.

3. Checking the game board as the game progresses.

If everything looks good, your API service is ready to host on Azure! If you're running into problems, try
commenting out the following lines in \data\game.js.
for (var i=0; i < board.length; i++){
var card = {};
card.cleared = board[i].cleared;

// Only reveal cleared card values


//if ("true" == card.cleared) { // To debug the board, comment out this line
card.value = board[i].value;
//} // And this line
currentBoardState.push(card);
}

With this change, the GET /game method will return all the card values (including the ones that haven't been
cleared). This is a useful debug hack to keep in place as you build the front-end for the memory game.
5. (Optional) Host your API service on Azure and enable CORS
The Azure docs will walk you through:
Registering a new API App with Azure Portal
Setting up Git deployment for your API app, and
Deploying your API app code to Azure
When registering your app, try to differentiate your App name (to avoid naming collisions with others requesting
variations on the http://memorygameapi.azurewebsites.net URL).
If you've made it this far and Azure is now serving up your swagger UI, there's just one final step to the memory
game backend. From Azure Portal, select your newly created App Service and then select or search for the CORS
(Cross-Origin Resource Sharing) option. Under Allowed Origins, add an asterisk ( * ) and click Save. This lets you
make cross-origin calls to your API service from your memory-game front-end as you develop it on your local
machine. Once you finalize the memory-game front-end and deploy that to Azure, you can replace this entry with
the specific URL of your web app.
Going further
To make the memory game API a viable back-end service for a production app, you'll want to extend the code to
support multiple players and games. For that you'll probably need to plumb in authentication (for managing player
identities), a NoSQL database (for tracking games and players), and some basic unit testing for your API.
Here are some useful resources for going further:
Advanced Node.js debugging with Visual Studio Code
Azure Web + Mobile docs
Azure DocumentDB docs

Part II: Build a single-page web appl


Now that you've built (or downloaded) the REST API backend from Part I, you're ready to create the single-page
memory game front-end with Node, Express, and Bootstrap.
Part II of this tutorial will give you experience with:
Node.js: to create the server hosting your game
jQuery: a JavaScript library
Express: for the web application framework
Pug: (formally Jade) for the templating engine
Bootstrap: for the responsive layout
Visual Studio Code: for code authoring, markdown viewing, and debugging
1. Create a Node.js application by using Express
Let's start by creating the Node.js project using Express.
1. Open a command prompt and navigate to the directory where you want to store your game.
2. Use the Express generator to create a new application called memory using the templating engine, Pug.

express --view=pug memory

3. In the memory directory, install the dependencies listed in the package.json file. The package.json file is
created in the root of your project. This file contains the modules that are required for your Node.js app.

cd memory
npm install

After running this command, you should see a folder called node_modules that contains all of the modules
needed for this app.
4. Now, run your application.

npm start

5. View your application by going to http://localhost:3000/.

6. Change the default title of your web app by editing index.js in the memory\routes directory. Change Express
in the line below to Memory Game (or another title of your choosing).

res.render('index', { title: 'Express' });

7. To refresh the app to see your new title, stop your app by pressing Crtl + C, Y in the command prompt, and
then restart it with npm start .
2. Add client-side game logic code
You can find the files you need for this half of the tutorial in the Start folder. If you get lost, the finished code is
available in the Final folder.
1. Copy the scripts.js file inside of the Start folder and paste it in memory\public\javascripts. This file contains
all the game logic needed to run the game, including:
Creating/starting a new game.
Restoring a game stored on the server.
Drawing the game board and cards based on user selection.
Flipping the cards.
2. In script.js, let's start by modifying the newGame() function. This function:
Handles the size of the game selection from the user.
Fetches the gameboard array from the server.
Calls the drawGameBoard() function to place the game board to the screen.
Add the following code inside of newGame() after the // Add code from Part 2.2 here comment.

// extract game size selection from user


var size = $("#selectGameSize").val();

// parse game size value


size = parseInt(size, 10);

This code retrieves the value from the dropdown menu with id="selectGameSize" (which we will create
later) and stores it in a variable ( size ). We use the parseInt() function to parse the string value from
the dropdown to return an integer, so we can pass the size of the requested game board to the
server.
We use the /new method created in Part I of this tutorial to post the chosen size of the game board to
the server. The method returns a single JSON array of cards and true/false values indicating whether
the cards have been matched.
3. Next, fill in the restoreGame() function that restores the last game played. For simplicity's sake, the app always
loads the last game played. If there is not a game stored on the server, use the drop-down menu to start a
new game.
Copy and paste this code into restoreGame() .

``` javascript
// reset the game
gameBoardSize = 0;
cardsFlipped = 0;

// fetch the game state from the server


$.get("http://localhost:8000/game", function (response) {
// store game board size
gameBoardSize = response.length;

// draw the game board


drawGameBoard(response);
});
```

The game will now fetch the game state from the server. For more information about the [`/game`](#part-i-build-a-rest-api-backend) method being
used in this step, see Part I of this tutorial. If you are using Azure (or another service) to host the backend API, replace the *localhost* address
above with your production URL.

1. Now we want to create the drawGameBoard() function. This function:


Detects the size of the game and applies specific CSS styles.
Generates the cards in HTML.
Adds the cards to the page.
Copy and paste this code into the drawGameBoard() function in scripts.js:

// create output
var output = "";
// detect board size CSS class
var css = "";
switch (board.length / 4) {
case 1:
css = "rows1";
break;
case 2:
css = "rows2";
break;
case 3:
css = "rows3";
break;
case 4:
css = "rows4";
break;
}
// generate HTML for each card and append to the output
for (var i = 0; i < board.length; i++) {
if (board[i].cleared == "true") {
// if the card has been cleared apply the .flip class
output += "<div class=\"flipContainer col-xs-3 " + css + "\"><div class=\"cards flip matched\" id=\"" + i + "\"
onClick=\"flipCard(this)\">\
<div class=\"front\"><span class=\"glyphicon glyphicon-question-sign\"></span></div>\
<div class=\"back\">" + lookUpGlyphicon(board[i].value) + "</div>\
</div></div>";
} else {
output += "<div class=\"flipContainer col-xs-3 " + css + "\"><div class=\"cards\" id=\"" + i + "\" onClick=\"flipCard(this)\">\
<div class=\"front\"><span class=\"glyphicon glyphicon-question-sign\"></span></div>\
<div class=\"back\"></div>\
</div></div>";
}
}
// place the output on the page
$("#game-board").html(output);

2. Next, we need to complete the flipCard() function. This function handles the majority of the game logic,
including getting the values of the selected cards from the server by using the /guess method developed in
Part I of the tutorial. Don't forget to replace the localhost address with your production URL if you are cloud
hosting the REST API backend.
In the flipCard() function, uncomment this code:

// post this guess to the server and get this card's value
$.ajax({
url: "http://localhost:8000/guess?card=" + selectedCards[0],
type: 'PUT',
success: function (response) {
// display first card value
$("#" + selectedCards[0] + " .back").html(lookUpGlyphicon(response[0].value));

// store the first card value


selectedCardsValues.push(response[0].value);
}
});
TIP
If you're using Visual Studio Code, select all the lines of code you wish to uncomment, and press Crtl + K, U

Here we use jQuery.ajax() and the PUT /guess method created in Part I.
This code executes in the following order.
The id of the first card the user selected is added as the first value to the selectedCards[] array: selectedCards[0]
The value ( id ) in selectedCards[0] is posted to the server using the /guess method
The server responds with the value of that card (an integer)
A Bootstrap glyphicon is added to the back of the card whose id is selectedCards[0]
The first card's value (from the server) is stored in the selectedCardsValues[] array: selectedCardsValues[0] .

The user's second guess follows the same logic. If the cards that the user selected have the same IDs, (for example,
selectedCards[0] == selectedCards[1] ), the cards are a match! The CSS class .matched is added to the matched cards
(turning them green) and the cards remained flipped.
Now we need to add logic to check whether the user matched all of the cards and won the game. Inside of the
flipCard() function, add the following lines of code under the //check if the user won the game comment.

if (cardsFlipped == gameBoardSize) {
setTimeout(function () {
output = "<div id=\"playAgain\"><p>You Win!</p><input type=\"button\" onClick=\"location.reload()\" value=\"Play Again\"
class=\"btn\" /></div>";
$("#game-board").html(output);
}, 1000);
}

If the number of cards flipped matches the size of the game board (for example, cardsFlipped == gameBoardSize ), there
are no more cards to flip and the user has won the game. We'll add some simple HTML to the div with
id="game-board" to let the user know they won and can play again.

3. Create the user interface


Now let's see all this code in action by creating the user interface. In this tutorial, we use the templating engine Pug
(formally Jade). Pug is clean, whitespace-sensitive syntax for writing HTML. Here's an example.

body
h1 Memory Game
#container
p We love tutorials!

becomes

<body>
<h1>Memory Game</h1>
<div id="container">
<p>We love tutorials!</p>
</div>
</body>

1. Replace the layout.pug file in memory\views with the provided layout.pug file in the Start folder. Inside of
layout.pug, you'll see links to:
Bootstrap
jQuery
A custom CSS file
The JavaScript file we just finished modifying
2. Open the file named index.pug in the directory memory\views. This file extends the layout.pug file and will
render our game. Inside of layout.pug, paste the following lines of code:

extends layout
block content
div
form(method="GET")
select(id="selectGameSize" class="form-control" onchange="newGame()")
option(value="0") New Game
option(value="2") 2 Matches
option(value="4") 4 Matches
option(value="6") 6 Matches
option(value="8") 8 Matches
#game-board
script restoreGame();

TIP
Remember: Pug is whitespace sensitive. Make sure all of your indentations are correct!

4. Use Bootstrap's grid system to create a responsive layout


Bootstrap's grid system is a fluid grid system that scales a grid as a device's viewport changes. The cards in this
game use Bootstrap's predefined grid system classes for the layout, including:
.container-fluid: specifies the fluid container for the grid
.row-fluid : specifies the fluid rows
.col-xs-3 : specifies the number of columns

Bootstrap's grid system allows a grid system to collapse into one vertical column, like you would see on a
navigation menu on a mobile device. However, because we want our game always to have columns, we use the
predefined class .col-xs-3 , which keeps the grid horizontal at all times.
The grid system allows up to 12 columns. Since we only want 4 columns in our game, we use the class .col-xs-3 .
This class specifies that we need each of our columns to span the width of 3 of the 12 available columns mentioned
before. This image shows a 12-column grid and a 4-column grid, like the one used in this game.

1. Open scripts.js and find the drawGameBoard() function. In the block of code where we generate the HTML for
each card, can you spot the div element with class="col-xs-3" ?
2. Inside of index.pug, let's add the predefined Bootstrap classes mentioned previously to create our fluid
layout. Change index.pug to the following.
extends layout

block content

.container-fluid
form(method="GET")
select(id="selectGameSize" class="form-control" onchange="newGame()")
option(value="0") New Game
option(value="2") 2 Matches
option(value="4") 4 Matches
option(value="6") 6 Matches
option(value="8") 8 Matches
#game-board.row-fluid
script restoreGame();

5. Add a card-flip animation with CSS Transforms


Replace the style.css file in memory\public\stylesheets with the style.css file from the Start folder.
Adding a flip motion using CSS Transforms gives the cards a realistic, 3D flipping motion. The cards in the game
are created by using the following HTML structure and programmatically added to the game board (in the
drawGameBoard() function shown previously).

<div class="flipContainer">
<div class="cards">
<div class="front"></div>
<div class="back"></div>
</div>
</div>

1. To start, give perspective to the parent container of the animation ( .flipContainer ). This gives the illusion of
depth for its child elements: the higher the value, the farther away from the user the element will appear.
Let's add the following perspective to the .flipContainer class in style.css.

perspective: 1000px;

2. Now add the following properties to the .cards class in style.css. The .cards div is the element that will
actually be doing the flipping animation, showing either the front or the back of the card.

transform-style: preserve-3d;
transition-duration: 1s;

The transform-style property establishes a 3D-rendering context, and the children of the .cards class ( .front
and .back are members of the 3D space. Adding the transition-duration property specifies the number of
seconds for the animation to finish.
3. Using the transform property, we can rotate the card around the Y-axis. Add the following CSS to cards.flip .

transform: rotateY(180deg);

The style defined in cards.flip is toggled on and off in the flipCard function by using .toggleClass() .

$(card).toggleClass("flip");

Now when a user clicks on a card, the card is rotated 180 degrees.
6. Test and play
Congratulations! You've finished creating the web app! Let's test it.
1. Open a command prompt in your memory directory and enter the following command: npm start

2. In your browser, go to http://localhost:3000/ and play a game!


3. If you encounter any errors, you can use Visual Studio Code's Node.js debugging tools by pressing F5 on
your keyboard and typing Node.js . For more information about debugging in Visual Studio Code, check out
this article.
You can also compare your code to the code provided in the Final folder.
4. To stop the game, in the command prompt type: Ctrl + C, Y.
Going further
You can now deploy your app to Azure (or any other cloud hosting service) for testing across different device form
factors, such as mobile, tablet, and desktop. (Don't forgot to test across different browsers too!) Once your app is
ready for production, you can easily package it as a Hosted Web App (HWA) for the Universal Windows Platform
(UWP) and distribute it from the Windows Store.
The basic steps for publishing to the Windows Store are:
1. Create a Windows Developer account
2. Use the app submission checklist
3. Submit your app for certification
Here are some useful resources for going further:
Deploy your application development project to Azure Websites
Convert your web application to a Universal Windows Platform (UWP) app
Publish Windows apps
Get Started Tutorial: A UWP game in MonoGame 2D
8/28/2017 22 min to read Edit Online

A simple 2D UWP game for the Windows Store, written in C# and


MonoGame

Introduction
MonoGame is a lightweight game development framework. This tutorial will teach you the basics of game
development in MonoGame, including how to load content, draw sprites, animate them, and handle user input.
Some more advanced concepts like collision detection and scaling up for high-DPI screens are also discussed. This
tutorial takes 30-60 minutes.

Prerequisites
Windows 10 and Microsoft Visual Studio 2017. Click here to learn how to get set up with Visual Studio.
The .NET desktop development framework. If you don't already have this installed, you can get it by re-running
the Visual Studio installer and modifying your installation of Visual Studio 2017.
Basic knowledge of C# or a similar object-oriented programming language. Click here to learn how to get
started with C#.
Familiarity with basic computer science concepts like classes, methods, and variables is a plus.

Why MonoGame?
Theres no shortage of options when it comes to game development environments. From full-featured engines like
Unity to comprehensive and complex multimedia APIs like DirectX, it can be hard to know where to start.
MonoGame is a set of tools, with a level of complexity falling somewhere between a game engine and a grittier API
like DirectX. It provides an easy-to-use content pipeline, and all the functionality required to create lightweight
games that run on a wide variety of platforms. Best of all, MonoGame apps are written in pure C#, and you can
distribute them quickly via the Windows Store or other similar distribution platforms.

Get the code


If you dont feel like working through the tutorial step-by-step and just want to see MonoGame in action, click here
to get the finished app.
Open the project in Visual Studio 2017, and press F5 to run the sample. The first time you do this may take a while,
as Visual Studio needs to fetch any NuGet packages that are missing from your installation.
If youve done this, skip the next section about setting up MonoGame to see a step-by-step walkthrough of the
code.
Note: The game created in this sample is not meant to be complete (or any fun at all). Its only purpose is to
demonstrate all the core concepts of 2D development in MonoGame. Feel free to use this code and make
something much betteror just start from scratch after youve mastered the basics!

Set up MonoGame project


1. Install MonoGame 3.6 for Visual Studio from MonoGame.net
2. Start Visual Studio 2017.
3. Go to File -> New -> Project
4. Under the Visual C# project templates, select MonoGame and MonoGame Windows 10 Universal
Project
5. Name your project MonoGame2D" and select OK. With the project created, it will probably look like it is full
of errorsthese should go away after you run the project for the first time, and any missing NuGet
packages are installed.
6. Make sure x86 and Local Machine are set as the target platform, and press F5 to build and run the empty
project. If you followed the steps above, you should see an empty blue window after the project finishes
building.

Method overview
Now youve created the project, open the Game1.cs file from the Solution Explorer. This is where the bulk of the
game logic is going to go. Many crucial methods are automatically generated here when you create a new
MonoGame project. Lets quickly review them:
public Game1() The constructor. We arent going to change this method at all for this tutorial.
protected override void Initialize() Here we initialize any class variables that are used. This method is called
once at the start of the game.
protected override void LoadContent() This method loads content (eg. textures, audio, fonts) into memory
before the game starts. Like Initialize, its called once when the app starts.
protected override void UnloadContent() This method is used to unload non content-manager content. We
dont use this one at all.
protected override void Update(GameTime gameTIme) This method is called once for every cycle of the
game loop. Here we update the states of any object or variable used in the game. This includes things like an
objects position, speed, or color. This is also where use input is handled. In short, this method handles every part of
the game logic except drawing objects on screen. protected override void Draw(GameTime gameTime) This is
where objects are drawn on the screen, using the positions given by the Update method.
Draw a sprite
So youve run your fresh MonoGame project and found a nice blue skylets add some ground. In MonoGame, 2D
art is added to the app in the form of sprites. A sprite is just a computer graphic that is manipulated as a single
entity. Sprites can be moved, scaled, shaped, animated, and combined to create anything you can imagine in the 2D
space.
1. Download a texture
For our purposes, this first sprite is going to be extremely boring. Click here to download this featureless green
rectangle.
2. Add the texture to the Content folder
Open the Solution Explorer
Right click Content.mgcb in the Content folder and select Open With. From the popup menu select
Monogame Pipeline, and select OK.
In the new window, Right-Click the Content item and select Add -> Existing Item.
Locate and select the green rectangle in the file browser
Name the item grass.png and select Add.
3. Add class variables
To load this image as a sprite texture, open Game1.cs and add the following class variables.

const float SKYRATIO = 2f/3f;


float screenWidth;
float screenHeight;
Texture2D grass;

The SKYRATIO variable tells us how much of the scene we want to be sky versus grassin this case, two-thirds.
screenWidth and screenHeight will keep track of the app window size, while grass is where well store our green
rectangle.
4. Initialize class variables and set window size
The screenWidth and screenHeight variables still need to be initialized, so add this code to the Initialize
method:

ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.FullScreen;

screenHeight = (float)ApplicationView.GetForCurrentView().VisibleBounds.Height;
screenWidth = (float)ApplicationView.GetForCurrentView().VisibleBounds.Width;

this.IsMouseVisible = false;

Along with getting the screens height and width, we also set the apps windowing mode to Fullscreen, and make
the mouse invisible.
5. Load the texture
To load the texture into the grass variable, add the following to the LoadContent method:

grass = Content.Load<Texture2D>("grass");

6. Draw the sprite


To draw the rectangle, add the following lines to the Draw method:
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(grass, new Rectangle(0, (int)(screenHeight * SKYRATIO),
(int)screenWidth, (int)screenHeight), Color.White);
spriteBatch.End();

Here we use the spriteBatch.Draw method to place the given texture within the borders of a Rectangle object. A
Rectangle is defined by the x and y coordinates of its top left and bottom right corner. Using the screenWidth,
screenHeight, and SKYRATIO variables we defined earlier, we draw the green rectangle texture across the bottom
one-third of the screen. If you run the program now you should see the blue background from before, partially
covered by the green rectangle.

Scale to high DPI screens


If youre running Visual Studio on a high pixel-density monitor, like those found on a Surface Pro or Surface Studio,
you may find that the green rectangle from the steps above doesnt quite cover the bottom third of the screen. Its
probably floating above the bottom-left corner of the screen. To fix this and unify the experience of our game
across all devices, we will need to create a method that scales certain values relative to the screens pixel density:

public float ScaleToHighDPI(float f)


{
DisplayInformation d = DisplayInformation.GetForCurrentView();
f *= (float)d.RawPixelsPerViewPixel;
return f;
}

Next replace the initializations of screenHeight and screenWidth in the Initialize method with this:

screenHeight = ScaleToHighDPI((float)ApplicationView.GetForCurrentView().VisibleBounds.Height);
screenWidth = ScaleToHighDPI((float)ApplicationView.GetForCurrentView().VisibleBounds.Width);

If youre using a high DPI screen and try to run the app now, you should see the green rectangle covering the
bottom third of the screen as intended.

Build the SpriteClass


Before we start animating sprites, were going to make a new class called SpriteClass, which will let us reduce the
surface-level complexity of sprite manipulation.
1. Create a new class
In the Solution Explorer, right-click MonoGame2D (Universal Windows) and select Add -> Class. Name the
class SpriteClass.cs then select Add.
2. Add class variables
Add this code to the class you just created:

public Texture2D texture


{
get;
}

public float x
{
get;
set;
}

public float y
{
get;
set;
}

public float angle


{
get;
set;
}

public float dX
{
get;
set;
}

public float dY
{
get;
set;
}

public float dA
{
get;
set;
}

public float scale


{
get;
set;
}

Here we set up the class variables we need to draw and animate a sprite. The x and y variables represent the
sprites current position on the plane, while the angle variable is the sprites current angle in degrees (0 being
upright, 90 being tilted 90 degrees clockwise). Its important to note that, for this class, x and y represent the
coordinates of the center of the sprite, (the default origin is the top-left corner). This is makes rotating sprites
easier, as they will rotate around whatever origin they are given, and rotating around the center gives us a uniform
spinning motion.
After this, we have dX, dY, and dA, which are the per-second rates of change for the x, y, and angle variables
respectively.
3. Create a constructor
When creating an instance of SpriteClass, we provide the constructor with the graphics device from Game1.cs, the
path to the texture relative to the project folder, and the desired scale of the texture relative to its original size. Well
set the rest of the class variables after we start the game, in the update method.

public SpriteClass (GraphicsDevice graphicsDevice, string textureName, float scale)


{
this.scale = scale;
if (texture == null)
{
using (var stream = TitleContainer.OpenStream(textureName))
{
texture = Texture2D.FromStream(graphicsDevice, stream);
}
}
}

4. Update and Draw


There are still a couple of methods we need to add to the SpriteClass declaration:

public void Update (float elapsedTime)


{
this.x += this.dX * elapsedTime;
this.y += this.dY * elapsedTime;
this.angle += this.dA * elapsedTime;
}

public void Draw (SpriteBatch spriteBatch)


{
Vector2 spritePosition = new Vector2(this.x, this.y);
spriteBatch.Draw(texture, spritePosition, null, Color.White, this.angle, new Vector2(texture.Width/2, texture.Height/2), new Vector2(scale, scale),
SpriteEffects.None, 0f);
}

The Update SpriteClass method is called in the Update method of Game1.cs, and is used to update the sprites x,
y, and angle values based on their respective rates of change.
The Draw method is called in the Draw method of Game1.cs, and is used to draw the sprite in the game window.

User input and animation


Now we have the SpriteClass built, well use it to create two new game objects, The first is an avatar that the player
can control with the arrow keys and the space bar. The second is an object that the player must avoid
1. Get the textures
For the players avatar were going to use Microsofts very own ninja cat, riding on his trusty t-rex. Click here to
download the image.
Now for the obstacle that the player needs to avoid. What do ninja-cats and carnivorous dinosaurs both hate more
than anything? Eating their veggies! Click here to download the image.
Just as before with the green rectangle, add these images to Content.mgcb via the MonoGame Pipeline, naming
them ninja-cat-dino.png and broccoli.png respectively.
2. Add class variables
Add the following code to the list of class variables in Game1.cs:
SpriteClass dino;
SpriteClass broccoli;

bool spaceDown;
bool gameStarted;

float broccoliSpeedMultiplier;
float gravitySpeed;
float dinoSpeedX;
float dinoJumpY;
float score;

Random random;

dino and broccoli are our SpriteClass variables. dino will hold the player avatar, while broccoli holds the broccoli
obstacle.
spaceDown keeps track of whether the spacebar is being held down as opposed to pressed and released.
gameStarted tells us whether the user has started the game for the first time.
broccoliSpeedMultiplier determines how fast the broccoli obstacle moves across the screen.
gravitySpeed determines how fast the player avatar accelerates downward after a jump.
dinoSpeedX and dinoJumpY determine how fast the player avatar moves and jumps. score tracks how many
obstacles the player has successfully dodged.
Finally, random will be used to add some randomness to the behavior of the broccoli obstacle.
3. Initialize variables
Next we need to initialize these variables. Add the following code to the Initialize method:

broccoliSpeedMultiplier = 0.5f;
spaceDown = false;
gameStarted = false;
score = 0;
random = new Random();
dinoSpeedX = ScaleToHighDPI(1000f);
dinoJumpY = ScaleToHighDPI(-1200f);
gravitySpeed = ScaleToHighDPI(30f);

Note that the last three variables need to be scaled for high DPI devices, because they specify a rate of change in
pixels.
4. Construct SpriteClasses
We will construct SpriteClass objects in the LoadContent method. Add this code to what you already have there:

dino = new SpriteClass(GraphicsDevice, "Content/ninja-cat-dino.png", ScaleToHighDPI(1f));


broccoli = new SpriteClass(GraphicsDevice, "Content/broccoli.png", ScaleToHighDPI(0.2f));

The broccoli image is quite a lot larger than we want it to appear in the game, so well scale it down to 0.2 times its
original size.
5. Program obstacle behavior
We want the broccoli to spawn somewhere offscreen, and head in the direction of the players avatar, so they need
to dodge it. To accomplish they, add this method to the Game1.cs class:
public void SpawnBroccoli()
{
int direction = random.Next(1, 5);
switch (direction)
{
case 1:
broccoli.x = -100;
broccoli.y = random.Next(0, (int)screenHeight);
break;
case 2:
broccoli.y = -100;
broccoli.x = random.Next(0, (int)screenWidth);
break;
case 3:
broccoli.x = screenWidth + 100;
broccoli.y = random.Next(0, (int)screenHeight);
break;
case 4:
broccoli.y = screenHeight + 100;
broccoli.x = random.Next(0, (int)screenWidth);
break;
}

if (score % 5 == 0) broccoliSpeedMultiplier += 0.2f;

broccoli.dX = (dino.x - broccoli.x) * broccoliSpeedMultiplier;


broccoli.dY = (dino.y - broccoli.y) * broccoliSpeedMultiplier;
broccoli.dA = 7f;
}

The first part of the of the method determines what off screen point the broccoli object will spawn from, using two
random numbers.
The second part determines how fast the broccoli will travel, which is determined by the current score. It will get
faster for every five broccoli the player successfully dodges.
The third part sets the direction of the broccoli sprites motion. It heads in the direction of the player avatar (dino)
when the broccoli is spawned. We also give it a dA value of 7f, which will cause the broccoli to spin through the air
as it chases the player.
6. Program game starting state
Before we can move on to handling keyboard input, we need a method that sets the initial game state of the two
objects weve created. Rather than the game starting as soon as the app runs, we want the user to start it manually,
by pressing the spacebar. Add the following code, which sets the initial state of the animated objects, and resets the
score:

public void StartGame()


{
dino.x = screenWidth / 2;
dino.y = screenHeight * SKYRATIO;
broccoliSpeedMultiplier = 0.5f;
SpawnBroccoli();
score = 0;
}

7. Handle keyboard input


Next we need a new method to handle user input via the keyboard. Add this this method to Game1.cs:
void KeyboardHandler()
{
KeyboardState state = Keyboard.GetState();

// Quit the game if Escape is pressed.


if (state.IsKeyDown(Keys.Escape))
{
Exit();
}

// Start the game if Space is pressed.


if (!gameStarted)
{
if (state.IsKeyDown(Keys.Space))
{
StartGame();
gameStarted = true;
spaceDown = true;
gameOver = false;
}
return;
}
// Jump if Space is pressed
if (state.IsKeyDown(Keys.Space) || state.IsKeyDown(Keys.Up))
{
// Jump if the Space is pressed but not held and the dino is on the floor
if (!spaceDown && dino.y >= screenHeight * SKYRATIO - 1) dino.dY = dinoJumpY;

spaceDown = true;
}
else spaceDown = false;

// Handle left and right


if (state.IsKeyDown(Keys.Left)) dino.dX = dinoSpeedX * -1;

else if (state.IsKeyDown(Keys.Right)) dino.dX = dinoSpeedX;


else dino.dX = 0;
}

Above we have a series of four if-statements:


The first quits the game if the Escape key is pressed.
The second starts the game if the Space key is pressed, and the game is not already started.
The third makes the dino avatar jump if Space is pressed, by changing its dY property. Note that the player cannot
jump unless they are on the ground (dino.y = screenHeight * SKYRATIO), and will also not jump if the space key
is being help down rather than pressed once. This stops the dino from jumping as soon as the game is started,
piggybacking on the same keypress that starts the game.
Finally, the last if/else clause checks if the left or right directional arrows are being pressed, and if so changes the
dinos dX property accordingly.
Challenge: can you make the keyboard handling method above work with the WASD input scheme as well as the
arrow keys?
8. Add logic to the Update method
Next we need to add logic for all of these parts to the Update method in Game1.cs:
float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardHandler(); // Handle keyboard input
// Update animated SpriteClass objects based on their current rates of change
dino.Update(elapsedTime);
broccoli.Update(elapsedTime);

// Accelerate the dino downward each frame to simulate gravity.


dino.dY += gravitySpeed;

// Set game floor so the player does not fall through it


if (dino.y > screenHeight * SKYRATIO)
{
dino.dY = 0;
dino.y = screenHeight * SKYRATIO;
}

// Set game edges to prevent the player from moving offscreen


if (dino.x > screenWidth - dino.texture.Width/2)
{
dino.x = screenWidth - dino.texture.Width/2;
dino.dX = 0;
}
if (dino.x < 0 + dino.texture.Width/2)
{
dino.x = 0 + dino.texture.Width/2;
dino.dX = 0;
}

// If the broccoli goes offscreen, spawn a new one and iterate the score
if (broccoli.y > screenHeight+100 || broccoli.y < -100 || broccoli.x > screenWidth+100 || broccoli.x < -100)
{
SpawnBroccoli();
score++;
}

9. Draw SpriteClass objects


Finally, add the following code to the Draw method of Game1.cs, just after the last call of spriteBatch.Draw:

broccoli.Draw(spriteBatch);
dino.Draw(spriteBatch);

In MonoGame, new calls of spriteBatch.Draw will draw over any prior calls. This means that both the broccoli and
the dino sprite will be drawn over the existing grass sprite, so they can never be hidden behind it regardless of their
position.
Try running the game now, and moving around the dino with the arrow keys and the spacebar. If you followed the
steps above, you should be able to make your avatar move within the game window, and the broccoli should at an
ever-increasing speed.
Render text with SpriteFont
Using the code above, we keep track of the players score behind the scenes, but we dont actually tell the player
what it is. We also have a fairly unintuitive introduction when the app starts upthe player sees a blue and green
window, but has no way of knowing they need to press Space to get things rolling.
To fix both these problems, were going to use a new kind of MonoGame object called SpriteFonts.
1. Create SpriteFont description files
In the Solution Explorer find the Content folder. In this folder, Right-Click the Content.mgcb file and select
Open With. From the popup menu select MonoGame Pipeline, then press OK. In the new window, Right-Click
the Content item and select Add -> New Item. Select SpriteFont Description, name it Score and press OK.
Then, add another SpriteFont description named GameState using the same procedure.
2. Edit descriptions
Right click the Content folder in the MonoGame Pipeline and select Open File Location. You should see a
folder with the SpriteFont description files that you just created, as well as any images youve added to the Content
folder so far. You can now close and save the MonoGame Pipeline window. From the File Explorer open both
description files in a text editor (Visual Studio, NotePad++, Atom, etc).
Each description contains a number of values that describe the SpriteFont. We're going to make a few changes:
In Score.spritefont, change the value from 12 to 36.
In GameState.spritefont, change the value from 12 to 72, and the value from Arial to Agency. Agency is another
font that comes standard with Windows 10 machines, and will add some flair to our intro screen.
3. Load SpriteFonts
Back in Visual Studio, were first going to add a new texture for the intro splash screen. Click here to download the
image.
As before, add the texture to the project by right-clicking the Content and selecting Add -> Existing Item. Name
the new item start-splash.png.
Next, add the following class variables to Game1.cs:

Texture2D startGameSplash;
SpriteFont scoreFont;
SpriteFont stateFont;

Then add these lines to the LoadContent method:


startGameSplash = Content.Load<Texture2D>("start-splash");
scoreFont = Content.Load<SpriteFont>("Score");
stateFont = Content.Load<SpriteFont>("GameState");

4. Draw the score


Go to the Draw method of Game1.cs and add the following code just before spriteBatch.End();

spriteBatch.DrawString(scoreFont, score.ToString(),
new Vector2(screenWidth - 100, 50), Color.Black);

The code above uses the sprite description we created (Arial Size 36) to draw the players current score near the
top right corner of the screen.
5. Draw horizontally centered text
When making a game, you will often want to draw text that is centered, either horizontally or vertically. To
horizontally center the introductory text, add this code to the Draw method just before spriteBatch.End();

if (!gameStarted)
{
// Fill the screen with black before the game starts
spriteBatch.Draw(startGameSplash, new Rectangle(0, 0,
(int)screenWidth, (int)screenHeight), Color.White);

String title = "VEGGIE JUMP";


String pressSpace = "Press Space to start";

// Measure the size of text in the given font


Vector2 titleSize = stateFont.MeasureString(title);
Vector2 pressSpaceSize = stateFont.MeasureString(pressSpace);

// Draw the text horizontally centered


spriteBatch.DrawString(stateFont, title,
new Vector2(screenWidth / 2 - titleSize.X / 2, screenHeight / 3),
Color.ForestGreen);
spriteBatch.DrawString(stateFont, pressSpace,
new Vector2(screenWidth / 2 - pressSpaceSize.X / 2,
screenHeight / 2), Color.White);
}

First we create two Strings, one for each line of text we want to draw. Next, we measure the width and height of
each line when printed, using the SpriteFont.MeasureString(String) method. This gives us the size as a Vector2
object, with the X property containing its width, and Y its height.
Finally, we draw each line. To center the text horizontally, we make the X value of its position vector equal to
screenWidth / 2 - textSize.X / 2
Challenge: how would you change the procedure above to center the text vertically as well as horizontally?
Try running the game. Do you see the intro splash screen? Does the score count up each time the broccoli
respawns?
Collision detection
So we have a broccoli that follows you around, and we have a score that ticks up each time a new one spawnsbut
as it is there is no way to actually lose this game. We need a way to know if the dino and broccoli sprites collide,
and if when they do, to declare the game over.
1. Rectangular collision
When detecting collisions in a game, objects are often simplified to reduce the complexity of the math involved. We
are going to treat both the player avatar and broccoli obstacle as rectangles for the purpose of detecting collision
between them.
Open SpriteClass.cs and add a new class variable:

const float HITBOXSCALE = .5f;

This value will represent how forgiving the collision detection is for the player. With a value of .5f, the edges of
the rectangle in which the dino can collide with the broccolioften call the hitboxwill be half of the full size of
the texture. This will result in few instances where the corners of the two textures collide, without any parts of the
images actually appearing to touch. Feel free to tweak this value to your personal taste.
Next, add a new method to SpriteClass.cs:

public bool RectangleCollision(SpriteClass otherSprite)


{
if (this.x + this.texture.Width * this.scale * HITBOXSCALE / 2 < otherSprite.x - otherSprite.texture.Width * otherSprite.scale / 2) return false;
if (this.y + this.texture.Height * this.scale * HITBOXSCALE / 2 < otherSprite.y - otherSprite.texture.Height * otherSprite.scale / 2) return false;
if (this.x - this.texture.Width * this.scale * HITBOXSCALE / 2 > otherSprite.x + otherSprite.texture.Width * otherSprite.scale / 2) return false;
if (this.y - this.texture.Height * this.scale * HITBOXSCALE / 2 > otherSprite.y + otherSprite.texture.Height * otherSprite.scale / 2) return false;
return true;
}

This method detects if two rectangular objects have collided. The algorithm works by testing to see if there is a gap
between any of the side sides of the rectangles. If there is any gap, there is no collisionif no gap exists, there must
be a collision.
2. Load new textures
Then, open Game1.cs and add two new class variables, one to store the game over sprite texture, and a Boolean to
track the games state:
Texture2D gameOverTexture;
bool gameOver;

Then, initialize gameOver in the Initialize method:

gameOver = false;

Finally, load the texture into gameOverTexture in the LoadContent method:

gameOverTexture = Content.Load<Texture2D>("game-over");

3. Implement game over logic


Add this code to the Update method, just after the KeyboardHandler method is called:

if (gameOver)
{
dino.dX = 0;
dino.dY = 0;
broccoli.dX = 0;
broccoli.dY = 0;
broccoli.dA = 0;
}

This will cause all motion to stop when the game has ended, freezing the dino and broccoli sprites in their current
positions.
Next, at the end of the Update method, just before base.Update(gameTime), add this line:

if (dino.RectangleCollision(broccoli)) gameOver = true;

This calls the RectangleCollision method we created in SpriteClass, and flags the game as over if it returns true.
4. Add user input for resetting the game
Add this code to the KeyboardHandler method, to allow the user to reset them game if they press Enter:

if (gameOver && state.IsKeyDown(Keys.Enter))


StartGame();
gameOver = false;
}

5. Draw game over splash and text


Finally, add this code to the Draw method, just after the first call of spriteBatch.Draw (this should be the call that
draws the grass texture).
if (gameOver)
{
// Draw game over texture
spriteBatch.Draw(gameOverTexture, new Vector2(screenWidth / 2 - gameOverTexture.Width / 2, screenHeight / 4 - gameOverTexture.Width / 2),
Color.White);

String pressEnter = "Press Enter to restart!";

// Measure the size of text in the given font


Vector2 pressEnterSize = stateFont.MeasureString(pressEnter);

// Draw the text horizontally centered


spriteBatch.DrawString(stateFont, pressEnter, new Vector2(screenWidth / 2 - pressEnterSize.X / 2, screenHeight - 200), Color.White);
}

Here we use the same method as before to draw text horizontally centered (reusing the font we used for the intro
splash), as well as centering gameOverTexture in the top half of the window.
And were done! Try running the game again. If you followed the steps above, the game should now end when the
dino collides with the broccoli, and the player should be prompted to restart the game by pressing the Enter key.

Publish to the Windows Store


Because we built this game as a UWP app, it is possible to publish this project to the Windows Store. There are a
few steps to the process.
You must be registered as a Windows Developer.
You must use the app submission checklist.
The app must be submitted for certification.
For more details, see Publishing your Windows Store app.
Get Started Tutorial - Adding WebVR support to a
3D Babylon.js game
5/11/2017 9 min to read Edit Online

If you've created a 3D game with Babylon.js and thought that it might look great in virtual reality (VR), follow the
simple steps in this tutorial to make that a reality.
We'll add WebVR support to the game shown here. Go ahead and plug in an Xbox controller to try it out!
EDIT ON
HTML CSS JS Result

Create

Log InI'm afraid


404 (Page Not Found)
Signyou've
Up found a page that doesn't really exist. That can happen when you follow a link to
something that has since been deleted. Or the link was incorrect to begin with.

This is a 3D game that works well on a flat screen, but what about in VR? In this tutorial, we'll walk through the few
steps it takes to get this up and running with WebVR. Well use a Windows Mixed Reality headset that can tap into
the added support for WebVR in Microsoft Edge. After we apply these changes to the game, you can expect it also
to work in other browser/headset combinations that support WebVR.

Prerequisites
A text editor (like Visual Studio Code)
An Xbox controller thats plugged in to your computer
Windows 10 Creators Update
A computer with the minimum required specs to run Windows Mixed Reality
A Windows Mixed Reality device (Optional)

Getting started
The simplest way to get started is to visit the Windows-tutorials-web GitHub repo, press the green Clone or
download button, and select Open in Visual Studio.
If you don't want to clone the project, you can download it as a zip file. You'll then have two folders, before and
after. The "before" folder is our game before any VR features are added, and the "after" folder is the finished game
with VR support.
The before and after folders contain these files:
textures/ - A folder containing any images used in the game.
css/ - A folder containing the CSS for the game.
js/ - A folder containing the JavaScript files. The main.js file is our game, and the other files are the libraries
used.
models/ - A folder containing the 3D models. For this game we have only one model, for the dinosaur.
index.html - The webpage that hosts the game's renderer. Opening this page in Edge launches the game.
You can test both versions of the game by opening their respective index.html files in Edge.

The Mixed Reality Portal


If you're unfamiliar with Windows Mixed Reality and have the Windows 10 Creators Update installed on a
computer with a compatible graphics card, try opening the Mixed Reality Portal app from the Start menu in
Windows 10.

If you met all the requirements, you can then turn on developer features and simulate a Windows Mixed Reality
headset plugged in to your computer. If you're fortunate enough to have an actual headset nearby, plug it in and
run the setup.

IMPORTANT
The Mixed Reality Portal must be open at all times during this tutorial.

You're now ready to experience WebVR with Edge.

2D UI in a virtual world
NOTE
Grab the before folder to get the starter code.

Because the Canvas2D element that is currently being used doesn't work well in virtual reality, we'll be cutting or
changing all the 2D UI in our game. We'll be updating the start UI to work in VR, but we'll forgo the distance
counter and game-over UI to keep things simple.
Step 1: Creating a WorldSpaceCanvas2D object
Within the create2d() function, we'll strip everything out and add a new Text2D object to hold our UI text. We'll then
use that Text2D object with a new WorldSpaceCanvas2D object. WorldSpaceCanvas2D is 2D UI that can be placed in a
3D environment (unlike the ScreenSpaceCanvas2D object, which adds a layer of UI on top of the 3D canvas).
Paste this code over the existing var create2d = function... code.

var create2d = function (scene) {


// Start button UI
startUI = new BABYLON.Rectangle2D({
id: "startUI",
children:
[
new BABYLON.Text2D("Left click to enter VR", {
size: new BABYLON.Size(110, 15), marginBottom: "20", textAlignment: "h: left, v: top",
wordWrap: true, fontName: "7pt Arial", fontSignedDistanceField: true
})
]
});

var canvas = new BABYLON.WorldSpaceCanvas2D(scene, new BABYLON.Size(105, 40), {


id: "ScreenCanvas",
backgroundFill: "#000000F2",
backgroundRoundRadius: 5,
children: [startUI]
});
return canvas;
};

Our 2D UI is now ready to be added to our scene.


Step 2: Positioning 2D UI
Within the createScene function, we'll now write a few lines of code to add the UI from our scene and position it so
that it's in front of the user.
Paste this code after skybox.material = skyboxMaterial; .

canvas2d = create2d(scene);
canvas2d.worldSpaceCanvasNode.position = new BABYLON.Vector3(0, 30, 175);

Step 3: Toggling 2D UI visibility


To make the start UI disappear after the game starts, we'll tweak the A button-press check to include an
isVisible = false; call on canvas2d .

Paste this code over your current xboxpad.onbuttondown call.


xboxpad.onbuttondown(function (buttonValue) {
// When the A button is pressed, either start or reload the game depending on the game state
if (buttonValue == BABYLON.Xbox360Button.A) {

// Game is over, reload it


if (gameOver) {
location.href = location.href;
}
// Game has begun
else {
// Hide start UI
canvas2d.worldSpaceCanvasNode.isVisible = false;
begin = true;
// Start looping the dino walking animation
scene.beginAnimation(dino.skeleton, 111, 130, true, 1);
}
}
});

Step 4: Resizing
As a final note on our UI, we can now update the onWindowResize() function to remove any references to the UI
because it's no longer impacted by the size of the window.
Paste the following code over the onWindowResize() function.

function onWindowResize() {
engine.resize();
}

You can load the game by opening the index.html file in Edge. And there you have it: 2D UI in a 3D world!

Detecting headsets
It's good practice for VR apps to have two types of cameras so that multiple scenarios can be supported. For this
game, we'll support one camera that requires a working headset to be plugged in, and another that uses no
headset. To determine which one the game will use, we must first check to see whether a headset has been
detected. To do that, well use navigator.getVRDisplays().
Add this code above window.addEventListener('DOMContentLoaded') .

var headset;
// If a VR headset is connected, get its info
navigator.getVRDisplays().then(function (displays) {
if (displays[0]) {
headset = displays[0];
}
});

With the info stored in the headset variable, we'll now be able to choose the camera thats right for the user.

Selecting the initial camera


With Babylon.js, WebVR can be added quickly by using the WebVRFreeCamera. This camera can take keyboard
input and enables you to use a VR headset to control your "head" rotation.
Step 1: Checking for headsets
For our fallback camera, we'll be using the UniversalCamera thats currently used in the original game.
We'll check our headset variable to determine whether we can use the WebVRFreeCamera camera.
Replace camera = new BABYLON.UniversalCamera("Camera", new BABYLON.Vector3(0, 18, -45), scene); with the following code.

if(headset){
// Create a WebVR camera with the trackPosition property set to false so that we can control movement with the gamepad
camera = new BABYLON.WebVRFreeCamera("vrcamera", new BABYLON.Vector3(0, 14, 0), scene, true, { trackPosition: false });
camera.deviceScaleFactor = 1;
} else {
// No headset, use universal camera
camera = new BABYLON.UniversalCamera("camera", new BABYLON.Vector3(0, 18, -45), scene);
}

Step 2: Activating the WebVRFreeCamera


To activate this camera in most browsers, the user must perform some interaction that requests the virtual
experience.
Now we'll hook this functionality up to a mouse click, and update our start UI text to show a different set of
instructions after doing so.
Paste the code within createScene() function after camera.applyGravity = true; .

scene.onPointerDown = function () {
startUI.children[0].text = "Dino is to your right! Press A button to start. L analog stick to move.";
scene.onPointerDown = undefined
camera.attachControl(canvas, true);
}

A click in the game now creates a prompt like the following, or displays the game in the headset right away if the
user has encountered the prompt before.

Step 3: Adding gamepad support


Because the WebVRFreeCamera doesn't initially support gamepads, we'll map our gamepad buttons to the
keyboard arrow keys. We'll do this by digging into the input property of the camera. By adding the corresponding
codes for left analog stick up, down, left, and right to match up with the arrow keys, our gamepad is back in action.
Add this code below the `scene.onPointerDown = function() {...} call.

// Custom input, adding Xbox controller support for left analog stick to map to keyboard arrows
camera.inputs.attached.keyboard.keysUp.push(211); // Left analog up
camera.inputs.attached.keyboard.keysDown.push(212); // Left analog down
camera.inputs.attached.keyboard.keysLeft.push(214); // Left analog left
camera.inputs.attached.keyboard.keysRight.push(213); // Left analog right

For this game, wherever the user looks will be forward. For example, if they look at a wall and push up on the left
analog stick, they'll move towards the wall.
Step 4: Give it a try!
If we open index.html with our headset and game controller plugged in, a left click on the blue game window will
switch our game to VR mode! Go ahead and put on your headset to check out the results.
In the next section, we'll cover the unpleasantness that occurs when you exit VR mode while in the Edge browser,
and what should happen when a headset isn't plugged in.

Swapping between cameras


With only the WebVRFreeCamera available, things can go awry in the Edge browser when you try to escape from
WebVR (because this camera works only while a headset is displaying content).
When the scene suddenly loses an active camera, the display in Edge will switch between views, causing a flickering
effect. To prevent this, we'll add a backup UniversalCamera to display after we've taken our headset off, pressed
ESC, or switched between tabs in Edge.
A VR headset can be plugged in but not displaying content (presenting). With the headset variable available to us,
we can now use our animate() function to see whether the headset is presenting using the isPresenting property. If it
is, keep the WebVRFreeCamera active; if it isn't, switch to the backup UniversalCamera.
Add this if check under engine.runRenderLoop() .

// Determine which camera should be showing depending on whether or not the headset is presenting
if (headset) {
if (!(headset.isPresenting)) {
var camera2 = new BABYLON.UniversalCamera("Camera", new BABYLON.Vector3(0, 18, -45), scene);
scene.activeCamera = camera2;
} else {
scene.activeCamera = camera;
}
}
Ending the game and fog changes
The last pieces we'll add are a couple calls to adjust the color of our fog. While this doesn't relate to WebVR, it's a
nice finishing touch to the game. This will add a tint to our sky when the dinosaur detects the player and after the
player has been caught.
Step 1: Player detected changes
When the dinosaur has detected the player, we'll make the fog turn red. If the player evades the dinosaur, we make
sure to switch the sky back to normal (grey).
Replace your current beginChase() function with this code.

function beginChase(distanceAway) {
if (distanceAway < CHASERANGE) {
// Change fog to red
scene.fogColor = new BABYLON.Color3(.5, 0, 0);
dino.lookAt(new BABYLON.Vector3(camera.position.x, dino.position.y, camera.position.z));
// Switch fog back to grey, dino out of range
} else {
scene.fogColor = new BABYLON.Color3(0.9, 0.9, 0.85);
}
}

Step 2: Player caught changes


To make the sky turn black after the player has been caught, we'll add a color change to the beginning of the
caught() function. Within caught() ,we also want to prevent the player from moving their body. We can do this by
removing the FreeCameraKeyboardMoveInput . This means the player won't be able to move, and will be allowed only to
look around with their head.
Replace your current caught() function with this code.

function caught() {
// Change fog to black
scene.fogColor = new BABYLON.Color3(0, 0, 0);
gameOver = true;

// Disable all movement except head rotation


camera.inputs.removeByType("FreeCameraKeyboardMoveInput");

if (frameCount % ROARDIVISOR == 0) {
dino.skeleton.beginAnimation("roar", false, .5, function () {
dino.skeleton.beginAnimation("stand", true, .5);
});
}
frameCount++;
}
Conclusion
Congratulations! You now have a complete Babylon.js game with WebVR support. From here you can take what
you've learned to build an even better game, or build off this one.
Plan your Universal Windows Platform (UWP) app
8/10/2017 19 min to read Edit Online

On Microsoft design teams, our process for creating apps consists of five distinct stages: concept, structure,
dynamics, visual, and prototype. We encourage you to adopt a similar process and have fun making new
experiences for the world to enjoy.

Concept
Focus your app
When planning your Universal Windows Platform (UWP) app, you should determine not only what your app will do
and who it's for, but also what your app will be great at. At the core of every great app is a strong concept that
provides a solid foundation.
Say you want to create a photo app. Thinking about the reasons users work with, save, and share their photos,
youll realize that they want to relive memories, connect with others through the photos, and keep the photos safe.
These, then, are the things that you want the app to be great at, and you use these experience goals to guide you
through the rest of the design process.
What's your app about? Start with a broad concept and list all of the things that you want to help users do with
your app.
For example, suppose you want to build an app that helps people plan their trips. Here are some ideas you might
sketch out on the back of a napkin:
Get maps of all the places on an itinerary, and take them with you on the trip.
Find out about special events happening while you're in a city.
Let travel buddies create separate but shareable lists of must-do activities and must-see attractions.
Let travel buddies compile all of their photos to share with friends and family.
Get recommended destinations based on flight prices.
Find a consolidated list of deals for restaurants, shops, and activities around your destination.

What's your app great at? Take a step back and look at your list of ideas to see if a particular scenario really
jumps out at you. Challenge yourself to trim the list to just a single scenario that you want to focus on. In the
process, you might cross off many good ideas, but saying "no" to them is crucial to making a single scenario great.
After you choose a single scenario, decide how you would explain to an average person what your app is great at
by writing it down in one sentence. For example:
My travel app is great at helping friends create itineraries collaboratively for group trips.
My workout app is great at letting friends track their workout progress and share their achievements with each
other.
My grocery app is great at helping families coordinate their weekly grocery shopping so they never miss or
duplicate a purchase.

This is your app's "great at" statement, and it can guide many design decisions and tradeoffs that you make as you
build your app. Focus on the scenarios you want users to experience in your app, and be careful not to turn this into
a feature list. It should be about what your users will be able to do, as opposed to what your app will be able to do.
The design funnel
Its very temptinghaving thought of an idea you liketo go ahead and develop it, perhaps even taking it quite a
ways into production. But lets say you do that and then another interesting idea comes along. Its natural that youll
be tempted to stick with the idea youve already invested in regardless of the relative merits of the two ideas. If only
youd thought of that other idea earlier in the process! Well, the design funnel is a technique to help uncover your
best ideas as early as possible.
The term "funnel" comes from its shape. At the wide end of the funnel, many ideas go in and each one is realized as
a very low-fidelity design artifact (a sketch, perhaps, or a paragraph of text). As this collection of ideas travels
through toward the narrow end of the funnel, the number of ideas is trimmed down while the fidelity of the
artifacts representing the ideas increases. Each artifact should capture only the information necessary to judge one
idea against another, or to answer a particular question such as "is this usable, or intuitive?". Put no more time and
effort into each than that. Some ideas will fall by the wayside as you test them, and youll be okay with that because
you wont be invested in them any more than was necessary to judge the idea. Ideas that survive to move further
into the funnel will receive successively high-fidelity treatments. In the end, youll have a single design artifact that
represents the winning idea. This is the idea that won because of its merits, not merely because it came along first.
You will have designed the best app you could.

Structure
Organization makes everything easier
When you're happy with your concept, you're ready for the next stagecreating your app's blueprint. Information
architecture (IA) gives your content the structural integrity it needs. It helps define your app's navigational model
and, ultimately, your app's identity. By planning how your content will be organizedand how your users will
discover that contentyou can get a better idea of how users will experience your app.
Good IA not only facilitates user scenarios, but it helps you envision the key screens to start with. The Audible app,
for example, launches directly into a hub that provides access to the user's library, store, news, and stats. The
experience is focused, so users can get and enjoy audiobooks quickly. Deeper levels of the app focus on more
specific tasks.
For related guidelines, see Navigation design basics.

Dynamics
Execute your concept
If the concept stage is about defining your app's purpose, the dynamics stage is all about executing that purpose.
This can be accomplished in many ways, such as using wireframes to sketch out your page flows (how you get
from one place to the next within the app to achieve their goals), and thinking about the voice and the words used
throughout your app's UI. Wireframes are a quick, low-fidelity tool to help you make critical decisions about your
app's user flow.
Your app flow should be tightly tied to your "great at" statement, and should help users achieve that single scenario
that you want to light up. Great apps have flows that are easy to learn, and require minimal effort. Start thinking on
a screen-to-screen levelsee your app as if you're using it for the first time. When you pinpoint user scenarios for
pages you create, you'll give people exactly what they want without lots of unnecessary screen touches. Dynamics
are also about motion. The right motion capabilities will determine fluidity and ease of use from one page to the
next.
Common techniques to help with this step:
Outline the flow: What comes first, what comes next?
Storyboard the flow: How should users move through your UI to complete the flow?
Prototype: Try out the flow with a quick prototype.
What should users be able to do? For example, the travel app is "great at helping friends collaboratively create
itineraries for group trips." Let's list the flows that we want to enable:
Create a trip with general information.
Invite friends to join a trip.
Join a friend's trip.
See itineraries recommended by other travelers.
Add destinations and activities to trips.
Edit and comment on destinations and activities that friends added.
Share itineraries for friends and families to follow.

Visual
Speak without words

Once you've established the dynamics of your app, you can make your app shine with the right visual polish. Great
visuals define not only how your app looks, but how it feels and comes alive through animation and motion. Your
choice of color palette, icon, and artwork are just a few examples of this visual language.
All apps have their own unique identity, so explore the visual directions you can take with your app. Let the content
guide the look and feel; don't let the look dictate your content.

Prototype
Refine your masterpiece
Prototyping is a stage in the design funnela technique we talked about earlierat which the artifact representing
your idea develops into something more than a sketch, but less complicated than a complete app. A prototype
might be a flow of hand-drawn screens shown to a user. The person running the test might respond to cues from
the user by placing different screens down, or sticking or unsticking smaller pieces of UI on the pages, to simulate a
running app. Or, a prototype might be a very simple app that simulates some workflows, provided the operator
sticks to a script and pushes the right buttons. At this stage, your ideas begin to really come alive and your hard
work is tested in earnest. When prototyping areas of your app, take the time to sculpt and refine the components
that need it the most.
To new developers, we can't stress enough: Making great apps is an iterative process. We recommend that you
prototype early and often. Like any creative endeavor, the best apps are the product of intensive trial and error.

Decide what features to include


When you know what your users want and how you can help them get there, you can look at the specific tools in
your toolbox. Explore the Universal Windows Platform (UWP) and associate features with your app's needs. Be sure
to follow the user experience (UX) guidelines for each feature.
Common techniques:
Platform research: Find out what features the platform offers and how you can use them.
Association diagrams: Connect your flows with features.
Prototype: Exercise the features to ensure that they do what you need.
App contracts Your app can participate in app contracts that enable broad, cross-app, cross-feature user flows.
Share Let your users share content from your app with other people through other apps, and receive shareable
content from other people and apps, too.
Play To Let your users enjoy audio, video, or images streamed from your app to other devices in their home
network.
File picker and file picker extensions Let your users load and save their files from the local file system,
connected storage devices, HomeGroup, or even other apps. You can also provide a file picker extension so
other apps can load your app's content.
For more info, see App contracts and extensions.
Different views, form factors, and hardware configurations Windows puts users in charge and your app in the
forefront. You want your app UI to shine on any device, using any input mode, in any orientation, in any hardware
configuration, and in whatever circumstance the user decides to use it.
Touch first Windows provides a unique and distinctive touch experience that does more than simply emulate
mouse functionality.
For example, semantic zoom is a touch-optimized way to navigate through a large set of content. Users can pan or
scroll through categories of content, and then zoom in on those categories to view more and more detailed
information. You can use this to present your content in a more tactile, visual, and informative way than with
traditional navigation and layout patterns like tabs.
Of course, you can take advantage of a number of touch interactions, like rotate, pan, swipe, and others. Learn more
about Touch and other user interactions.
Engaging and fresh Be sure your app feels fresh and engages users with these standard experiences:
Animations Use our library of animations to make your app fast and fluid for your users. Help users
understand context changes and tie experiences together with visual transitions. Learn more about animating
your UI.
Toast notifications Let your users know about time-sensitive or personally relevant content through toast
notifications, and invite them back to your app even when your app is closed. Learn more about tiles, badges,
and toast notifications.
App tiles Provide fresh and relevant updates to entice users back into your app. There's more info about this in
the next section. Learn more about app tiles.
Personalization
Settings Let your users create the experience they want by saving app settings. Consolidate all of your settings
on one screen, and then users can configure your app through a common mechanism that they are already
familiar with. Learn more about Adding app settings.
Roaming Create a continuous experience across devices by roaming data that lets users pick up a task right
where they left off and preserves the UX they care most about, regardless of the device they're using. Make it
easy to use your app anywheretheir kitchen family PC, their work PC, their personal tablet, and other form
factorsby maintaining settings and states with roaming. Learn more about Managing application data and see
Guidelines for roaming application data.
User tiles Make your app more personal to your users by loading their user tile image, or let the users set
content from your app as their personal tile throughout Windows.
Device capabilities Be sure your app takes full advantage of the capabilities of today's devices.
Proximity gestures Let your users connect devices with other users who are physically in close proximity, by
physically tapping the devices together (multiplayer games). Learn more about proximity and tapping.
Cameras and external storage devices Connect your users to their built-in or plugged-in cameras for
chatting and conferencing, recording vlogs, taking profile pics, documenting the world around them, or
whatever activity your app is great at. Learn more about Accessing content on removable storage.
Accelerometers and other sensors Devices come with a number of sensors nowadays. Your app can dim or
brighten the display based on ambient light, reflow the UI if the user rotates the display, or react to any physical
movement. Learn more about sensors.
Geolocation Use geolocation information from standard web data or from geolocation sensors to help your
users get around, find their position on a map, or get notices about nearby people, activities, and destinations.
Learn more about geolocation.
Let's consider the travel app example again. To be great at helping friends collaboratively create itineraries for
group trips, you could use some of these features, just to name a few:
Share: Users share upcoming trips and their itineraries to multiple social networks to share the pre-trip
excitement with their friends and families.
Search: Users search for and find activities or destinations from others' shared or public itineraries that they can
include in their own trips.
Notifications: Users are notified when travel companions update their itineraries.
Settings: Users configure the app to their preference, like which trip should bring up notifications or which social
groups are allowed to search the users' itineraries.
Semantic zoom: Users navigate through the timeline of their itinerary and zoom in to see greater details of the
long list of activities they've planned.
User tiles: Users choose the picture they want to appear when they share their trip with friends.

Decide how to monetize your app


You have a lot of options for earning money from your app. If you decide to use in-app ads or sales, you'll want to
design your UI to support that. For more information, see Plan for monetization.

Design the UX for your app


This is about getting the basics right. Now that you know what your app is great at, and you've figured out the
flows that you want to support, you can start to think about the fundamentals of user experience (UX) design.
How should you organize UI content? Most app content can be organized into some form of groupings or
hierarchies. What you choose as the top-level grouping of your content should match the focus of your "great at"
statement.
To use the travel app as an example, there are multiple ways to group itineraries. If the focus of the app is
discovering interesting destinations, you might group them based on interest, like adventure, fun in the sun, or
romantic getaways. However, because the focus of the app is planning trips with friends, it makes more sense to
organize itineraries based on social circles, like family, friends, or work.
Choosing how you want to group your content helps you decide what pages or views you need in your app. See UI
basics for more info.
How should you present UI content? After you've decided how to organize your UI, you can define UX goals that
specify how your UI gets built and presented to your user. In any scenario, you want to make sure that your user
can continue using and enjoying your app as quickly as possible. To do this, decide what parts of your UI need to be
presented first, and make sure that those parts are complete before you spend time building the noncritical parts.
In the travel app, probably the first thing the user will want to do in the app is find a specific trip itinerary. To
present this info as fast as possible, you should show the list of trips first, using a ListView control.
After showing the trips list, you could start loading other features, like a news feed of their friends' trips.
What UI surfaces and commands do you need? Review the flows that you identified earlier. For each flow,
create a rough outline of the steps users take.
Let's look at the "Share itineraries for friends and families to follow" flow. We'll assume that the user has already
created a trip. Sharing a trip itinerary might require these steps:
1. The user opens the app and sees a list of trips she created.
2. The user taps on the trip she wants to share.
3. The details of the trip appear on screen.
4. The user accesses some UI to initiate sharing.
5. The user selects or enters the email address or name of the friend she wants to share the trip with.
6. The user accesses some UI to finalize sharing.
7. Your app updates the trip details with the list of people she has shared her trip with.
During this process, you begin to see what UI you need to create and the additional details you need to figure out
(like drafting a standard email boilerplate for friends who aren't using your app yet). You also can start eliminating
unnecessary steps. Perhaps the user doesn't actually need to see the details of the trip before sharing, for example.
The cleaner the flow, the easier to use.
For more details on how to use different surfaces, take a look at .
What should the flow feel like? When you have defined the steps your user will take, you can turn that flow into
performance goals. For more info, see Plan for performance.
How should you organize commands? Use your outline of the flow steps to identify potential commands that
you need to design for. Then think about where to use those commands in your app.
Always try to use the content. Whenever possible, let users directly manipulate the content on the app's
canvas, rather than adding commands that act on the content. For example, in the travel app, let users rearrange
their itinerary by dragging and dropping activities in a list on the canvas, rather than by selecting the activity and
using Up or Down command buttons.
If you can't use the content. Place commands on one of these UI surfaces if you are not able to use the
content:
In the command bar: You should put most commands on the command bar, which is usually hidden until
the user taps to make it visible.
On the app's canvas: If the user is on a page or view that has a single purpose, you can provide
commands for that purpose directly on the canvas. There should be very few of these commands.
In a context menu: You can use context menus for clipboard actions (such as cut, copy, and paste), or for
commands that apply to content that cannot be selected (like adding a push pin to a location on a map).
Decide how to lay out your app in each view. Windows supports landscape and portrait orientations and
supports resizing apps to any width, from full screen to a minimum width. You want your app to look and work
great at any size, on any screen, in either orientation. This means you need to plan the layout of your UI elements
for different sizes and views. When you do this, your app UI changes fluidly to meet your user's needs and
preferences.

For more info on designing for different screen sizes, see Screen sizes and break points for responsive design.

Make a good first impression


Think about what you want users to think, feel, or do when they first launch your app. Refer back to your "great at"
statement. Even though you won't get a chance to personally tell your users what your app is great at, you can
convey the message to them when you make your first impression. Take advantage of these:
Tile and notifications The tile is the face of your app. Among the many other apps on a user's Start screen, what
will make the user want to launch your app? Be sure your tile highlights your app's brand and shows what the app
is great at. Use tile notifications so your app will always feel fresh and relevant, bringing the user back to your app
again and again.
Splash screen The splash screen should load as fast as possible, and remain on the screen only as long as you
need to initialize your app state. What you show on the splash screen should express your app's personality.
First launch Before users sign up for your service, log in to their account, or add their own content, what will they
see? Try to demonstrate the value of your app before asking users for information. Consider showing sample
content so people can look around and understand what your app does before you ask them to commit.
Home page The home page is where you bring users each time they launch your app. The content here should
have a clear focus, and immediately showcase what your app is tailored to do. Make this page great at one thing
and trust that people will explore the rest of your app. Focus on eliminating distractions on the landing page, and
not on discoverability.

Validate your design


Before you get too far into developing your app, you should validate your design or prototype against guidelines,
user impressions, and requirements to avoid having to rework it later. Each feature has a set of UX guidelines to
help you polish your app, and a set of Store requirements that you must meet to publish your app in the Windows
Store. You can use the Windows App Certification Kit to test for technical compliance with Store requirements. You
can also use the performance tools in Microsoft Visual Studio to make sure that you're giving your users a great
experience in every scenario.
Use the detailed UX guidelines for UWP apps to stay focused on important features. Use the Visual Studio
performance tools to analyze the performance of each of your app's scenarios.
3/20/2017 3 min to read Edit Online

What's next?
So you want to write an app and publish it to the Windows Store: where do you start? If you're completely new to
the UWP platform, try some of the Channel 9 videos and Microsoft Virtual Academy and LinkedIn Learning
courses. If you are already familiar with Windows development, you can start reading through the topics below, or
go straight to downloading some samples.
There are many tools and frameworks available to help you write apps, and many support cross-platform
development. For example, if you want to write 2D games, you might want to look at Monogame or some of the
many JavaScript/HTML frameworks. For 3D games, there's Unity, and don't forget Xamarin if your focus is mobile
devices.
If you want to get started writing something that isn't a game, our recommendation is that you look through the
UWP topics to get a feel for the platform, and then investigate creating your user interface by using, and then
customizing, XAML controls. You'll use XAML to design your app (here's a tutorial that will walk you through it), but
XAML's main strength is the use of data binding which couples the controls to the information your app wants to
display: if you are new to the Windows platform, this will be an important concept to understand.

UWP and the UWP app Lifecycle


How does an app start, what happens when you start another one? Heres the story.
Guide to Universal Windows Platform (UWP) apps
UWP app lifecycle
What's cool in Windows 10

UX and UI
What controls do you have at your disposal, and how can they be used? These topics explain how controls and
code work together, and how you can customize them to suit the look of your app.
Design and UI
Define page layouts with XAML
Controls by function
Intro to controls and patterns
Styling controls
Screen sizes and break points for responsive design
Use the UWP Community Toolkit for a selection of prebuilt controls and patterns
Data and Services
Learn about data binding, which lets your code automatically populate lists and grids. Discover how to link to
external resources to get data into your apps.
Data binding
ListViews, GridViews and data binding
Data access

Publishing
Share your work with the world, make money. Well walk you through the process of getting your app onto the
store.
Publish Windows apps
Packaging apps

Other resources
Samples, tutorials, videos, other tools and SDKs. Take it to the next level.
How-to articles
Code samples
C# reference
API Reference
Writing apps for Xbox One
Developing for HoloLens
Porting apps to Windows 10
Writing apps for the Enterprise
The UWP Community Toolkit

Windows Developer Blog


The Windows Developer Blog includes regular postings on the latest in coding techniques, project ideas, and tools.
Here are some you might find useful as you explore Windows development.
Animations with the Visual layer
Interop between XAML and the Visual layer
Creating beautiful effects for UWP
Beautiful apps made possible and easy with Windows.UI
Polishing your app with animation and audio cues
Adding color to your design

Finding help in the Dev Center


The docs.microsoft.com site contains a multitude of documentation for many different tools, frameworks and
platforms. When you are browsing for topics and samples, you should make sure you are reading UWP specific
content. You'll find the UWP reference starts at the Windows Dev Center, and the API reference you need is at
Develop UWP apps. When reading content that is specifically for UWP, the URL path will contain uwp, and so will
the path displayed at the top of the page, like this:
When using a search engine, appending "Windows app development" to your search string will more often than
not lead you to UWP content.

Important Dev Center topics


Here is a list of the key sections of content in the DevCenter.

Design Design guidelines for UWP apps.

Develop Detailed info and coding examples for the many of the features available to your app.

Language reference The programming languages available for UWP development.

Games Developing games with DirectX.

Internet of Things Building your own connected devices.

Porting Leverage your Android and iOS skills to quickly make UWP apps.

Windows Bridges Tools for updating older apps and iOS apps to UWP.

Xamarin Use C# to write apps for iOS, Android and Windows 10.

Task snippets Ready-to-use code that accomplish small but useful tasks.

How-to topics Sample code covering specific UWP features.

Hardware Hardware for developers from the Microsoft Store.


Get UWP app samples
4/5/2017 1 min to read Edit Online

The Universal Windows Platform (UWP) app samples are available through repositories on GitHub. See Samples
for a searchable, categorized list, or browse the Microsoft/Windows-universal-samples repository, which contains
samples that demonstrate all of the UWP features and their API usage patterns.

Download the code


To download the samples, go to the repository and select Clone or download, then Download ZIP. Or, just click
here.
The zip file will always have the latest samples. You dont need a GitHub account to download it. When an SDK
update is released or if you want to pick up any recent changes/additions, just check back for the latest zip file.
Note: The UWP samples require Visual Studio 2015 or later and the Windows SDK to open, build, and run. You
can get a free copy of Visual Studio Community with support for building UWP apps here.
Also, be sure to unzip the entire archive, and not just individual samples. The samples all depend on the
SharedContent folder in the archive. The UWP feature samples use Linked files in Visual Studio to reduce
duplication of common files, including sample template files and image assets. These common files are stored
in the SharedContent folder at the root of the repository, and are referred to in the project files using links.

After you download the zip file, open the samples in Visual Studio:
1. Before you unzip the archive, right-click it, select Properties > Unblock > Apply. Then, unzip the archive to
a local folder on your machine.

2. Within the samples folder, youll see a number of folders, each of which contains a UWP feature sample.

3. Select a sample, such as Altimeter, and youll see multiple folders indicating the languages supported.
4. Select the language youd like to use, such as CS for C#, and youll see a Visual Studio solution file, which
you can open in Visual Studio.

Give feedback, ask questions, and report issues


If you have problems or questions, just use the Issues tab on the repository to create a new issue and well do what
we can to help.
XAML basics tutorials
9/1/2017 1 min to read Edit Online

This tutorial series covers four fundamental aspects of XAML programming: user interfaces, data binding, custom
styles, and adaptive layouts. Each tutorial track starts with a partially-complete version of the PhotoLab Sample, and
builds one missing component of the final app step-by-step. Note that these tutorials do not build up to the full
sample, so be sure to check out the completed version after you've mastered the basics.

PhotoLab overview
The PhotoLab app has two primary pages:
MainPage.xaml: displays a photo gallery view, along with some information about each image file.

DetailPage.xaml: displays a single photo after it has been selected. A flyout editting menu allows the photo to be
altered, renamed, and saved.
Tutorial overview
Here's a quick summary of each tutorial track.
Create user interfaces shows how to create the basic photo gallery interface.
Create data bindings shows how to add data bindings to the photo gallery, populating it with real image data.
Create custom styles shows how to add fancy custom styles to the photo editing menu.
Create adaptive layouts shows how to make the gallery layout adaptive, so it looks good on every device and
screen size.
Create a user interface
9/1/2017 13 min to read Edit Online

In this tutorial, you'll learn have to create a basic user interface (UI) with common XAML controls and panels by:
Using the XAML tools in Visual Studio, such as XAML Designer, Toolbox, XAML editor, Properties panel, and
Document Outline to add controls and content to your UI
Utilizing some of the most common XAML layout panels, such as RelativePanel, Grid, and StackPanel.
We'll start with a simplified version of the PhotoLab sample. This starter version includes the complete data layer
plus the basic XAML pages, but leaves out many features in order to make the code easier to browse around in.
This tutorial doesn't build up to the complete app, so be sure to check out the final version to see other features
such as custom animations and phone support. You can find the final version in the UWP Academy\XAML\Final
folder.

Prerequisites
Visual Studio 2017 and the Windows 10 SDK (10.0.15063.468 or later)

Part 0: Get the code


The starting point for this lab is located in the PhotoLab sample repository, in the xaml-basics-tutorials/user-
interface/ folder. After you've cloned/downloaded the repo, you can edit the project by openning PhotoLab.sln with
Visual Studio 2017.

Part 1: Add a TextBlock using XAML Designer


Visual Studio provides several tools to make creating your XAML UI easier. XAML Designer lets you drag controls
onto the design surface and see what they'll look like before you run the app. The Properties panel lets you view
and set all the properties of the control that are active in the designer. Document Outline shows the parent-child
structure of the XAML visual tree for your UI. The XAML editor lets you directly enter and modify the XAML
markup.
Here's the Visual Studio UI with the tools labeled.
Each of these tools make creating your UI easier, so we'll use all of them in this tutorial. You'll start by using XAML
Designer to add a control.
Add a control using XAML Designer:
1. Open the UWP Academy\XAML\Basic layout\Start folder and load the PhotoLab solution, then double-click
MainPage.xaml in Solution Explorer to open it. This shows the main page of the app without any UI
elements added.
2. Before going further, you need to make some adjustments to Visual Studio.
Make sure the Solution Platform is set to x86 or x64, not ARM.
Set the main page XAML Designer to show the 13.3" Desktop preview.
You should see both settings near the top of the window, as shown here.

You can run the app now, but you won't see much. Let's add some UI elements to make things more
interesting.
3. In Toolbox, expand Common XAML controls and find the TextBlock control. Drag a TextBlock onto the
design surface near the upper left corner of the page.
The TextBlock 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 TextBlock to indicate that it is now the active object.
Notice the margins and other settings added by the designer. Your XAML will look something like this. Don't
worry if it's not formatted exactly like this; we abbreviated here to make it easier to read.

<TextBlock x:Name="textBlock"
HorizontalAlignment="Left"
Margin="351,44,0,0"
TextWrapping="Wrap"
Text="TextBlock"
VerticalAlignment="Top"/>

In the next steps, you'll update these values.


4. In the Properties panel, change the Name value of the TextBlock from textBlock to TitleTextBlock. (Make
sure the TextBlock is still the active object.)
5. Under Common, change the Text value to Collection.
In the XAML editor, your XAML will now look like this.

<TextBlock x:Name="TitleTextBlock"
HorizontalAlignment="Left"
Margin="351,44,0,0"
TextWrapping="Wrap"
Text="Collection"
VerticalAlignment="Top"/>

6. To position the TextBlock, you should first remove the property values that were added by Visual Studio. In
Document Outline, right-click TitleTextBlock, then select Layout > Reset All.

1. In the Properties panel, enter margin into the search box to easily find the Margin property. Set the left and
bottom margins to 24.

Margins provide the most basic positioning of an element on the page. They're useful for fine-tuning your
layout, but using large margin values like those added by Visual Studio makes it difficult for your UI to adapt
to various screen sizes, and should be avoided.
For more info, see Alignment, margins, and padding.
2. In the Properties panel, enter style into the search box to find the Style property. Click the property marker
for the Style property to open its menu. (The property marker is the small box symbol to the right of each
property value.) On the Property menu, select System Resource > TitleTextBlockStyle. This applies a
system-defined style to your title text.

<TextBlock x:Name="TitleTextBlock"
TextWrapping="Wrap"
Text="Collection"
Margin="24,0,0,24"
Style="{StaticResource TitleTextBlockStyle}"/>

3. In the Properties panel, enter textwrapping into the search box to find the TextWrapping property. Click
the property marker for the TextWrapping property to open its menu. (The property marker is black to
indicate that the property is set to a non-default value.) On the Property menu, select Reset to reset the
TextWrapping property.
Visual Studio adds this property, but it's already set in the style you applied, so you don't need it here.
You've added the first part of the UI to your app! Run the app now to see what it looks like.
You might have noticed that in XAML Designer, your app showed white text on a black background, but when you
ran it, it showed black text on a white background. That's because Windows has both a Dark and a Light theme, and
the default theme varies by device. On a PC, the default theme is Light. You can click the gear icon at the top of
XAML Designer to open Device Preview Settings and change the theme to Light to make the app in XAML Designer
look the same as it does on your PC.

NOTE
In this part of the tutorial, you added a control by dragging-and-dropping. You can also add a control by double-clicking it
in Toolbox. Give it a try, and see the differences in the XAML that Visual Studio generates.

Part 2: Add a GridView control using the XAML editor


In Part 1, you had a taste of using XAML Designer and some of the other tools provided by Visual Studio. Here,
you'll use the XAML editor to work directly with the XAML markup. As you become more familiar with XAML, you
might find that this is a more efficient way for you to work.
First, you'll replace the root layout Grid with a RelativePanel. The RelativePanel makes it easier to rearrange
chunks of UI relative to the panel or other pieces of UI. You'll see its usefulness in the XAML Adaptive Layout
tutorial.
Then, you'll add a GridView control to display your data.
Add a control using the XAML editor
1. In the XAML editor, change the root Grid to a RelativePanel.
Before

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


<TextBlock x:Name="TitleTextBlock"
Text="Collection"
Margin="24,0,0,24"
Style="{StaticResource TitleTextBlockStyle}"/>
</Grid>

After
<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="TitleTextBlock"
Text="Collection"
Margin="24,0,0,24"
Style="{StaticResource TitleTextBlockStyle}"/>
</RelativePanel>

For more info about layout using a RelativePanel, see Layout panels.
2. Below the TextBlock element, add a GridView control named 'ImageGridView'. Set the RelativePanel
attached properties to place the control below the title text and make it stretch across the entire width of the
screen.
Add this XAML

<GridView x:Name="ImageGridView"
Margin="0,0,0,8"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="TitleTextBlock"/>

After the TextBlock

<RelativePanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


<TextBlock x:Name="TitleTextBlock"
Text="Collection"
Margin="24,0,0,24"
Style="{StaticResource TitleTextBlockStyle}"/>

<!-- Add the GridView here. -->

</RelativePanel>

For more info about Panel attached properties, see Layout panels.
3. In order for the GridView to show anything, you need to give it a collection of data to show. Open
MainPage.xaml.cs and find the GetItemsAsync method. This method populates a collection called Images,
which is a property that we've added to MainPage.
After the foreach loop in GetItemsAsync, add this line of code.

ImageGridView.ItemsSource = Images;

This sets the GridView's ItemsSource property to the app's Images collection and gives the GridView
something to show.
This is a good place to run the app and make sure everything's working. It should look something like this.
You'll notice that the app isn't showing images yet. By default, it shows the ToString value of the data type that's in
the collection. Next, you'll create a data template to define how the data is shown.

NOTE
You can find out more about layout using a RelativePanel in the Layout panels article. Take a look, and then experiment
with some different layouts by setting RelativePanel attached properties on the TextBlock and GridView.

Part 3: Add a DataTemplate to display your data


Now, you'll create a DataTemplate that tells the GridView how to display your data. For a full explanation of data
templates, see Item containers and templates.
For now, you'll only be adding placeholders to help you create the layout you want. In the XAML Data Binding
tutorial, you'll replace these placeholders with real data from the ImageFileInfo class. You can open the
ImageFileInfo.cs file now if you want to see what the data object looks like.
Add a data template to a grid view
1. Open MainPage.xaml.
2. To show the rating, you use the RadRating control from the Telerik UI for UWP NuGet package. Add a
XAML namespace reference that specifies the namespace for the Telerik controls. Put this in the opening
Page tag, right after the other 'xmlns:' entries.
Add this XAML

xmlns:telerikInput="using:Telerik.UI.Xaml.Controls.Input"

After the last 'xmlns:' entry


<Page x:Name="page"
x:Class="PhotoLab.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PhotoLab"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:telerikInput="using:Telerik.UI.Xaml.Controls.Input"
mc:Ignorable="d"
NavigationCacheMode="Enabled">

For more info about XAML namespaces, see XAML namespaces and namespace mapping.
3. In Document Outline, right-click ImageGridView. In the context menu, select Edit Additional Templates
> Edit Generated Items (ItemTemplate) > Create Empty.... The Create Resource dialog opens.
4. In the dialog, change the Name (key) value to ImageGridView_DefaultItemTemplate, and then click OK.
Several things happen when you click OK.
A DataTemplate is added to the Page.Resources section of MainPage.xaml.

<Page.Resources>
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate">
<Grid/>
</DataTemplate>
</Page.Resources>

The Document Outline scope is set to this DataTemplate.


When you're done creating the data template, you can click the up arrow in the top left corner of
Document Outline to return to page scope.
The GridView's ItemTemplate property is set to the DataTemplate resource.

<GridView x:Name="ImageGridView"
Margin="0,0,0,8"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="TitleTextBlock"
ItemTemplate="{StaticResource ImageGridView_DefaultItemTemplate}"/>

5. In the ImageGridView_DefaultItemTemplate resource, give the root Grid a Height and Width of 300, and
Margin of 8. Then add two rows and set the Height of the second row to Auto.
Before

<Grid/>

After
<Grid Height="300"
Width="300"
Margin="8">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
</Grid>

For more info about Grid layouts, see Layout panels.


6. Add controls to the Grid.
a. Add an Image control in the first grid row. This is where the image will be shown, but for now, you'll use
the app's store logo as a placeholder.
b. Add TextBlock controls to show the image's name, file type, and dimensions. For this, you use
StackPanel controls to arrange the text blocks.
For more info about StackPanel layout, see Layout panels
c. Add the RadRating control to the outer (vertical) StackPanel. Place it after the inner (horizontal)
StackPanel.
The final template
<Grid Height="300"
Width="300"
Margin="8">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<Image x:Name="ItemImage"
Source="Assets/StoreLogo.png"
Stretch="Uniform" />

<StackPanel Orientation="Vertical"
Grid.Row="1">
<TextBlock Text="ImageTitle"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}" />
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<TextBlock Text="ImageFileType"
HorizontalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}" />
<TextBlock Text="ImageDimensions"
HorizontalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Margin="8,0,0,0" />
</StackPanel>

<telerikInput:RadRating Value="3"
IsReadOnly="True">
<telerikInput:RadRating.FilledIconContentTemplate>
<DataTemplate>
<SymbolIcon Symbol="SolidStar"
Foreground="White" />
</DataTemplate>
</telerikInput:RadRating.FilledIconContentTemplate>
<telerikInput:RadRating.EmptyIconContentTemplate>
<DataTemplate>
<SymbolIcon Symbol="OutlineStar"
Foreground="White" />
</DataTemplate>
</telerikInput:RadRating.EmptyIconContentTemplate>
</telerikInput:RadRating>

</StackPanel>
</Grid>

Run the app now to see the GridView with the item template you just created. You might not see the rating
control, though, because it has white stars on a white background. You'll change the background color next.
Part 4: Modify the item container style
An items control template contains the visuals that display state, like selection, pointer over, and focus. These
visuals are rendered either on top of or below the data template. Here, you'll modify the Background and Margin
properties of the control template to give the GridView items a gray background.
Modify the item container
1. In Document Outline, right-click ImageGridView. On the context menu, select Edit Additional Templates
> Edit Generated Item Container (ItemContainerStyle) > Edit a Copy.... The Create Resource dialog
opens.
2. In the dialog, change the Name (key) value to ImageGridView_DefaultItemContainerStyle, then click OK.
A copy of the default style is added to the Page.Resources section of your XAML.
<Style x:Key="ImageGridView_DefaultItemContainerStyle" TargetType="GridViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="Background" Value="{ThemeResource GridViewItemBackground}"/>
<Setter Property="Foreground" Value="{ThemeResource GridViewItemForeground}"/>
<Setter Property="TabNavigation" Value="Local"/>
<Setter Property="IsHoldingEnabled" Value="True"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,4,4"/>
<Setter Property="MinWidth" Value="{ThemeResource GridViewItemMinWidth}"/>
<Setter Property="MinHeight" Value="{ThemeResource GridViewItemMinHeight}"/>
<Setter Property="AllowDrop" Value="False"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="FocusVisualMargin" Value="-2"/>
<Setter Property="FocusVisualPrimaryBrush" Value="{ThemeResource GridViewItemFocusVisualPrimaryBrush}"/>
<Setter Property="FocusVisualPrimaryThickness" Value="2"/>
<Setter Property="FocusVisualSecondaryBrush" Value="{ThemeResource GridViewItemFocusVisualSecondaryBrush}"/>
<Setter Property="FocusVisualSecondaryThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<!-- XAML removed for clarity
<ListViewItemPresenter ... />
-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

The GridViewItem default style sets a lot of properties. You should always start with a copy of the default
style and modify only the properties necessary. Otherwise, the visuals might not show up the way you
expect because some properties won't be set correctly.
And as in the previous step, the GridView's ItemContainerStyle property is set to the new Style resource.

<GridView x:Name="ImageGridView"
Margin="0,0,0,8"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="TitleTextBlock"
ItemTemplate="{StaticResource ImageGridView_DefaultItemTemplate}"
ItemContainerStyle="{StaticResource ImageGridView_DefaultItemContainerStyle}"/>

3. Change the value for the Background property to Gray.


Before

<Setter Property="Background" Value="{ThemeResource GridViewItemBackground}"/>

After

<Setter Property="Background" Value="Gray"/>

4. Change the value for the Margin property to 8.


Before
<Setter Property="Margin" Value="0,0,4,4"/>

After

<Setter Property="Margin" Value="8"/>

Run the app and see how it looks now. Resize the app window. The GridView takes care of rearranging the images
for you, but at some widths, there's a lot of space on the right side of the app window. It would look better if the
images were centered. We'll take care of that next.

NOTE
If you'd like to experiment, try setting the Background and Margin properties to different values and see what effect it has.

Part 5: Apply some final adjustments to the layout


To center the images in the page, you need to adjust the alignment of the Grid in the page. Or do you need to
adjust the alignment of the Images in the GridView? Does it matter? Let's see.
For more info about alignment, see Alignment, margins, and padding.
(You might try setting the Background of the GridView to your favorite color for this step. It will let you see more
clearly what's happening with the layout.)
Modify the alignment of the images
1. In the Gridview, set the HorizontalAlignment property to Center.
Before
<GridView x:Name="ImageGridView"
Margin="0,0,0,8"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="TitleTextBlock"
ItemTemplate="{StaticResource ImageGridView_DefaultItemTemplate}"
ItemContainerStyle="{StaticResource ImageGridView_DefaultItemContainerStyle}"/>

After

<GridView x:Name="ImageGridView"
Margin="0,0,0,8"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.Below="TitleTextBlock"
ItemTemplate="{StaticResource ImageGridView_DefaultItemTemplate}"
ItemContainerStyle="{StaticResource ImageGridView_DefaultItemContainerStyle}"
HorizontalAlignment="Center"/>

2. Run the app and resize the window. Scroll down to see more images.
The images are centered, which looks better. However, the scrollbar is aligned with the edge of GridView
instead of with the edge of the window. To fix this, you'll center the images in the GridView rather than
centering the GridView in the page. It's a little more work, but it will look better in the end.
3. Remove the HorizontalAlignment setting from the previous step.
4. In Document Outline, right-click ImageGridView. On the context menu, select Edit Additional Templates
> Edit Layout of Items (ItemsPanel) > Edit a Copy.... The Create Resource dialog opens.
5. In the dialog, change the Name (key) value to ImageGridView_ItemsPanelTemplate, and then click OK.
A copy of the default ItemsPanelTemplate is added to the Page.Resources section of your XAML. (And as
before, the GridView is updated to reference this resource.)

<ItemsPanelTemplate x:Key="ImageGridView_ItemsPanelTemplate">
<ItemsWrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>

Just as you've used various panels to layout the controls in your app, the GridView has an internal panel
that manages the layout of its items. Now that you have access to this panel (the ItemsWrapGrid), you can
modify its properties to change the layout of items inside the GridView.
6. In the ItemsWrapGrid, set the HorizontalAlignment property to Center.
Before

<ItemsPanelTemplate x:Key="ImageGridView_ItemsPanelTemplate">
<ItemsWrapGrid Orientation="Horizontal" />
</ItemsPanelTemplate>

After

<ItemsPanelTemplate x:Key="ImageGridView_ItemsPanelTemplate">
<ItemsWrapGrid Orientation="Horizontal"
HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
7. Run the app and resize the window again. Scroll down to see more images.

Now, the scrollbar is aligned with the edge of the window. Good job! You've created the basic UI for your app.

Going further
Now that you've created the basic UI, see the XAML Data Binding tutorial to add real images and data. Or go on to
the XAML Adaptive Layout tutorial to see how to adapt the UI to multiple screen sizes.
Create custom styles
9/1/2017 14 min to read Edit Online

This tutorial shows you how to customize the UI of our XAML app. Warning: this tutorial might or might not involve
a unicorn. (It does!)

Prerequisites
Visual Studio 2017 and the Windows 10 SDK (10.0.15063.468 or later)

Part 0: Get the code


The starting point for this lab is located in the PhotoLab sample repository, in the xaml-basics-tutorials/style/
folder. After you've cloned/downloaded the repo, you can edit the project by openning PhotoLab.sln with Visual
Studio 2017.

Part 1: Create a fancy slider control


Universal Windows Platform (UWP) provides a number of ways to customize the look of your app. From fonts and
typography settings to colors and gradients to blur effects, you have a lot of options.
For the first part of the tutorial, let's jazz up some of our photo editing controls.

A humble slider with default styling.

These sliders are nice--they do all the things a slider should do--but they aren't very fancy. Let's fix that.
The exposure slider adjusts the exposure of the image: slide it to the left and the image gets darker; slider it to the
right and it gets lighter. Let's make our slider cooler by giving it a background that goes from black to white. It'll
make the slider look better, which is great, but it will also provide a visual clue about the functionality that the slider
provides.
Customize a slider control
1. Open the folder for this tutorial: UWP Academy\XAML\Styling\Part1\Start. Double-click the
PhotoLab.sln file to open it in Visual Studio 2017, and then set your Solution Platform to x86 or x64, not
ARM.
Press F5 to compile and run the app. The first screen shows a gallery of images. Click an image to go to the
image details page. Once you're there, click the edit button to see the editing controls we'll be working on.
Exit the app and return to Visual Studio.
2. In the Solution Explorer panel, double-click DetailPage.xaml to open it.
3. Use a Polygon element to create a background shape for the exposure slider.
The Windows.XAML.Ui.Shapes namespace provides seven shapes to choose from. There's an ellipse, a
rectangle, and a thing called a Path, which can make any sort of shape--yes, even a unicorn!

Read about it: The Draw shapes article tells you everything you need to know about XAML shapes.

We want to create a triangle-looking widget--something like the shape you'd see on a stereo's volume
control.
Sounds like a job for the Polygon shape! To define a polygon, you specify a set of points and give it a fill.
Let's create a polygon that's about 200 pixels wide and 20 pixels tall, with a gradient fill.
In DetailPage.xaml, find the code for the exposure slider, then create a Polygon element just before it:
Set Grid.Row to "2" to put the polygon in the same row as the exposure slider.
Set the Points property to "0,20 200,20 200,0" to define the triangle shape.
Set the Stretch property to "Fill" and the HorizontalAlignment property to "Stretch".
Set the Height to "20" and the VerticalAlignment to "Center".
Give the Polygon a linear gradient fill.
On the exposure slider, set the Foreground property to "Transparent" so you can see the polygon.
Before

<Slider Header="Exposure"
Grid.Row="2"
Value="{x:Bind item.Exposure, Mode=TwoWay}"
Minimum="-2"
Maximum="2" />

After

<Polygon Grid.Row="2" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20">
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
<Slider Header="Exposure"
Grid.Row="2"
Foreground="Transparent"
Value="{x:Bind item.Exposure, Mode=TwoWay}"
Minimum="-2"
Maximum="2" />

Notes:
If you look at the surrounding XAML, you'll see that these elements are in a Grid. We put the polygon in
the same row as the exposure slider (Grid.Row="2") so they appear in the same spot. We put the polygon
before the slider so that the slider renders of top of the shape.
We set Stretch="Fill" and HorizontalAlignment="Stretch" on the polygon so that the triangle will adjust
to fill the available space. If the slider shrinks or grows in width, the polygon will shrink or grow to match.
4. Compile and run the app. Your slider should now look awesome:

5. Let's give the next slider, the temperature slider, an upgrade. The temperature slider changes the color
temperature of the image; sliding to the left makes the image bluer and sliding to the right makes the image
more yellow.
We'll use another polygon for this background shape with the same dimensions as the previous one, but
this time we'll make the fill a blue-yellow gradient instead of black and white.
Before

<TextBlock Grid.Row="2"
Grid.Column="1"
Margin="10,8,0,0" VerticalAlignment="Center" Padding="0"
Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

<Slider Header="Temperature"
Grid.Row="3" Background="Transparent" Foreground="Transparent"
Value="{x:Bind item.Temperature, Mode=TwoWay}"
Minimum="-1"
Maximum="1" />

After

<TextBlock Grid.Row="2"
Grid.Column="1"
Margin="10,8,0,0" VerticalAlignment="Center" Padding="0"
Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

<Polygon Grid.Row="3" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20">
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="Yellow" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
<Slider Header="Temperature"
Grid.Row="3" Background="Transparent" Foreground="Transparent"
Value="{x:Bind item.Temperature, Mode=TwoWay}"
Minimum="-1"
Maximum="1" />

6. Compile and run the app. You should now have two fancy sliders.

7. Extra credit
Add a background shape for the tint slider that has a gradient from green to red.
Congratulations, you've completed part 1! If you got stuck or want to see the final solution, you can find the
completed code at UWP Academy\XAML\Styling\Part1\Finish.

Part 2: Create basic styles


One of the advantages of XAML styles is that it can dramatically cut down the amount of code you have to write,
and it can make it much, much easier to update the look of your app.
To define a style, you add a Style element to the Resources property of an element that contains the control you
want to style. If you add your style to the Page.Resources property, your styles will be accessible to the entire
page. If you add your style to the Application.Resources property in your App.xaml file, the style will be
accessible to the entire app.
You can create named styles and general styles. A named style must be explicitly applied to specific controls; a
general style is applied to any control that matches the specified TargetType.
In this example, the first style has an x:Key attribute and its target type is Button. The first button's Style property
is set to this key, so this style is a named style and must be applied explicitly. The second style is applied
automatically to the second button because its target type is Button and the style doesn't have an x:Key attribute.

<Page.Resources>
<Style x:Key="PurpleStyle" TargetType="Button">
<Setter Property="FontFamily" Value="Lucida Sans Unicode"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="MediumOrchid"/>
</Style>

<Style TargetType="Button">
<Setter Property="Foreground" Value="Orange"/>
</Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
<Button Content="Button" Style="{StaticResource PurpleStyle}"/>
<Button Content="Button" />
</Grid>

Let's add a style to our app. In DetailsPage.xaml, take a look at the text blocks that sit next to our exposure,
temperature, and tint sliders. Each of these text blocks displays the value of a slider. Here's the text block for the
exposure slider. Notice that the Margin, VerticalAlignment, and Padding properties are set.

<TextBlock Grid.Row="2"
Grid.Column="1"
Margin="10,8,0,0" VerticalAlignment="Center" Padding="0"
Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

Look at the other text blocks--notice that those same properties are set to the same values. Sounds like a good
candidate for a style...
Create a value text block style
1. Open DetailsPage.xaml.
2. Find the Grid control named EditControlsGrid. It contains our sliders and text boxes. Notice that the grid
already defines a style for our sliders.
<Grid x:Name="EditControlsGrid"
HorizontalAlignment="Stretch"
Margin="24,48,24,24">
<Grid.Resources>
<Style TargetType="Slider">
<Setter Property="Margin"
Value="0,0,0,0" />
<Setter Property="Padding"
Value="0" />
<Setter Property="MinWidth"
Value="100" />
<Setter Property="StepFrequency"
Value="0.1" />
<Setter Property="TickFrequency"
Value="0.1" />
</Style>
</Grid.Resources>

3. Create a style for a TextBlock that sets its Margin to "10,8,0,0", its VerticalAlignment to "Center", and its
Padding to "0".
Before

<Grid.Resources>
<Style TargetType="Slider">
<Setter Property="Margin"
Value="0,0,0,0" />
<Setter Property="Padding"
Value="0" />
<Setter Property="MinWidth"
Value="100" />
<Setter Property="StepFrequency"
Value="0.1" />
<Setter Property="TickFrequency"
Value="0.1" />
</Style>
</Grid.Resources>

After

<Grid.Resources>
<Style TargetType="Slider">
<Setter Property="Margin"
Value="0,0,0,0" />
<Setter Property="Padding"
Value="0" />
<Setter Property="MinWidth"
Value="100" />
<Setter Property="StepFrequency"
Value="0.1" />
<Setter Property="TickFrequency"
Value="0.1" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Margin"
Value="10,8,0,0" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Padding"
Value="0" />
</Style>
</Grid.Resources>
4. Let's make this a named style so we can specify which TextBlock controls it applies to. Set the style's x:Key
property to "ValueTextBox".
Before

<Style TargetType="TextBlock">
<Setter Property="Margin"
Value="10,8,0,0" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Padding"
Value="0" />
</Style>

After

<Style TargetType="TextBlock"
x:Key="ValueTextBox">
<Setter Property="Margin"
Value="10,8,0,0" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Padding"
Value="0" />
</Style>

5. For each TextBlock, remove its Margin, VerticalAlignment, and Padding properties, and set its Style
property to "{StaticResource ValueTextBox}".
Before

<TextBlock Grid.Row="2"
Grid.Column="1"
Margin="10,8,0,0" VerticalAlignment="Center" Padding="0"
Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

After

<TextBlock Grid.Row="2"
Grid.Column="1"
Style="{StaticResource ValueTextBox}"
Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

Make this change to all 6 TextBlock controls associated with the sliders.
6. Compile and run the app. It should look... the same. But you should feel that wonderful sense of satisfaction
and accomplishment that comes from writing efficient, maintainable code.
Congratulations, you've completed Part 2!

Part 3: Use a control template to make a fancy slider


Remember, how in Part 1 we added a shape behind the slider to make it look cool?
Well, we got the job done, but there's a better way to achieve the same effect: create a control template.
1. In the Solution Explorer panel, double-click DetailPage.xaml.
2. Next, we'll use the default control template for slider as our starting point. Add this XAML to the
Page.Resources element. (The Page.Resources element is toward the beginning of the page.)

<ControlTemplate x:Key="FancySliderControlTemplate" TargetType="Slider">


<Grid Margin="{TemplateBinding Padding}">
<Grid.Resources>
<Style TargetType="Thumb" x:Key="SliderThumbStyle">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="{ThemeResource SliderThumbBackground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalThumb" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillDisabled}" />
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalThumb" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="TopTickBar" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTickBarFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BottomTickBar" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTickBarFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LeftTickBar" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTickBarFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RightTickBar" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTickBarFillDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalTrackRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackFillPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalThumb" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderThumbBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderContainerBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalDecreaseRect" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SliderTrackValueFillPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusEngagementStates">
<VisualState x:Name="FocusDisengaged" />
<VisualState x:Name="FocusEngagedHorizontal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="
(Control.IsTemplateFocusTarget)">
<DiscreteObjectKeyFrame KeyTime="0" Value="False" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalThumb" Storyboard.TargetProperty="
(Control.IsTemplateFocusTarget)">
<DiscreteObjectKeyFrame KeyTime="0" Value="True" />
</ObjectAnimationUsingKeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="FocusEngagedVertical">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SliderContainer" Storyboard.TargetProperty="
(Control.IsTemplateFocusTarget)">
<DiscreteObjectKeyFrame KeyTime="0" Value="False" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalThumb" Storyboard.TargetProperty="
(Control.IsTemplateFocusTarget)">
<DiscreteObjectKeyFrame KeyTime="0" Value="True" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Visibility="Collapsed"
Foreground="{ThemeResource SliderHeaderForeground}"
Margin="{ThemeResource SliderHeaderThemeMargin}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="{ThemeResource SliderHeaderThemeFontWeight}"
TextWrapping="Wrap" />
<Grid x:Name="SliderContainer"
Background="{ThemeResource SliderContainerBackground}"
Grid.Row="1"
Control.IsTemplateFocusTarget="True">
<Grid x:Name="HorizontalTemplate" MinHeight="44">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="Auto" />
<RowDefinition Height="18" />
</Grid.RowDefinitions>
<Rectangle x:Name="HorizontalTrackRect"
Fill="{TemplateBinding Background}"
Height="{ThemeResource SliderTrackThemeHeight}"
Grid.Row="1"
Grid.ColumnSpan="3" />
<Rectangle x:Name="HorizontalDecreaseRect" Fill="{TemplateBinding Foreground}" Grid.Row="1" />
<TickBar x:Name="TopTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderTickBarFill}"
Height="{ThemeResource SliderOutsideTickBarThemeHeight}"
VerticalAlignment="Bottom"
Margin="0,0,0,4"
Grid.ColumnSpan="3" />
<TickBar x:Name="HorizontalInlineTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderInlineTickBarFill}"
Height="{ThemeResource SliderTrackThemeHeight}"
Grid.Row="1"
Grid.ColumnSpan="3" />
<TickBar x:Name="BottomTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderTickBarFill}"
Height="{ThemeResource SliderOutsideTickBarThemeHeight}"
VerticalAlignment="Top"
Margin="0,4,0,0"
Grid.Row="2"
Grid.ColumnSpan="3" />
<Thumb x:Name="HorizontalThumb"
Style="{StaticResource SliderThumbStyle}"
Style="{StaticResource SliderThumbStyle}"
DataContext="{TemplateBinding Value}"
Height="24"
Width="8"
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="1"
FocusVisualMargin="-14,-6,-14,-6"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
<Grid x:Name="VerticalTemplate" MinWidth="44" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="18" />
</Grid.ColumnDefinitions>
<Rectangle x:Name="VerticalTrackRect"
Fill="{TemplateBinding Background}"
Width="{ThemeResource SliderTrackThemeHeight}"
Grid.Column="1"
Grid.RowSpan="3" />
<Rectangle x:Name="VerticalDecreaseRect"
Fill="{TemplateBinding Foreground}"
Grid.Column="1"
Grid.Row="2" />
<TickBar x:Name="LeftTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderTickBarFill}"
Width="{ThemeResource SliderOutsideTickBarThemeHeight}"
HorizontalAlignment="Right"
Margin="0,0,4,0"
Grid.RowSpan="3" />
<TickBar x:Name="VerticalInlineTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderInlineTickBarFill}"
Width="{ThemeResource SliderTrackThemeHeight}"
Grid.Column="1"
Grid.RowSpan="3" />
<TickBar x:Name="RightTickBar"
Visibility="Collapsed"
Fill="{ThemeResource SliderTickBarFill}"
Width="{ThemeResource SliderOutsideTickBarThemeHeight}"
HorizontalAlignment="Left"
Margin="4,0,0,0"
Grid.Column="2"
Grid.RowSpan="3" />
<Thumb x:Name="VerticalThumb"
Style="{StaticResource SliderThumbStyle}"
DataContext="{TemplateBinding Value}"
Width="24"
Height="8"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
FocusVisualMargin="-6,-14,-6,-14"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</Grid>
</Grid>
</ControlTemplate>

Wow, that's a lot of XAML! Control templates are a powerful feature, but they can be quite complex, which is
why it's usually a good idea to start from the default template.
3. Within the ControlTemplate you just added, find the grid control named HorizontalTemplate. This grid
defines the portion of the template that we want to change.

<Grid x:Name="HorizontalTemplate" MinHeight="44">


<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="Auto" />
<RowDefinition Height="18" />
</Grid.RowDefinitions>

4. Create a polygon that's just like the polygon you created for the exposure slider in Part 1. Add the polygon
after the closing Grid.RowDefinitions tag. Set Grid.Row to "0", Grid.RowSpan to "3", and
Grid.ColumnSpan to "3".
Before

<Grid x:Name="HorizontalTemplate" MinHeight="44">


<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="Auto" />
<RowDefinition Height="18" />
</Grid.RowDefinitions>

After

<Grid x:Name="HorizontalTemplate" MinHeight="44">


<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="Auto" />
<RowDefinition Height="18" />
</Grid.RowDefinitions>
<Polygon Grid.Row="0" Grid.RowSpan="3" Grid.ColumnSpan="3" Stretch="Fill"
Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20" >
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>

5. Remove the Polygon.Fill setting. Set Fill to "{TemplateBinding Background}". This makes it so that setting
the Background property of the slider sets the Fill property of the polygon.
Before

<Polygon Grid.Row="0" Grid.RowSpan="3" Grid.ColumnSpan="3" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20" >
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>

After

<Polygon Grid.Row="0" Grid.RowSpan="3" Grid.ColumnSpan="3" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20"
Fill="{TemplateBinding Background}">
</Polygon>

6. Just after the polygon you added, there's a rectangle named HorizontalTrackRect. Remove the Rectangle's
Fill setting so that the rectangle won't be visible and won't block our polygon shape. (We don't want to
completely remove the rectangle because the control template also uses it for interaction visuals, such as
hover.)
Before

<Rectangle x:Name="HorizontalTrackRect"
Fill="{TemplateBinding Background}"
Height="{ThemeResource SliderTrackThemeHeight}"
Grid.Row="1"
Grid.ColumnSpan="3" />

After

<Rectangle x:Name="HorizontalTrackRect"
Height="{ThemeResource SliderTrackThemeHeight}"
Grid.Row="1"
Grid.ColumnSpan="3" />

You're done with the template! Now we need to apply it to our sliders.
7. Let's update our exposure slider.
Set the slider's Template property to "{StaticResource FancySliderControlTemplate}".
Remove the slider's Background="Transparent" setting.
Set the slider's Background to a linear gradient that transitions from black to white.
Remove the background polygon we created in Part 1.
Before
<Polygon Grid.Row="2" Stretch="Fill"
Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20">
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
<Slider Header="Exposure"
Grid.Row="2" Background="Transparent" Foreground="Transparent"
Value="{x:Bind item.Exposure, Mode=TwoWay}"
Minimum="-2"
Maximum="2"
Template="{StaticResource FancySliderControlTemplate}"/>

After

<Slider Header="Exposure"
Grid.Row="2" Foreground="Transparent"
Value="{x:Bind item.Exposure, Mode=TwoWay}"
Minimum="-2"
Maximum="2"
Template="{StaticResource FancySliderControlTemplate}">
<Slider.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Black" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Slider.Background>
</Slider>

8. Make the same updates to the temperature slider.


Before

<Polygon Grid.Row="3" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20">
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="Yellow" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
<Slider Header="Temperature"
Grid.Row="3" Background="Transparent" Foreground="Transparent"
Value="{x:Bind item.Temperature, Mode=TwoWay}"
Minimum="-1"
Maximum="1" />

After
<Slider Header="Temperature"
Grid.Row="3" Foreground="Transparent"
Value="{x:Bind item.Temperature, Mode=TwoWay}"
Minimum="-1"
Maximum="1"
Template="{StaticResource FancySliderControlTemplate}">
<Slider.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="Yellow" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Slider.Background>
</Slider>

9. Make the same updates to the tint slider.


Before

<Polygon Grid.Row="4" Stretch="Fill"


Points="0,20 200,20 200,0" HorizontalAlignment="Stretch"
VerticalAlignment="Center" Height="20">
<Polygon.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="1" Color="Green" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Polygon.Fill>
</Polygon>
<Slider Header="Tint"
Grid.Row="4" Background="Transparent" Foreground="Transparent"
Value="{x:Bind item.Tint, Mode=TwoWay}"
Minimum="-1"
Maximum="1" />

After

<Slider Header="Tint"
Grid.Row="4" Foreground="Transparent"
Value="{x:Bind item.Tint, Mode=TwoWay}"
Minimum="-1"
Maximum="1"
Template="{StaticResource FancySliderControlTemplate}">
<Slider.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="Red" />
<GradientStop Offset="1" Color="Green" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Slider.Background>
</Slider>

10. Compile and run the app.


As you can see, our updates improved the positioning of the polygon; now the bottom of the polygon is
aligned to the bottom of the slider thumb.
Congratulations, you've finished the tutorial! If you got stuck and want to see the final solution, you can find the
complete sample in the UWP app sample repository.
Create data bindings
9/1/2017 20 min to read Edit Online

Suppose you've designed and implemented a nice looking UI filled with placeholder images, "lorem ipsum"
boilerplate text, and controls that don't do anything yet. Next, you'll want to connect it to real data and transform it
from a design prototype into a living app.
In this tutorial, you'll learn how to replace your boilerplate with data bindings and create other direct links between
your UI and your data. You'll also learn how to format or convert your data for display, and keep your UI and data
in sync. When you complete this tutorial, you'll be able to improve the simplicity and organization of the XAML and
C# code, making it easier to maintain and extend.
You'll start with a simplified version of the PhotoLab sample. This starter version includes the complete data layer
plus the basic XAML page layouts, and leaves out many features to make the code easier to browse around in. This
tutorial doesn't build up to the complete app, so be sure to check out the final version to see features such as
custom animations and phone support. You can find the final version in the UWP Academy\XAML\Final** folder.

Prerequisites
Visual Studio 2017 and the Windows 10 SDK (10.0.15063.468 or later)

Part 0: Get the code


The starting point for this lab is located in the PhotoLab sample repository, in the xaml-basics-tutorials/data-
binding/ folder. After you've cloned/downloaded the repo, you can edit the project by openning PhotoLab.sln with
Visual Studio 2017.

Part 1: Replace the placeholders


Here you'll create one-time bindings in data-template XAML to display real images and image metadata instead of
placeholder content.
One-time bindings are for read-only, unchanging data, which means they are high performance and easy to create,
letting you display large data sets in GridView and ListView controls.
Replace the placeholders with one-time bindings
1. Open the UWP Academy\XAML\Binding\Start folder and load the PhotoLab solution.
2. Make sure your Solution Platform is set to x86 or x64, not ARM, and then run the app. This shows the state
of the app with UI placeholders, before bindings have been added.
3. Open MainPage.xaml and search for a DataTemplate named ImageGridView_DefaultItemTemplate.
You'll update this template to use data bindings.
Before:

<DataTemplate x:Key="ImageGridView_DefaultItemTemplate">

The x:Key value is used by the ImageGridView to select this template for displaying data objects.
4. Add an x:DataType value to the template.
After:

<DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
x:DataType="local:ImageFileInfo">

x:DataType indicates which type this is a template for. In this case, it's a template for the ImageFileInfo
class (where "local:" indicates the local namespace, as defined in an xmlns declaration near the top of the
file).
x:DataType is required when using x:Bind expressions in a data template, as described next.
5. In the DataTemplate, find the Image element named ItemImage and replace its Source value as shown.
Before:

<Image x:Name="ItemImage"
Source="/Assets/StoreLogo.png"
Stretch="Uniform" />

After:
<Image x:Name="ItemImage"
Source="{x:Bind ImageSource}"
Stretch="Uniform" />

x:Name identifies a XAML element so you can refer to it elsewhere in the XAML and in the code-behind.
x:Bind expressions supply a value to a UI property by getting the value from a data-object property. In
templates, the property indicated is a property of whatever the x:DataType has been set to. So in this case,
the data source is the ImageFileInfo.ImageSource property.

NOTE
The x:Bind value also lets the editor know about the data type, so you can use IntelliSense instead of typing in the
property name in an x:Bind expression. Try it on the code you just pasted in: place the cursor just after x:Bind and
press the Spacebar to see a list of properties you can bind to.

6. Replace the values of the other UI controls in the same way. (Try doing this with IntelliSense instead of
copy/pasting!)
Before:

<TextBlock Text="Placeholder" ... />


<StackPanel ... >
<TextBlock Text="PNG file" ... />
<TextBlock Text="50 x 50" ... />
</StackPanel>
<telerikInput:RadRating Value="3" ... />

After:

<TextBlock Text="{x:Bind ImageTitle}" ... />


<StackPanel ... >
<TextBlock Text="{x:Bind ImageFileType}" ... />
<TextBlock Text="{x:Bind ImageDimensions}" ... />
</StackPanel>
<telerikInput:RadRating Value="{x:Bind ImageRating}" ... />

Run the app to see how it looks so far. No more placeholders! We're off to a good start.
NOTE
If you want to experiment further, try adding a new TextBlock to the data template, and use the x:Bind IntelliSense trick to
find a property to display.

Part 2: Use binding to connect the gallery UI to the images


Here, you'll create one-time bindings in page XAML to connect the gallery view to the image collection, replacing
the existing procedural code that does this in code-behind. You'll also create a Delete button to see how the
gallery view changes when images are removed from the collection. At the same time, you'll learn how to bind
events to event handlers for more flexibility than that provided by traditional event handlers.
All the bindings covered so far are inside data templates and refer to properties of the class indicated by the
x:DataType value. What about the rest of the XAML in your page?
x:Bind expressions outside of data templates are always bound to the page itself. This means you can reference
anything you put in code-behind or declare in XAML, including custom properties and properties of other UI
controls on the page (as long as they have an x:Name value).
In the PhotoLab sample, one use for a binding like this is to connect the main GridView control directly to the
collection of images, instead of doing it in code-behind. Later, you'll see other examples.
Bind the main GridView control to the Images collection
1. In MainPage.xaml.cs, find the OnNavigatedTo method and remove the code that sets ItemsSource.
Before:

ImageGridView.ItemsSource = Images;

After:
// Replaced with XAML binding:
// ImageGridView.ItemsSource = Images;

2. In MainPage.xaml, find the GridView named ImageGridView and add an ItemsSource attribute. For the
value, use an x:Bind expression that refers to the Images property implemented in code-behind.
Before:

<GridView x:Name="ImageGridView"

After:

<GridView x:Name="ImageGridView"
ItemsSource="{x:Bind Images}"

The Images property is of type ObservableCollection<ImageFileInfo>, so the individual items displayed


in the GridView are of type ImageFileInfo. This matches the x:DataType value described in Part 1.
All the bindings we've looked at so far are one-time, read-only bindings, which is the default behavior for plain
x:Bind expressions. The data is loaded only at initialization, which makes for high-performance bindings - perfect
for supporting multiple, complex views of large data sets.
Even the ItemsSource binding you just added is a one-time, read-only binding to an unchanging property value,
but there's an important distinction to make here. The unchanging value of the Images property is a single,
specific instance of a collection, initialized once as shown here.

private ObservableCollection<ImageFileInfo> Images { get; } = new ObservableCollection<ImageFileInfo>();

The Images property value never changes, but because the property is of type ObservableCollection<T>, the
contents of the collection can change, and the binding will automatically notice the changes and update the UI.
To test this, we're going to temporarily add a button that deletes the currently-selected image. This button isn't in
the final version because selecting an image will take you to a detail page. However, the behavior of
ObservableCollection<T> is still important in the final PhotoLab sample because the XAML is initialized in the
page constructor (through the InitializeComponent method call), but the Images collection is populated later in
the OnNavigatedTo method.
To add a delete button:
1. In MainPage.xaml, find the CommandBar named MainCommandBar and add a new button before the
zoom button. (The zoom controls don't work yet. You'll hook those up in the next part of the tutorial.)

<AppBarButton Icon="Delete"
Label="Delete selected image"
Click="{x:Bind DeleteSelectedImage}" />

If you're already familiar with XAML, this Click value might look unusual. In previous versions of XAML, you
had to set this to a method with a specific event-handler signature, typically including parameters for the
event sender and an event-specific arguments object. You can still use this technique when you need the
event arguments, but with x:Bind, you can connect to other methods, too. For example, if you don't need the
event data, you can connect to methods that have no parameters, like we do here.
2. In MainPage.xaml.cs, add the DeleteSelectedImage method.
private void DeleteSelectedImage() => Images.Remove(ImageGridView.SelectedItem as ImageFileInfo);

This method simply deletes the selected image from the Images collection.
Now run the app and use the button to delete a few images. As you can see, the UI is updated automatically,
thanks to data binding and the ObservableCollection<T> type.

NOTE
For a challenge, try adding two buttons that move the selected image up or down in the list, then x:Bind their Click events to
two new methods similar to DeleteSelectedImage.

Part 3: Set up the zoom slider


In this part, you'll create one-way bindings from a control in the data template to the zoom slider, which is outside
the template. You'll also learn that you can use data binding with many control properties, not just the most
obvious ones like TextBlock.Text and Image.Source.
Bind the image data template to the zoom slider*
Find the DataTemplate named ImageGridView_DefaultItemTemplate and replace the Height and
Width values of the Grid control at the top of the template.
Before

<DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
x:DataType="local:ImageFileInfo">
<Grid Height="200"
Width="200"
Margin="{StaticResource LargeItemMargin}">

After

<DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
x:DataType="local:ImageFileInfo">
<Grid Height="{Binding Value, ElementName=ZoomSlider}"
Width="{Binding Value, ElementName=ZoomSlider}"
Margin="{StaticResource LargeItemMargin}">

Did you notice that these are Binding expressions, and not x:Bind expressions? This is the old way of doing
data bindings, and it's mostly obsolete. x:Bind does nearly everything that Binding does, and more.
However, when you use x:Bind in a data template, it binds to the type declared in the x:DataType value. So
how do you bind something in the template to something in the page XAML or in code-behind? You must
use an old-style Binding expression.
Binding expressions don't recognize the x:DataType value, but these Binding expressions have
ElementName values that work almost the same way. These tell the binding engine that Binding Value is
a binding to the Value property of the specified element on the page (that is, the element with that x:Name
value). If you want to bind to a property in code-behind, it would look something like
{Binding MyCodeBehindProperty, ElementName=page} where page refers to the x:Name value set in the Page
element in XAML.
NOTE
By default, Binding expressions are one-way, meaning that they will automatically update the UI when the bound
property value changes.
In contrast, the default for x:Bind is one-time, meaning that any changes to the bound property are ignored. This is
the default because it's the most high-performance option, and most bindings are to static, read-only data.
The lesson here is that if you use x:Bind with properties that can change their values, be sure to add Mode=OneWay
or Mode=TwoWay . You'll see examples of this in the next section.

Run the app and use the slider to change the image-template dimensions. As you can see, the effect is pretty
powerful without needing much code.

NOTE
For a challenge, try binding other UI properties to the zoom slider Value property, or to other sliders that you add after the
zoom slider. For example, you could bind the FontSize property of the TitleTextBlock to a new slider with a default value of
24. Be sure to set reasonable minimum and maximum values.

Part 4: Improve the zoom experience


In this part, you'll add a custom ItemSize property to code-behind and create one-way bindings from the image
template to the new property. The ItemSize value will be updated by the zoom slider and other factors such as the
Fit to screen toggle and the window size, making for a more refined experience.
Unlike built-in control properties, your custom properties do not automatically update the UI, even with one-way
and two-way bindings. They work fine with one-time bindings, but if you want your property changes to actually
show up in your UI, you need to do some work.
Create the ItemSize property so that it updates the UI
1. In MainPage.xaml.cs, change the signature of the MainPage class so that it implements the
INotifyPropertyChanged interface.
Before:

public sealed partial class MainPage : Page

After:

public sealed partial class MainPage : Page, INotifyPropertyChanged

This informs the binding system that MainPage has a PropertyChanged event (added next) that bindings
can listen for in order to update the UI.
2. Add a PropertyChanged event to the MainPage class.

public event PropertyChangedEventHandler PropertyChanged;

This event provides the complete implementation required by the INotifyPropertyChanged interface.
However, for it to have any effect, you must explicitly raise the event in your custom properties.
3. Add an ItemSize property and raise the PropertyChanged event in its setter.

public double ItemSize


{
get => _itemSize;
set
{
if (_itemSize != value)
{
_itemSize = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ItemSize)));
}
}
}
private double _itemSize;

The ItemSize property exposes the value of a private _itemSize field. Using a backing field like this enables
the property to check whether a new value is the same as the old value before it raises a potentially
unnecessary PropertyChanged event.
The event itself is raised by the Invoke method. The question mark checks whether the PropertyChanged
event is null - that is, whether any event handlers have been added yet. Every one-way or two-way binding
adds an event handler behind the scenes, but if no one is listening, nothing more would happen here. If
PropertyChanged isn't null, however, then Invoke is called with a reference to the event source (the page
itself, represented by the this keyword) and an event-args object that indicates the name of the property.
With this info, any one-way or two-way bindings to the ItemSize property will be informed of any changes
so they can update the bound UI.
4. In MainPage.xaml, find the DataTemplate named ImageGridView_DefaultItemTemplate and replace
the Height and Width values of the Grid control at the top of the template. (If you did the control-to-
control binding in the previous part of this tutorial, the only changes are to replace Value with ItemSize
and ZoomSlider with page. Be sure to do this for both Height and Width!)
Before
<DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
x:DataType="local:ImageFileInfo">
<Grid Height="{Binding Value, ElementName=ZoomSlider}"
Width="{Binding Value, ElementName=ZoomSlider}"
Margin="{StaticResource LargeItemMargin}">

After

<DataTemplate x:Key="ImageGridView_DefaultItemTemplate"
x:DataType="local:ImageFileInfo">
<Grid Height="{Binding ItemSize, ElementName=page}"
Width="{Binding ItemSize, ElementName=page}"
Margin="{StaticResource LargeItemMargin}">

Now that the UI can respond to ItemSize changes, you need to actually make some changes. As mentioned
previously, the ItemSize value is calculated from the current state of various UI controls, but the calculation must
be performed whenever those controls change state. To do this, you'll use event binding so that certain UI changes
will call a helper method that updates ItemSize.
Update the ItemSize property value
1. Add the DetermineItemSize method to MainPage.xaml.cs.

private void DetermineItemSize()


{
if (FitScreenToggle != null
&& FitScreenToggle.IsOn == true
&& ImageGridView != null
&& ZoomSlider != null)
{
// The 'margins' value represents the total of the margins around the
// image in the grid item. 8 from the ItemTemplate root grid + 8 from
// the ItemContainerStyle * (Right + Left). If those values change,
// this value needs to be updated to match.
int margins = (int)this.Resources["LargeItemMarginValue"] * 4;
double gridWidth = ImageGridView.ActualWidth - (int)this.Resources["DesktopWindowSidePaddingValue"];

if (AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile" &&


UIViewSettings.GetForCurrentView().UserInteractionMode == UserInteractionMode.Touch)
{
margins = (int)this.Resources["SmallItemMarginValue"] * 4;
gridWidth = ImageGridView.ActualWidth - (int)this.Resources["MobileWindowSidePaddingValue"];
}

double ItemWidth = ZoomSlider.Value + margins;


// We need at least 1 column.
int columns = (int)Math.Max(gridWidth / ItemWidth, 1);

// Adjust the available grid width to account for margins around each item.
double adjustedGridWidth = gridWidth - (columns * margins);

ItemSize = (adjustedGridWidth / columns);


}
else
{
ItemSize = ZoomSlider.Value;
}
}

2. In MainPage.xaml, navigate to the top of the file and add a SizeChanged event binding to the Page
element.
Before:

<Page x:Name="page"

After:

<Page x:Name="page"
SizeChanged="{x:Bind DetermineItemSize}"

3. Find the Slider named ZoomSlider and add a ValueChanged event binding.
Before:

<Slider x:Name="ZoomSlider"

After:

<Slider x:Name="ZoomSlider"
ValueChanged="{x:Bind DetermineItemSize}"

4. Find the ToggleSwitch named FitScreenToggle and add a Toggled event binding.
Before:

<ToggleSwitch x:Name="FitScreenToggle"

After:

<ToggleSwitch x:Name="FitScreenToggle"
Toggled="{x:Bind DetermineItemSize}"

Run the app and use the zoom slider and Fit to screen toggle to change the image-template dimensions. As you
can see, the latest changes enable a more refined zoom/resize experience while keeping the code well organized.
NOTE
For a challenge, try adding a TextBlock after the ZoomSlider and binding the Text property to the ItemSize property.
Because it's not in a data template, you can use x:Bind instead of Binding like in the previous ItemSize bindings.
}

Part 5: Enable user edits


Here, you'll create two-way bindings to enable users to update values, including the image title, rating, and various
visual effects.
To achieve this, you'll update the existing DetailPage, which provides a single-image viewer, zoom control, and
editing UI.
First, however, you need to attach the DetailPage so that the app navigates to it when the user clicks an image in
the gallery view.
Attach the DetailPage
1. In MainPage.xaml, find the GridView named ImageGridView and add an ItemClick value.

TIP
If you type in the change below instead of copy/pasting, you'll see an IntelliSense pop-up that says "<New Event
Handler>". If you press the Tab key, it will fill in the value with a default method handler name, and automatically
stub out the method shown in the next step. You can then press F12 to navigate to the method in the code-behind.

Before:

<GridView x:Name="ImageGridView"
After:

<GridView x:Name="ImageGridView"
ItemClick="ImageGridView_ItemClick"

NOTE
We're using a conventional event handler here instead of an x:Bind expression. This is because we need to see the
event data, as shown next.

2. In MainPage.xaml.cs, add the event handler (or fill it in, if you used the tip in the last step).

private void ImageGridView_ItemClick(object sender, ItemClickEventArgs e)


{
this.Frame.Navigate(typeof(DetailPage), e.ClickedItem);
}

This method simply navigates to the detail page, passing in the clicked item, which is an ImageFileInfo
object used by DetailPage.OnNavigatedTo for initializing the page. You won't have to implement that
method in this tutorial, but you can take a look to see what it does.
3. (Optional) Delete or comment out any controls you added in previous play-points that work with the
currently selected image. Keeping them around won't hurt anything, but it's now a lot harder to select an
image without navigating to the detail page.
Now that you've connected the two pages, run the app and take a look around. Everything works except the
controls on the editing pane, which don't respond when you try to change the values.
As you can see, the title text box does display the title and lets you type in changes. You have to change focus to
another control to commit the changes, but the title in the upper-left corner of the screen doesn't update yet.
All the controls are already bound using the plain x:Bind expressions we covered in Part 1. If you recall, this means
they are all one-time bindings, which explains why changes to the values aren't registered. To fix this, all we have
to do is turn them into two-way bindings.
Make the editing controls interactive
1. In DetailPage.xaml, find the TextBlock named TitleTextBlock and the RadRating control after it, and
update their x:Bind expressions to include Mode=TwoWay.
Before:

<TextBlock x:Name="TitleTextBlock"
Text="{x:Bind item.ImageTitle}"
... >
<telerikInput:RadRating Value="{x:Bind item.ImageRating}"
... >

After:

<TextBlock x:Name="TitleTextBlock"
Text="{x:Bind item.ImageTitle, Mode=TwoWay}"
... >
<telerikInput:RadRating Value="{x:Bind item.ImageRating, Mode=TwoWay}"
... >
2. Do the same thing for all the effect sliders that come after the rating control.

<Slider Header="Exposure" ... Value="{x:Bind item.Exposure, Mode=TwoWay}" ...


<Slider Header="Temperature" ... Value="{x:Bind item.Temperature, Mode=TwoWay}" ...
<Slider Header="Tint" ... Value="{x:Bind item.Tint, Mode=TwoWay}" ...
<Slider Header="Contrast" ... Value="{x:Bind item.Contrast, Mode=TwoWay}" ...
<Slider Header="Saturation" ... Value="{x:Bind item.Saturation, Mode=TwoWay}" ...
<Slider Header="Blur" ... Value="{x:Bind item.Blur, Mode=TwoWay}" ...

The two-way mode, as you might expect, means that the data moves in both directions whenever there are
changes on either side.
Like the one-way bindings covered earlier, these two-way bindings will now update the UI whenever the bound
properties change, thanks to the INotifyPropertyChanged implementation in the ImageFileInfo class. With
two-way binding, however, the values will also move from the UI to the bound properties whenever the user
interacts with the control. Nothing more is needed on the XAML side.
Run the app and try the editing controls. As you can see, when you make a change, it now affects the image values,
and those changes persist when you navigate back to the main page.

Part 6: Format values through function binding


One last problem remains. When you move the effect sliders, the labels next to them still don't change.

The final part in this tutorial is to add bindings that format the slider values for display.
Bind the effect-slider labels and format the values for display
1. Find the TextBlock after the Exposure slider and replace the Text value with the binding expression
shown here.
Before:

<Slider Header="Exposure" ... />


<TextBlock ... Text="0.00" />

After:

<Slider Header="Exposure" ... />


<TextBlock ... Text="{x:Bind item.Exposure.ToString('N', culture), Mode=OneWay}" />

This is called a function binding because you are binding to the return value of a method. The method must
be accessible through the page's code-behind or the x:DataType type if you are in a data template. In this
case, the method is the familiar .NET ToString method, which is accessed through the item property of the
page, and then through the Exposure property of the item. (This illustrates how you can bind to methods
and properties that are deeply nested in a chain of connections.)
Function binding is an ideal way to format values for display because you can pass in other binding sources
as method arguments, and the binding expression will listen for changes to those values as expected with
the one-way mode. In this example, the culture argument is a reference to an unchanging field
implemented in code-behind, but it could just as easily have been a property that raises PropertyChanged
events. In that case, any changes to the property value would cause the x:Bind expression to call ToString
with the new value and then update the UI with the result.
2. Do the same thing for the TextBlocks that label the other effect sliders.

<Slider Header="Temperature" ... />


<TextBlock ... Text="{x:Bind item.Temperature.ToString('N', culture), Mode=OneWay}" />

<Slider Header="Tint" ... />


<TextBlock ... Text="{x:Bind item.Tint.ToString('N', culture), Mode=OneWay}" />

<Slider Header="Contrast" ... />


<TextBlock ... Text="{x:Bind item.Contrast.ToString('N', culture), Mode=OneWay}" />

<Slider Header="Saturation" ... />


<TextBlock ... Text="{x:Bind item.Saturation.ToString('N', culture), Mode=OneWay}" />

<Slider Header="Blur" ... />


<TextBlock ... Text="{x:Bind item.Blur.ToString('N', culture), Mode=OneWay}" />

Now when you run the app, everything works, including the slider labels.

NOTE
Try using function binding with the TextBlock from the last play-point and bind it to a new method that returns a string in
"000 x 000" format when you pass it the ItemSize value.

Conclusion
This tutorial has given you a taste of data binding and shown you some of the functionality available. One word of
caution before we wrap up: not everything is bindable, and sometimes the values you try to connect to are
incompatible with the properties you are trying to bind. There is a lot of flexibility in binding, but it won't work in
every situation.
One example of a problem not addressed by binding is when a control has no suitable properties to bind to, as
with the detail page zoom feature. This zoom slider needs to interact with the ScrollViewer that displays the
image, but ScrollViewer can only be updated through its ChangeView method. In this case, we use conventional
event handlers to keep the ScrollViewer and the zoom slider in sync; see the DetailPage
ZoomSlider_ValueChanged and MainImageScroll_ViewChanged methods for details.
Nonetheless, binding is a powerful and flexible way to simplify your code and keep your UI logic separate from
your data logic. This will make it much easier for you adjust either side of this divide while reducing the risk of
introducing bugs on the other side.
One example of UI and data separation is with the ImageFileInfo.ImageTitle property. This property (and the
ImageRating property) is slightly different than the ItemSize property you created in Part 4 because the value is
stored in the file metadata (exposed through the ImageProperties type) instead of in a field. Additionally,
ImageTitle returns the ImageName value (set to the file name) if there is no title in the file metadata.

public string ImageTitle


{
get => String.IsNullOrEmpty(ImageProperties.Title) ? ImageName : ImageProperties.Title;
set
{
if (ImageProperties.Title != value)
{
ImageProperties.Title = value;
var ignoreResult = ImageProperties.SavePropertiesAsync();
OnPropertyChanged();
}
}
}

As you can see, the setter updates the ImageProperties.Title property and then calls SavePropertiesAsync to
write the new value to the file. (This is an async method, but we can't use the await keyword in a property - and
you wouldn't want to because property getters and setters should complete immediately. So instead, you would
call the method and ingore the Task object it returns.)

Going further
Now that you've completed this lab, you have enough binding knowledge tackle a problem on your own.
As you might have noticed, if you change the zoom level on the details page, it resets automatically when you
navigate backward then select the same image again. Can you figure out how to preserve and restore the zoom
level for each image individually? Good luck!
You should have all the info you need in this tutorial, but if you need more guidance, the data binding docs are
only a click away. Start here:
{x:Bind} markup extension
Data binding in depth
Create adaptive layouts
9/1/2017 7 min to read Edit Online

This tutorial covers the basics of using XAML's adaptive and tailored layout features, which let you create apps that
look at home on any device. You'll learn how to create a new DataTemplate, add window snap points, and tailor
your app's layout using the VisualStateManager and AdaptiveTrigger elements.
We'll use these tools to optimize the PhotoLab sample app for smaller device screens. This starter version of the
PhotoLab sample includes the complete data layer plus a partially complete XAML layout, but leaves out many
minor features to make the code easier to browse. This lab doesn't build up to the complete app, so be sure to
check out the final version to see features such as custom animations.

Prerequisites
Visual Studio 2017 and the Windows 10 SDK (10.0.15063.468 or later)
Windows 10 mobile emulator

Part 0: Get the code


The starting point for this lab is located in the PhotoLab sample repository, in the xaml-basics-tutorials/adaptive-
layout/ folder. After you've cloned/downloaded the repo, you can edit the project by openning PhotoLab.sln with
Visual Studio 2017.

Part 1: Run the mobile emulator


In the Visual Studio toolbar, make sure your Solution Platform is set to x86 or x64, not ARM, and then change your
target device from Local Machine to one of the mobile emulators that you've installed (for example, Mobile
Emulator 10.0.15063 WVGA 5 inch 1GB). Try running the Photo Gallery app in the mobile emulator you've
selected by pressing F5.
As soon as the app starts, you'll probably notice that while the app works, it doesn't look great on such a small
viewport. The fluid Grid element tries to accommodate for the limited screen real estate by reducing the number of
columns displayed, but we are left with a layout that looks uninspired and ill-fitted to such a small viewport.
Part 2: Build a tailored mobile layout
To make this app look good on smaller devices, we're going to create a separate set of styles in our XAML page
that will only be used if a mobile device is detected.
Create a new DataTemplate
We're going to tailor the gallery view of the application by creating a new DataTemplate for the images. Open
MainPage.xaml from the Solution Explorer, and add the following code within the Page.Resources tags.

<DataTemplate x:Key="ImageGridView_MobileItemTemplate"
x:DataType="local:ImageFileInfo">

<!-- Create image grid -->


<Grid Height="{Binding ItemSize, ElementName=page}"
Width="{Binding ItemSize, ElementName=page}">

<!-- Place image in grid, stretching it to fill the pane-->


<Image x:Name="ItemImage"
Source="{x:Bind ImagePreview}"
Stretch="UniformToFill">
</Image>

</Grid>
</DataTemplate>

This gallery template saves screen real estate by eliminating the border around images, and getting rid of the
image metadata (filename, ratings, and so on.) below each thumbnail. Instead, we show each thumbnail as a
simple square.
Add metadata to a tooltip
We still want the user to be able to access the metadata for each image, so we'll add a tooltip to each image item.
Add the following code within the Image tags of the DataTemplate you just created.
<Image ...>

<!-- Add a tooltip to the image that displays metadata -->


<ToolTipService.ToolTip>
<ToolTip x:Name="tooltip">

<!-- Arrange tooltip elements vertically -->


<StackPanel Orientation="Vertical"
Grid.Row="1">

<!-- Image title -->


<TextBlock Text="{x:Bind ImageTitle, Mode=OneWay}"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}" />

<!-- Arrange elements horizontally -->


<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">

<!-- Image file type -->


<TextBlock Text="{x:Bind ImageFileType}"
HorizontalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}" />

<!-- Image dimensions -->


<TextBlock Text="{x:Bind ImageDimensions}"
HorizontalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Margin="8,0,0,0" />
</StackPanel>
</StackPanel>
</ToolTip>
</ToolTipService.ToolTip>
</Image>

This will show the title, file type, and dimensions of an image when you hover the mouse over the thumbnail (or
press and hold on a touch screen).
Add a VisualStateManager and StateTrigger
We've now created a new layout for our data, but the app currently has no way of knowing when to use this layout
over the default styles. To fix this, we'll need to add a VisualStateManager. Add the following code to the root
element of the page, RelativePanel.

<VisualStateManager.VisualStateGroups>
<VisualStateGroup>

<!-- Add a new VisualState for mobile devices -->


<VisualState x:Key="Mobile">

<!-- Trigger visualstate when a mobile device is detected -->


<VisualState.StateTriggers>
<local:MobileScreenTrigger InteractionMode="Touch" />
</VisualState.StateTriggers>

</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

This adds a new VisualState and StateTrigger, which will be triggered when the app detects that it is running on
a mobile device (the logic for this operation can be found in MobileScreenTrigger.cs, which is provided for you in
the PhotoLab directory). When the StateTrigger starts, the app will use whatever layout attributes are assigned to
this VisualState.
Add VisualState setters
Next, we'll use VisualState setters to tell the VisualStateManager what attributes to apply when the state is
triggered. Each setter targets one property of a particular XAML element and sets it to the given value. Add this
code to the mobile VisualState you just created, below the VisualState.StateTriggers element.

<VisualStateManager.VisualStateGroups>
<VisualStateGroup>

<VisualState x:Key="Mobile">
...

<!-- Add setters for mobile visualstate -->


<VisualState.Setters>

<!-- Move GridView about the command bar -->


<Setter Target="ImageGridView.(RelativePanel.Above)"
Value="MainCommandBar" />

<!-- Switch to mobile layout -->


<Setter Target="ImageGridView.ItemTemplate"
Value="{StaticResource ImageGridView_MobileItemTemplate}" />

<!-- Switch to mobile container styles -->


<Setter Target="ImageGridView.ItemContainerStyle"
Value="{StaticResource ImageGridView_MobileItemContainerStyle}" />

<!-- Move command bar to bottom of the screen -->


<Setter Target="MainCommandBar.(RelativePanel.AlignBottomWithPanel)"
Value="True" />
<Setter Target="MainCommandBar.(RelativePanel.AlignLeftWithPanel)"
Value="True" />
<Setter Target="MainCommandBar.(RelativePanel.AlignRightWithPanel)"
Value="True" />

<!-- Adjust the zoom slider to fit mobile screens -->


<Setter Target="ZoomSlider.Minimum"
Value="80" />
<Setter Target="ZoomSlider.Maximum"
Value="180" />
<Setter Target="ZoomSlider.TickFrequency"
Value="20" />
<Setter Target="ZoomSlider.Value"
Value="100" />
</VisualState.Setters>

</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

These setters set the ItemTemplate of the image gallery to the new DataTemplate that we created in the first
part, and align the command bar and zoom slider with the bottom of the screen, so they are easier to reach with
your thumb on a mobile phone screen.
Run the app
Now try running the app using a mobile emulator. Does the new layout display successfully? You should see a grid
of small thumbnails as below. If you still see the old layout, there may be a typo in your VisualStateManager
code.
Part 3: Adapt to multiple window sizes on a single device
Creating a new tailored layout solves the challenge of responsive design for mobile devices, but what about
desktops and tablets? The app may look good at full screen, but if the user shrinks the window, they may end up
with an awkward interface. We can ensure that the end-user experience always looks and feels right by using the
VisualStateManager to adapt to multiple window sizes on a single device.

Add window snap points


The first step is to define the "snap points" at which different VisualStates will be triggered. Open App.xaml from
the Solution Explorer, and add the following code between the Application tags.

<Application.Resources>
<!-- window width adaptive snap points -->
<x:Double x:Key="MinWindowSnapPoint">0</x:Double>
<x:Double x:Key="MediumWindowSnapPoint">641</x:Double>
<x:Double x:Key="LargeWindowSnapPoint">1008</x:Double>
</Application.Resources>

This gives us three snap points, which allow us to create new VisualStates for three ranges of window sizes:
Small (0 - 640 pixels wide)
Medium (641 - 1007 pixels wide)
Large (> 1007 pixels wide)
Create new VisualStates and StateTriggers
Next, we create the VisualStates and StateTriggers that correspond to each snap point. In MainPage.xaml, add
the following code to the VisualStateManager that you created in Part 2.

<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
...

<!-- Large window VisualState -->


<VisualState x:Key="LargeWindow">

<!-- Large window trigger -->


<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource LargeWindowSnapPoint}"/>
</VisualState.StateTriggers>

</VisualState>

<!-- Medium window VisualState -->


<VisualState x:Key="MediumWindow">

<!-- Medium window trigger -->


<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource MediumWindowSnapPoint}"/>
</VisualState.StateTriggers>

</VisualState>

<!-- Small window VisualState -->


<VisualState x:Key="SmallWindow">

<!-- Small window trigger -->


<VisualState.StateTriggers >
<AdaptiveTrigger MinWindowWidth="{StaticResource MinWindowSnapPoint}"/>
</VisualState.StateTriggers>

</VisualState>

</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

Add setters
Finally, add these setters to the SmallWindow state.
<VisualState x:Key="SmallWindow">
...

<!-- Small window setters -->


<VisualState.Setters>

<!-- Apply mobile itemtemplate and styles -->


<Setter Target="ImageGridView.ItemTemplate"
Value="{StaticResource ImageGridView_MobileItemTemplate}" />
<Setter Target="ImageGridView.ItemContainerStyle"
Value="{StaticResource ImageGridView_MobileItemContainerStyle}" />

<!-- Adjust the zoom slider to fit small windows-->


<Setter Target="ZoomSlider.Minimum"
Value="80" />
<Setter Target="ZoomSlider.Maximum"
Value="180" />
<Setter Target="ZoomSlider.TickFrequency"
Value="20" />
<Setter Target="ZoomSlider.Value"
Value="100" />
</VisualState.Setters>

</VisualState>

These setters apply the mobile DataTemplate and styles to the desktop app, whenever the viewport is less than
641 pixels wide. They also tweak the zoom slider to better fit the small screen.
Run the app
In the Visual Studio toolbar set the target device to Local Machine, and run the app. When the app loads, try
changing the size of the window. When you shrink the window to a small size, you should see the app switch to
the mobile layout you created in Part 2.
Going further
Now that you've completed this lab, you have enough adaptive layout knowledge to experiment further on your
own. Try adding a rating control to the mobile-only tooltip you added earlier. Or, for a bigger challenge, try
optimizing the layout for larger screen sizes (think TV screens or a Surface Studio)
If you get stuck, you can find more guidance in these sections of Define page layouts with XAML.
Visual states and state triggers
Tailored layouts
Alternatively, if you want to learn more about how the initial app was built, check out these tutorials on XAML user
interfaces and data binding.
Introduction to UWP app design
8/9/2017 11 min to read Edit Online

A Universal Windows Platform (UWP) app can run on any Windows-based device, from your phone to your tablet
or PC.
Designing an app that looks good on such a wide variety of devices can be a big challenge. Fortunately, the
Universal Windows Platform (UWP) provides a set of built-in features and universal building blocks that help you
create a UX that works well with a variety of devices, screens, and input methods. This articles describes the UI
features and benefits of UWP apps and provides some high-level design guidance for creating your first UWP app.

Video summary

UWP features
Let's start by taking a look at some of the features that you get when you create a UWP app.
Effective pixels and scaling
UWP apps automatically adjust the size of controls, fonts, and other UI elements so that they are legible and easy
to interact with on all devices.
When your app runs on a device, the system uses an algorithm to normalize the way UI elements display on the
screen. This scaling algorithm takes into account viewing distance and screen density (pixels per inch) to optimize
for perceived size (rather than physical size). The scaling algorithm ensures that a 24 px font on Surface Hub 10
feet away is just as legible to the user as a 24 px font on 5" phone that's a few inches away.

Because of how the scaling system works, when you design your UWP app, you're designing in effective pixels, not
actual physical pixels. So, how does that impact the way you design your app?
You can ignore the pixel density and the actual screen resolution when designing. Instead, design for the
effective resolution (the resolution in effective pixels) for a size class (for details, see the Screen sizes and
breakpoints article).
When the system scales your UI, it does so by multiples of 4. To ensure a crisp appearance, snap your
designs to the 4x4 pixel grid: make margins, sizes, and the positions of UI elements a multiple of 4 effective
pixels. Note that text doesn't have this requirement; the text can have any size and position.
This illustration shows design elements that map to the 4x4 pixel grid. The design element will always have crisp,
sharp edges.

TIP
When creating screen mockups in image editing programs, set the DPI to 72 and set the image dimensions to the effective
resolution for the size class you're targeting. For a list of size classes and effective resolutions, see the Screen sizes and
breakpoints article.

Universal input and smart interactions


Another built-in capability of the UWP is universal input enabled via smart interactions. Although you can design
your apps for specific input modes and devices, you arent required to. Thats because Universal Windows apps by
default rely on smart interactions. That means you can design around a click interaction without having to know or
define whether the click comes from an actual mouse click or the tap of a finger.
Universal controls and styles
The UWP also provides some useful building blocks that make it easier to design apps for multiple device families.
Universal controls
The UWP provides a set of universal controls that are guaranteed to work well on all Windows-powered
devices. This set of universal controls includes everything from common form controls like radio button and
text box to sophisticated controls like grid view and list view that can generate lists of items from a stream
of data and a template. These controls are input-aware and deploy with the proper set of input affordances,
event states, and overall functionality for each device family.
For a complete list of these controls and the patterns you can make from them, see the Controls and
patterns section.
Universal styles
Your UWP app automatically gets a default set of styles that gives you these features:
A set of styles that automatically gives your app a light or dark theme (your choice) and can
incorporate the user's accent color preference.

A Segoe-based type ramp that ensures that app text looks crisp on all devices.
Default animations for interactions.
Automatic support for high-contrast modes. Our styles were designed with high-contrast in mind, so
when your app runs on a device in high-contrast mode, it will display properly.
Automatic support for other languages. Our default styles automatically select the correct font for every
language that Windows supports. You can even use multiple languages in the same app and they'll be
displayed properly.
Built-in support for RTL reading order.
You can customize these default styles to give your app a personal touch, or you can completely replace
them with your own to create a unique visual experience. For example, here's a design for a weather app
with a unique visual style:
UWP and the Fluent Design System
The Fluent Design System helps you create modern, clean UI that incorporates light, depth, motion, material, and
scale. Fluent Design is being applied across Windows 10 devices and apps to create beautiful, engaging, and
intuitive experiences.
How can you incorporate Fluent Design into your app? We're continually adding new controls and features that
make it easy. Here's a list of current Fluent Design features for UWP:
Acrylic is a type of brush that creates semi-transparent surfaces.
Parallax adds three-dimensional perspective, depth, and movement to scrolling content, such as lists.
Reveal uses light to create a hover effect that illuminates interactive UI elements.
Connected animations provide graceful scene transitions that improve usability by maintaining context and
providing continuity.
We've also updated our design guidelines (which you're current reading) so they're based on Fluent Design
principles.

The anatomy of a typical UWP app


Now that we've described the building blocks of UWP apps, let's take a look at how to put them together to create
a UI.
A modern user interface is a complex thing, made up of text, shapes, colors, and animations which are ultimately
made up out of individual pixels of the screen of the device you're using. When you start designing a user interface,
the sheer number of choices can be overwhelming.
To make things simpler, let's define the anatomy of an app from a design perspective. Let's say that an app is made
up of screens and pages. Each page has a user interface, made up of three types of UI elements: navigation,
commanding, and content elements.
Navigation elements
Navigation elements help users choose the content they
want to display. Examples of navigation elements include
tabs and pivots, hyperlinks, and nav panes.
Navigation elements are covered in detail in the
Navigation design basics article.
Command elements
Command elements initiate actions, such as
manipulating, saving, or sharing content. Examples of
command elements include button and the command
bar. Command elements can also include keyboard
shortcuts that aren't actually visible on the screen.
Command elements are covered in detail in the
Command design basics article.
Content elements
Content elements display the app's content. For a
painting app, the content might be a drawing; for a news
app, the content might be a news article.
Content elements are covered in detail in the Content
design basics article.

At a minimum, an app has a splash screen and a home page that defines the user interface. A typical app will have
multiple pages and screens, and navigation, command, and content elements might change from page to page.
When deciding on the right UI elements for your app, you might also consider the devices and the screen sizes
your app will run on.

Tailoring your app for specific devices and screen sizes.


UWP apps use effective pixels to guarantee that your design elements will be legible and usable on all Windows-
powered devices. So, why would you ever want to customize your app's UI for a specific device family?
Note
Before we go any further, Windows doesn't provide a way for your app to detect the specific device your app is
running on. It can tell you the device family (mobile, desktop, etc) the app is running on, the effective resolution,
and the amount of screen space available to the app (the size of the app's window).
To make the most effective use of space and reduce the need to navigate
If you design an app to look good on a device that has a small screen, such as a phone, the app will be
usable on a PC with a much bigger display, but there will probably be some wasted space. You can
customize the app to display more content when the screen is above a certain size. For example, a shopping
app might display one merchandise category at a time on a phone, but show multiple categories and
products simultaneously on a PC or laptop.
By putting more content on the screen, you reduce the amount of navigation that the user needs to perform.
To take advantage of devices' capabilities
Certain devices are more likely to have certain device capabilities. For example, phones are likely to have a
location sensor and a camera, while a PC might not have either. Your app can detect which capabilities are
available and enable features that use them.
To optimize for input
The universal control library works with all input types (touch, pen, keyboard, mouse), but you can still
optimize for certain input types by re-arranging your UI elements. For example, if you place navigation
elements at the bottom of the screen, they'll be easier for phone users to accessbut most PC users expect
to see navigation elements toward the top of the screen.

Responsive design techniques


When you optimize your app's UI for specific screen widths, we say that you're creating a responsive design. Here
are six responsive design techniques you can use to customize your app's UI.
Reposition
You can alter the location and position of app UI elements to get the most out of each device. In this example, the
portrait view on phone or phablet necessitates a scrolling UI because only one full frame is visible at a time. When
the app translates to a device that allows two full on-screen frames, whether in portrait or landscape orientation,
frame B can occupy a dedicated space. If you're using a grid for positioning, you can stick to the same grid when UI
elements are repositioned.

In this example design for a photo app, the photo app repositions its content on larger screens.
Resize
You can optimize the frame size by adjusting the margins and size of UI elements. This could allow you, as the
example here shows, to augment the reading experience on a larger screen by simply growing the content frame.

Reflow
By changing the flow of UI elements based on device and orientation, your app can offer an optimal display of
content. For instance, when going to a larger screen, it might make sense to switch larger containers, add columns,
and generate list items in a different way.
This example shows how a single column of vertically scrolling content on phone or phablet can be reflowed on a
larger screen to display two columns of text.
Show/hide
You can show or hide UI elements based on screen real estate, or when the device supports additional
functionality, specific situations, or preferred screen orientations.
In this example with tabs, the middle tab with the camera icon might be specific to the app on phone or phablet
and not be applicable on larger devices, which is why it's revealed in the device on the right. Another common
example of revealing or hiding UI applies to media player controls, where the button set is reduced on smaller
devices and expanded on larger devices. The media player on PC, for instance, can handle far more on-screen
functionality than it can on a phone.

Part of the reveal-or-hide technique includes choosing when to display more metadata. When real estate is at a
premium, such as with a phone or phablet, it's best to show a minimal amount of metadata. With a laptop or
desktop PC, a significant amount of metadata can be surfaced. Some examples of how to handle showing or hiding
metadata include:
In an email app, you can display the user's avatar.
In a music app, you can display more info about an album or artist.
In a video app, you can display more info about a film or a show, such as showing cast and crew details.
In any app, you can break apart columns and reveal more details.
In any app, you can take something that's vertically stacked and lay it out horizontally. When going from phone
or phablet to larger devices, stacked list items can change to reveal rows of list items and columns of metadata.
Replace
This technique lets you switch the user interface for a specific device size-class or orientation. In this example, the
nav pane and its compact, transient UI works well for a smaller device, but on a larger device tabs might be a better
choice.

Re-architect
You can collapse or fork the architecture of your app to better target specific devices. In this example, going from
the left device to the right device demonstrates the joining of pages.
Here's an example of this technique applied to the design for a smart home app.
Tools and design toolkits
We provide a variety of tools to help you design you UWP app. See our Design toolkits page for XD, Illustrator,
Photoshop, Framer, and Sketch toolkits, as well as additional design tools and font downloads.
To get your machine set up to actually code UWP apps, see our Get started > Get set up article.

Related articles
What's a UWP app?
Design toolkits
Layout for UWP apps
8/9/2017 2 min to read Edit Online

App structure, page layout, and navigation are the foundation of your app's user experience. The articles in this
section use the Fluent Design System to help you create an app that is easy to navigate and looks great on a variety
of devices and screen sizes.

Intro
Intro to app UI design
When you design a UWP app, you create a user interface that suits a variety of devices with different display
sizes. This article provides an introduction to the Fluent Design System, an overview of UI-related features and
benefits of UWP apps and some tips & tricks for designing a responsive UI.

App layout and structure


Check out these recommendations for structuring your app and using the three types of UI elements: navigation,
command, and content.

Navigation basics
Navigation in UWP apps is based on a flexible model of navigation structures, navigation elements, and system-
level features. This article introduces you to these components and shows you how to use them together to
create a good navigation experience.

Content basics
The main purpose of any app is to provide access to content: in a photo-editing app, the photo is the content; in
a travel app, maps and info about travel destinations is the content; and so on. This article provides content
design recommendations for the three content scenarios: consumption, creation, and interaction.

Command basics
Command elements are the interactive UI elements that enable the user to perform actions, such as sending an
email, deleting an item, or submitting a form. This article describes the command elements, such as buttons and
check boxes, the interactions they support, and the command surfaces (such as command bars and context
menus) for hosting them.

Page layout
These articles help you create a flexible UI that looks great on different screen sizes, window sizes, resolutions, and
orientations.

Screen sizes and breakpoints


The number of device targets and screen sizes across the Windows 10 ecosystem is too great to worry about
optimizing your UI for each one. Instead, we recommended designing for a few key widths (also called
"breakpoints"): 360, 640, 1024 and 1366 epx.
Define layouts with XAML
How to use XAML properties and layout panels to make your app responsive and adaptive.
Layout panels
Learn about each type of layout each panel and show how to use them to layout XAML UI elements.
Alignment, margins, and padding
In addition to dimension properties (width, height, and constraints) elements can also have alignment, margin, and
padding properties that influence the layout behavior when an element goes through a layout pass and is rendered
in a UI.
Create layouts with Grid and StackPanel
Use XAML to create the layout for a simple weather app using the Grid and StackPanel elements.
Navigation design basics for UWP apps
5/22/2017 9 min to read Edit Online

If you think of an app as a collection of pages, the term navigation describes the act of moving between pages
and within the page. It's the starting point of the user experience. It's how users find the content and features
they're interested in. It's very important, and it can be difficult to get right.

Important APIs: Frame, Pivot class, NavigationView class

Part of the reason it's difficult to get right is that, as app designers, we have a huge number of choices to make. If
we were designing a book, our choices would be simple: what order do the chapters go in. With an app, we can
create a navigation experience that mimics a book, requiring the user to go through a series of pages in order. Or
we could provide a menu that lets the user jump directly to any page he or she wants--but if we have too many
pages, we might overwhelm the user with choices. Or we could put everything on a single page and provide
filtering mechanisms for viewing content.
While there's no single navigation design that works for every app, there are a set of principles and guidelines
you can follow to help you figure out the right design for your app.

Principles of good design


Let's start with the basic principles that research has shown form the foundation of good navigation design:
Be consistent: Meet user expectations.
Keep it simple: Don't do more than you need to.
Keep it clean: Don't let navigation features get in the user's way.
Be consistent
Navigation should be consistent with user expectations, leaning on standard conventions for icons, location and
styling.
For example, in the following illustration, you can see the spots where users will typically expect to find
functionality, like the navigation pane and command bar. Different device families have their own conventions
for navigational elements. For example, the navigation pane typically appears on the left side of the screen for
tablets, but up top for mobile devices.

Users expect to find certain UI elements in standard locations.

Keep it simple
Another important factor in navigation design is the Hick-Hyman Law, often cited in relation to navigational
options. This law encourages us to add fewer options to the menu. The more options there are, the slower user
interactions with them will be, particularly when users are exploring a new app.

On the left, notice there are fewer options for the user to select, whereas on the right, there are several. The Hick-Hyman Law
indicates that the menu on the left will be easier for users to understand and utilize.

Keep it clean
The final key characteristic of navigation is clean interaction, which refers to the physical way that users interact
with navigation across a variety of contexts. This is one area where putting yourself in the users position will
inform your design. Try to understand your user and their behaviors. For example, if you're designing a cooking
app, you might consider providing easy access to a shopping list and a timer.

Three general rules


Now lets take our design principles--consistency, simplicity, and clean interaction--and use them to come up
with some general rules. As with any rule of thumb, use them as starting points and tweak as needed.
1. Avoid deep navigational hierarchies. How many levels of navigation are best for your users? A top-level
navigation and one level beneath it is usually plenty. If you go beyond three levels of navigation, then you
break the principle of simplicity. Even worse, you risk stranding your user in a deep hierarchy that they
will have difficulty leaving.
2. Avoid too many navigational options. Three to six navigation elements per level are most common. If your
navigation needs more than this, especially at the top level of your hierarchy, then you might consider
splitting your app into multiple apps, since you may be trying to do too much in one place. Too many
navigation elements in an app usually lead to inconsistent and unrelated objectives.
3. Avoid "pogo-sticking." Pogo-sticking occurs when there is related content, but navigating to it requires the
user to go up a level and then down again. Pogo-sticking violates the principle of clean interaction by
requiring unnecessary clicks or interactions to achieve an obvious goalin this case, looking at related
content in a series. (The exception to this rule is in search and browse, where pogo-sticking may be the
only way to provide the diversity and depth required.)
Pogo-sticking to navigate through an appthe user has to go back (green back arrow) to the main page in order to
navigate to the Projects tab.

You can resolve some pogo-sticking issues with an icon (note the swipe gesture in green).

Use the right structure


Now that you're familiar with general navigation principles and rules, it's time to make the most important of all
navigation decisions: how should you structure your app? There are two general structures: flat and hierarchal.
Flat/lateral
In a flat/lateral structure, pages exist side-by-side. You can go from on page to another in any order.

Pages arranged in a flat structure

Flat structures have many benefits: they're simple and they're easy to understand, and they let the user jump
directly to a specific page without having to wade through intermediary pages. In general, flat structures are
great--but they don't work for every app. If your app has a lot of pages, a flat list can be overwhelming. If pages
need to be viewed in a particular order, a flat structure doesn't work.
We recommend using a flat structure when:
The pages can be viewed in any order.
The pages are clearly distinct from each other and don't have an obvious parent/child relationship.
There are fewer than 8 pages in the group.
When there are more than 7 pages in the group, it might be difficult for users to understand how the pages
are unique or to understand their current location within the group. If you don't think that's an issue for your
app, go ahead and make the pages peers. Otherwise, consider using a hierarchical structure to break the
pages into two or more smaller groups. (A hub control can help you group pages into categories.)
Hierarchical
In a hierarchical structure, pages are organized into a tree-like structure. Each child page has only one parent, but
a parent can have one or more child pages. To reach a child page, you travel through the parent.

Pages arranged in a hierarchy

Hierarchical structures are good for organizing complex content that spans lots of pages or when pages should
be viewed in a particular order. The downside is that hierarchical pages introduce some navigation overhead: the
deeper the structure, the more clicks it takes for users to get from page to page.
We recommend a hiearchical structure when:
You expect the user to traverse the pages in a specific order. Arrange the hierarchy to enforce that order.
There is a clear parent-child relationship between one of the pages and the other pages in the group.
There are more than 7 pages in the group.
When there are more than 7 pages in the group, it might be difficult for users to understand how the pages
are unique or to understand their current location within the group. If you don't think that's an issue for your
app, go ahead and make the pages peers. Otherwise, consider using a hierarchical structure to break the
pages into two or more smaller groups. (A hub control can help you group pages into categories.)
Combining structures
You don't have choose one structure or the other; many well-design apps use both flat and hierarchical
structures:

These apps use flat structures for top-level pages that can be viewed in any order, and hierarchical structures for
pages that have more complex relationships.
If your navigation structure has multiple levels, we recommend that peer-to-peer navigation elements only link
to the peers within their current subtree. Consider the following illustration, which shows a navigation structure
that has three levels:

For level 1, the peer-to-peer navigation element should provide access to pages A, B, C, and D.
At level 2, the peer-to-peer navigation elements for the A2 pages should only link to the other A2 pages. They
should not link to level 2 pages in the C subtree.

Use the right controls


Once you've decided on a page structure, you need to decide how users navigate through those pages. UWP
provides a variety of navigation controls to help you. Because these controls are available to every UWP app,
using them helps ensure a consistent and reliable navigation experience.

CONTROL DESCRIPTION

Frame With few exceptions, any app that has multiple pages uses
the frame. In a typical setup, the app has a main page that
contains the frame and a primary navigation element, such
as a navigation view control. When the user selects a page,
the frame loads and displays it.

Tabs and pivot Displays a list of links to pages at the same level.
Use tabs/pivots when:
There are 2-5 pages.
(You can use tabs/pivots when there are more
than 5 pages, but it might be difficult to fit all the
tabs/pivots on the screen.)
You expect users to switch between pages frequently.

Nav view Displays a list of links to top-level pages.


Use a navigation pane when:
You don't expect users to switch between pages
frequently.
You want to conserve space at the expense of slowing
down navigation operations.
The pages exist at the top level.

Master/details Displays a list (master view) of item summaries. Selecting an


item displays its corresponding items page in the details
section.
Use the Master/details element when:
You expect users to switch between child items
frequently.
You want to enable the user to perform high-level
operations, such as deleting or sorting, on individual
items or groups of items, and also want to enable the
user to view or update the details for each item.
Master/details elements are well suited for email inboxes,
contact lists, and data entry.
Back Lets the user traverse the navigation history within an app
and, depending on the device, from app to app. For more
info, see the Navigation history and backwards navigation
article.

Hyperlinks and buttons Content-embedded navigation elements appear in a page's


content. Unlike other navigation elements, which should be
consistent across the page's group or subtree, content-
embedded navigation elements are unique from page to
page.

Next: Add navigation code to your app


The next article, Implement basic navigation, shows the XAML and code required to use a Frame control to
enable basic navigation in your app.
Implement navigation between two pages
5/22/2017 7 min to read Edit Online

Learn how to use a frame and pages to enable basic navigation in your app.

Important APIs: Windows.UI.Xaml.Controls.Frame class,


Windows.UI.Xaml.Controls.Page class,
Windows.UI.Xaml.Navigation namespace

1. Create a blank app


1. On the Microsoft Visual Studio menu, choose File > New Project.
2. In the left pane of the New Project dialog box, choose the Visual C# -> Windows -> Universal or the Visual
C++ -> Windows -> Universal node.
3. In the center pane, choose Blank App.
4. In the Name box, enter NavApp1, and then choose the OK button.
The solution is created and the project files appear in Solution Explorer.
5. To run the program, choose Debug > Start Debugging from the menu, or press F5.
A blank page is displayed.
6. Press Shift+F5 to stop debugging and return to Visual Studio.

2. Add basic pages


Next, add two content pages to the project.
Do the following steps two times to add two pages to navigate between.
1. In Solution Explorer, right-click the BlankApp project node to open the shortcut menu.
2. Choose Add > New Item from the shortcut menu.
3. In the Add New Item dialog box, choose Blank Page in the middle pane.
4. In the Name box, enter Page1 (or Page2) and press the Add button.
These files should now be listed as part of your NavApp1 project.

C# C++

Page1.xaml Page1.xaml
Page1.xaml.cs Page1.xaml.cpp
Page2.xaml Page1.xaml.h
Page2.xaml.cs Page2.xaml
Page2.xaml.cpp
Page2.xaml.h

Add the following content to the UI of Page1.xaml.


Add a TextBlock element named pageTitle as a child element of the root Grid. Change the Text property to
Page 1 .
<TextBlock x:Name="pageTitle" Text="Page 1" />

Add the following HyperlinkButton element as a child element of the root Grid and after the pageTitle
TextBlock element.

<HyperlinkButton Content="Click to go to page 2"


Click="HyperlinkButton_Click"
HorizontalAlignment="Center"/>

Add the following code to the Page1 class in the Page1.xaml code-behind file to handle the Click event of the
HyperlinkButton you added previously. Here, we navigate to Page2.xaml.

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)


{
this.Frame.Navigate(typeof(Page2));
}

void Page1::HyperlinkButton_Click(Platform::Object^ sender, RoutedEventArgs^ e)


{
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(Page2::typeid));
}

Make the following changes to the UI of Page2.xaml.


Add a TextBlock element named pageTitle as a child element of the root Grid. Change the value of the Text
property to Page 2 .

<TextBlock x:Name="pageTitle" Text="Page 2" />

Add the following HyperlinkButton element as a child element of the root Grid and after the pageTitle
TextBlock element.

<HyperlinkButton Content="Click to go to page 1"


Click="HyperlinkButton_Click"
HorizontalAlignment="Center"/>

Add the following code to the Page2 class in the Page2.xaml code-behind file to handle the Click event of the
HyperlinkButton you added previously. Here, we navigate to Page1.xaml.

NOTE
For C++ projects, you must add a #include directive in the header file of each page that references another page. For the
inter-page navigation example presented here, page1.xaml.h file contains #include "Page2.xaml.h" , in turn, page2.xaml.h
contains #include "Page1.xaml.h" .

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)


{
this.Frame.Navigate(typeof(Page1));
}
void Page2::HyperlinkButton_Click(Platform::Object^ sender, RoutedEventArgs^ e)
{
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(Page1::typeid));
}

Now that we've prepared the content pages, we need to make Page1.xaml display when the app starts.
Open the app.xaml code-behind file and change the OnLaunched handler.
Here, we specify Page1 in the call to Frame.Navigate instead of MainPage .

protected override void OnLaunched(LaunchActivatedEventArgs e)


{
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();

rootFrame.NavigationFailed += OnNavigationFailed;

if (e.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
rootFrame.Navigate(typeof(Page1), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ e)
{
auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == nullptr)
{
// Create a Frame to act as the navigation context and associate it with
// a SuspensionManager key
rootFrame = ref new Frame();

rootFrame->NavigationFailed +=
ref new Windows::UI::Xaml::Navigation::NavigationFailedEventHandler(
this, &App::OnNavigationFailed);

if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
{
// TODO: Load state from previously suspended application
}

// Place the frame in the current Window


Window::Current->Content = rootFrame;
}

if (rootFrame->Content == nullptr)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(Page1::typeid), e->Arguments);
}

// Ensure the current window is active


Window::Current->Activate();
}

Note The code here uses the return value of Navigate to throw an app exception if the navigation to the app's
initial window frame fails. When Navigate returns true, the navigation happens.
Now, build and run the app. Click the link that says "Click to go to page 2". The second page that says "Page 2" at
the top should be loaded and displayed in the frame.

About the Frame and Page classes


Before we add more functionality to our app, let's look at how the pages we added provide navigation support for
the app.
First, a Frame ( rootFrame ) is created for the app in the App.OnLaunched method of the App.xaml code-behind file.
The Navigate method is used to display content in this Frame.
Note
The Frame class supports various navigation methods such as Navigate, GoBack, and GoForward, and properties
such as BackStack, ForwardStack, and BackStackDepth.
In our example, Page1 is passed to the Navigate method. This method sets the content of the app's current
window to the Frame and loads the content of the page you specify into the Frame (Page1.xaml in our example, or
MainPage.xaml, by default).
Page1 is a subclass of the Page class. The Page class has a read-only Frame property that gets the Frame
containing the Page. When the Click event handler of the HyperlinkButton calls Frame.Navigate(typeof(Page2)) , the
Frame in the app's window displays the content of Page2.xaml.
Whenever a page is loaded into the frame, that page is added as a PageStackEntry to the BackStack or
ForwardStack of the Frame.

3. Pass information between pages


Our app navigates between two pages, but it really doesn't do anything interesting yet. Often, when an app has
multiple pages, the pages need to share information. Let's pass some information from the first page to the second
page.
In Page1.xaml, replace the the HyperlinkButton you added earlier with the following StackPanel.
Here, we add a TextBlock label and a TextBox ( name ) for entering a text string.

<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="Enter your name"/>
<TextBox HorizontalAlignment="Center" Width="200" Name="name"/>
<HyperlinkButton Content="Click to go to page 2"
Click="HyperlinkButton_Click"
HorizontalAlignment="Center"/>
</StackPanel>

In the HyperlinkButton_Click event handler of the Page1.xaml code-behind file, add a parameter referencing the Text
property of the name TextBox to the Navigate method.

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)


{
this.Frame.Navigate(typeof(Page2), name.Text);
}

void Page1::HyperlinkButton_Click(Platform::Object^ sender, RoutedEventArgs^ e)


{
this->Frame->Navigate(Windows::UI::Xaml::Interop::TypeName(Page2::typeid), name->Text);
}

In Page2.xaml, replace the the HyperlinkButton you added earlier with the following StackPanel.
Here, we add a TextBlock for displaying a text string passed from Page1.

<StackPanel>
<TextBlock HorizontalAlignment="Center" Name="greeting"/>
<HyperlinkButton Content="Click to go to page 1"
Click="HyperlinkButton_Click"
HorizontalAlignment="Center"/>
</StackPanel>

In the Page2.xaml code-behind file, override the OnNavigatedTo method with the following:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.Parameter is string && !string.IsNullOrWhiteSpace((string)e.Parameter))
{
greeting.Text = $"Hi, {e.Parameter.ToString()}";
}
else
{
greeting.Text = "Hi!";
}
base.OnNavigatedTo(e);
}

void Page2::OnNavigatedTo(NavigationEventArgs^ e)
{
if (dynamic_cast<Platform::String^>(e->Parameter) != nullptr)
{
greeting->Text = "Hi," + e->Parameter->ToString();
}
else
{
greeting->Text = "Hi!";
}
::Windows::UI::Xaml::Controls::Page::OnNavigatedTo(e);
}

Run the app, type your name in the text box, and then click the link that says Click to go to page 2. When you
called this.Frame.Navigate(typeof(Page2), name.Text) in the Click event of the HyperlinkButton, the name.Text property
was passed to Page2 and the value from the event data is used for the message displayed on the page.

4. Cache a page
Page content and state is not cached by default, you must enable it in each page of your app.
In our basic peer-to-peer example, there is no back button (we demonstrate back navigation in Back button
navigation), but if you did click a back button on Page2 , the TextBox (and any other field) on Page1 would be set
to its default state. One way to work around this is to use the NavigationCacheMode property to specify that a
page be added to the frame's page cache.
In the constructor of Page1 , set NavigationCacheMode to Enabled. This retains all content and state values for
the page until the page cache for the frame is exceeded.
Set NavigationCacheMode to Required if you want to ignore cache size limits for the frame. However, cache size
limits might be crucial, depending on the memory limits of a device.

NOTE
The CacheSize property specifies the number of pages in the navigation history that can be cached for the frame.

public Page1()
{
this.InitializeComponent();
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
}
Page1::Page1()
{
this->InitializeComponent();
this->NavigationCacheMode = Windows::UI::Xaml::Navigation::NavigationCacheMode::Enabled;
}

Related articles
Navigation design basics for UWP apps
Guidelines for tabs and pivots
Guidelines for navigation panes
Navigation history and backwards navigation for
UWP apps
5/22/2017 7 min to read Edit Online

On the Web, individual web sites provide their own navigation systems, such as tables of contents, buttons, menus,
simple lists of links, and so on. The navigation experience can vary wildly from website to website. However, there
is one consistent navigation experience: back. Most browsers provide a back button that behaves the same way
regardless of the website.

Important APIs: SystemNavigationManager class, BackRequested event, OnNavigatedTo

For similar reasons, the Universal Windows Platform (UWP) provides a consistent back navigation system for
traversing the user's navigation history within an app and, depending on the device, from app to app.
The UI for the system back button is optimized for each form factor and input device type, but the navigation
experience is global and consistent across devices and UWP apps.
Here are the primary form factors with the back button UI:

Devices Back button behavior

Phone Always present.


A software or hardware button
at the bottom of the device.
Global back navigation within
the app and between apps.

Tablet Always present in Tablet mode.


Not available in Desktop mode.
Title bar back button can be
enabled, instead. See PC,
Laptop, Tablet. Users can switch
between running in Tablet mode
and Desktop mode by going to
Settings > System > Tablet
mode and setting Make
Windows more touch-
friendly when using your
device as a tablet.
A software button in the
navigation bar at the bottom of
the device.
Global back navigation within
the app and between apps.
PC, Laptop, Tablet Optional in Desktop mode. Not
available in Tablet mode. See
Tablet. Disabled by default.
Must opt in to enable it. Users
can switch between running in
Tablet mode and Desktop mode
by going to Settings > System
> Tablet mode and setting
Make Windows more touch-
friendly when using your
device as a tablet.
A software button in the title
bar of the app.
Back navigation within the app
only. Does not support app-to-
app navigation.

Surface Hub Optional.


Disabled by default. Must opt in
to enable it.
A software button in the title
bar of the app.
Back navigation within the app
only. Does not support app-to-
app navigation.

Here are some alternative input types that don't rely on a back button UI, but still provide the exact same functionality.

Input devices

Keyboard Windows key + Backspace

Cortana Say, "Hey Cortana, go back"

When your app runs on a phone, tablet, or on a PC or laptop that has system back enabled, the system notifies
your app when the back button is pressed. The user expects the back button to navigate to the previous location in
the app's navigation history. It's up to you to decide which navigation actions to add to the navigation history and
how to respond to the back button press.

How to enable system back navigation support


Apps must enable back navigation for all hardware and software system back buttons. Do this by registering a
listener for the BackRequested event and defining a corresponding handler.
Here we register a global listener for the BackRequested event in the App.xaml code-behind file. You can register
for this event in each page if you want to exclude specific pages from back navigation, or you want to execute
page-level code before displaying the page.
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested +=
App_BackRequested;

Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
BackRequested += ref new Windows::Foundation::EventHandler<
Windows::UI::Core::BackRequestedEventArgs^>(
this, &App::App_BackRequested);

Here's the corresponding BackRequested event handler that calls GoBack on the root frame of the app.
This handler is invoked on a global back event. If the in-app back stack is empty, the system might navigate to the
previous app in the app stack or to the Start screen. There is no app back stack in Desktop mode and the user stays
in the app even when the in-app back stack is depleted.

private void App_BackRequested(object sender,


Windows.UI.Core.BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
return;

// Navigate back if possible, and if the event has not


// already been handled .
if (rootFrame.CanGoBack && e.Handled == false)
{
e.Handled = true;
rootFrame.GoBack();
}
}

void App::App_BackRequested(
Platform::Object^ sender,
Windows::UI::Core::BackRequestedEventArgs^ e)
{
Frame^ rootFrame = dynamic_cast<Frame^>(Window::Current->Content);
if (rootFrame == nullptr)
return;

// Navigate back if possible, and if the event has not


// already been handled.
if (rootFrame->CanGoBack && e->Handled == false)
{
e->Handled = true;
rootFrame->GoBack();
}
}

How to enable the title bar back button


Devices that support Desktop mode (typically PCs and laptops, but also some tablets) and have the setting enabled
(Settings > System > Tablet mode), do not provide a global navigation bar with the system back button.
In Desktop mode, every app runs in a window with a title bar. You can provide an alternative back button for your
app that is displayed in this title bar.
The title bar back button is only available in apps running on devices in Desktop mode, and only supports in-app
navigation historyit does not support app-to-app navigation history.
Important The title bar back button is not displayed by default. You must opt in.

Desktop mode, no back navigation. Desktop mode, back navigation enabled.

Override the OnNavigatedTo event and set AppViewBackButtonVisibility to Visible in the code-behind file
for each page that you want to enable the title bar back button.
For this example, we list each page in the back stack and enable the back button if the CanGoBack property of the
frame has a value of true.

protected override void OnNavigatedTo(NavigationEventArgs e)


{
Frame rootFrame = Window.Current.Content as Frame;

string myPages = "";


foreach (PageStackEntry page in rootFrame.BackStack)
{
myPages += page.SourcePageType.ToString() + "\n";
}
stackCount.Text = myPages;

if (rootFrame.CanGoBack)
{
// Show UI in title bar if opted-in and in-app backstack is not empty.
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Visible;
}
else
{
// Remove the UI from the title bar if in-app back stack is empty.
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
AppViewBackButtonVisibility.Collapsed;
}
}
void StartPage::OnNavigatedTo(NavigationEventArgs^ e)
{
auto rootFrame = dynamic_cast<Windows::UI::Xaml::Controls::Frame^>(Window::Current->Content);

Platform::String^ myPages = "";

if (rootFrame == nullptr)
return;

for each (PageStackEntry^ page in rootFrame->BackStack)


{
myPages += page->SourcePageType.ToString() + "\n";
}
stackCount->Text = myPages;

if (rootFrame->CanGoBack)
{
// If we have pages in our in-app backstack and have opted in to showing back, do so
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->AppViewBackButtonVisibility =
Windows::UI::Core::AppViewBackButtonVisibility::Visible;
}
else
{
// Remove the UI from the title bar if there are no pages in our in-app back stack
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->AppViewBackButtonVisibility =
Windows::UI::Core::AppViewBackButtonVisibility::Collapsed;
}
}

Guidelines for custom back navigation behavior


If you choose to provide your own back stack navigation, the experience should be consistent with other apps. We
recommend that you follow the following patterns for navigation actions:

NAVIGATION ACTION ADD TO NAVIGATION HISTORY?

Page to page, different peer groups Yes


In this illustration, the user navigates from level 1 of the
app to level 2, crossing peer groups, so the navigation is
added to the navigation history.

In the next illustration, the user navigates between two


peer groups at the same level, again crossing peer
groups, so the navigation is added to the navigation
history.
NAVIGATION ACTION ADD TO NAVIGATION HISTORY?

Page to page, same peer group, no on-screen Yes


navigation element In the following illustration, the user navigates between
The user navigates from one page to another with the two pages in the same peer group. The pages don't use
same peer group. There is no navigation element that is tabs or a docked navigation pane, so the navigation is
always present (such as tabs/pivots or a docked added to the navigation history.
navigation pane) that provides direct navigation to both
pages.

Page to page, same peer group, with an on-screen No


navigation element When the user presses back, go back to the last page
The user navigates from one page to another in the same before the user navigated to the current peer group.
peer group. Both pages are shown in the same navigation
element. For example, both pages use the same
tabs/pivots element, or both pages appear in a docked
navigation pane.

Show a transient UI No
The app displays a pop-up or child window, such as a When the user presses the back button, dismiss the
dialog, splash screen, or on-screen keyboard, or the app transient UI (hide the on-screen keyboard, cancel the
enters a special mode, such as multiple selection mode. dialog, etc) and return to the page that spawned the
transient UI.
NAVIGATION ACTION ADD TO NAVIGATION HISTORY?

Enumerate items No
The app displays content for an on-screen item, such as Enumerating items is similar to navigating within a peer
the details for the selected item in master/details list. group. When the user presses back, navigate to the page
that preceded the current page that has the item
enumeration.

Resuming
When the user switches to another app and returns to your app, we recommend returning to the last page in the
navigation history.

Get the samples


Back button sample
Shows how to set up an event handler for the back button event and how to enable the title bar back button for
when the app is in windowed Desktop mode.

Related articles
Navigation basics
Show multiple views for an app
5/22/2017 5 min to read Edit Online

Help your users be more productive by letting them view independent parts of your app in separate windows.
When you create multiple windows for an app, each window behaves independently. The taskbar shows each
window separately. Users can move, resize, show, and hide app windows independently and can switch between
app windows as if they were separate apps. Each window operates in its own thread.

Important APIs: ApplicationViewSwitcher, CreateNewView

When should an app use multiple views?


There's a variety of scenarios that can benefit from multiple views. Here are a few examples:
An email app that lets users view a list of received messages while composing a new email
An address book app that lets users compare contact info for multiple people side-by-side
A music player app that lets users see what's playing while browsing through a list of other available music
A note-taking app that lets users copy information from one page of notes to another
A reading app that lets users open several articles for reading later, after an opportunity to peruse all high-level
headlines

What is a view?
An app view is the 1:1 pairing of a thread and a window that the app uses to display content. It's represented by a
Windows.ApplicationModel.Core.CoreApplicationView object.
Views are managed by the CoreApplication object. You call CoreApplication.CreateNewView to create
aCoreApplicationView object. The CoreApplicationView brings together a CoreWindow and a
CoreDispatcher (stored in the CoreWindow and Dispatcher properties). You can think of the
CoreApplicationView as the object that the Windows Runtime uses to interact with the core Windows system.
You typically dont work directly with the CoreApplicationView. Instead, the Windows Runtime provides the
ApplicationView class in the Windows.UI.ViewManagement namespace. This class provides properties,
methods, and events that you use when your app interacts with the windowing system. To work with an
ApplicationView, call the static ApplicationView.GetForCurrentView method, which gets an ApplicationView
instance tied to the current CoreApplicationViews thread.
Likewise, the XAML framework wraps the CoreWindow object in a Windows.UI.XAML.Window object. In a XAML
app, you typically interact with the Window object rather than working directly with the CoreWindow.

Show a new view


While each app layout is unique, we recommend including a "new window" button in a predictable location, such as
the top right corner of the content that can be opened in a new window. Also consider including a context menu
option to "Open in a new window".
Let's look at the steps to create a new view. Here, the new view is launched in response to a button click.

private async void Button_Click(object sender, RoutedEventArgs e)


{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame frame = new Frame();
frame.Navigate(typeof(SecondaryPage), null);
Window.Current.Content = frame;
// You have to activate the window in order to show it later.
Window.Current.Activate();

newViewId = ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}

To show a new view


1. Call CoreApplication.CreateNewView to create a new window and thread for the view content.

CoreApplicationView newView = CoreApplication.CreateNewView();

2. Track the Id of the new view. You use this to show the view later.
You might want to consider building some infrastructure into your app to help with tracking the views you
create. See the ViewLifetimeControl class in the MultipleViews sample for an example.

int newViewId = 0;

3. On the new thread, populate the window.


You use the CoreDispatcher.RunAsync method to schedule work on the UI thread for the new view. You
use a lambda expression to pass a function as an argument to the RunAsync method. The work you do in
the lambda function happens on the new view's thread.
In XAML, you typically add a Frame to the Window's Content property, then navigate the Frame to a XAML
Page where you've defined your app content. For more info, see Peer-to-peer navigation between two
pages.
After the new Window is populated, you must call the Window's Activate method in order to show the
Window later. This work happens on the new view's thread, so the new Window is activated.
Finally, get the new view's Id that you use to show the view later. Again, this work is on the new view's
thread, so ApplicationView.GetForCurrentView gets the Id of the new view.

await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>


{
Frame frame = new Frame();
frame.Navigate(typeof(SecondaryPage), null);
Window.Current.Content = frame;
// You have to activate the window in order to show it later.
Window.Current.Activate();

newViewId = ApplicationView.GetForCurrentView().Id;
});

4. Show the new view by calling ApplicationViewSwitcher.TryShowAsStandaloneAsync.


After you create a new view, you can show it in a new window by calling the
ApplicationViewSwitcher.TryShowAsStandaloneAsync method. The viewId parameter for this method
is an integer that uniquely identifies each of the views in your app. You retrieve the view Id by using either
the ApplicationView.Id property or the ApplicationView.GetApplicationViewIdForWindow method.

bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);

The main view


The first view thats created when your app starts is called the main view. This view is stored in the
CoreApplication.MainView property, and its IsMain property is true. You dont create this view; its created by
the app. The main view's thread serves as the manager for the app, and all app activation events are delivered on
this thread.
If secondary views are open, the main views window can be hidden for example, by clicking the close (x) button in
the window title bar - but its thread remains active. Calling Close on the main views Window causes an
InvalidOperationException to occur. (Use Application.Exit to close your app.) If the main views thread is
terminated, the app closes.

Secondary views
Other views, including all views that you create by calling CreateNewView in your app code, are secondary views.
Both the main view and secondary views are stored in the CoreApplication.Views collection. Typically, you create
secondary views in response to a user action. In some instances, the system creates secondary views for your app.

NOTE
You can use the Windows assigned access feature to run an app in kiosk mode. When you do this, the system creates a
secondary view to present your app UI above the lock screen. App-created secondary views are not allowed, so if you try to
show your own secondary view in kiosk mode, an exception is thrown.

Switch from one view to another


Consider providing a way for the user to navigate from a secondary window back to its parent window. To do this,
use the ApplicationViewSwitcher.SwitchAsync method. You call this method from the thread of the window
you're switching from and pass the view ID of the window you're switching to.
await ApplicationViewSwitcher.SwitchAsync(viewIdToShow);

When you use SwitchAsync, you can choose if you want to close the initial window and remove it from the taskbar
by specifying the value of ApplicationViewSwitchingOptions.

Do's and don'ts


Do provide a clear entry point to the secondary view by utilizing the "open new window" glyph.
Do communicate the purpose of the secondary view to users.
Do ensure that your app works is fully functional in a single view and users will open a secondary view only for
convenience.
Don't rely on the secondary view to provide notifications or other transient visuals.

Related topics
ApplicationViewSwitcher
CreateNewView
Command design basics for UWP apps
5/22/2017 6 min to read Edit Online

In a Universal Windows Platform (UWP) app, command elements are the interactive UI elements that enable the
user to perform actions, such as sending an email, deleting an item, or submitting a form. This article describes the
command elements, such as buttons and check boxes, the interactions they support, and the command surfaces
(such as command bars and context menus) for hosting them.

Important APIs: ICommand interface, Button class, CommandBar class, MenuFlyout class

Provide the right type of interactions


When designing a command interface, the most important decision is choosing what users should be able to do.
For example, if you're creating a photo app, the user will need tools to edit their photos. However, if you're
creating a social media app that happens to display photos, image editing might not be a priority and so editing
tools can be omitted to save space. Decide what you want users to accomplish and provide the tools to help them
do it.
For recommendations about how to plan the right interactions for your app, see Plan your app.

Use the right command element for the interaction


Using the right elements for the right interactions can mean the difference between an app that feels intuitive to
use and one that seems difficult or confusing. The Universal Windows Platform (UWP) provides a large set of
command elements, in the form of controls, that you can use in your app. Here's a list of some of the most
common controls and a summary of the interactions they enable.

CATEGORY ELEMENTS INTERACTION

Buttons Button Triggers an immediate action, such as


sending an email, confirming an action
in a dialog, submitting form data.

Date and time pickers calendar date picker, calendar view, Enables the user to view and modify
date picker, time picker date and time info, such as when
entering a credit card expiration date or
setting an alarm.

Lists drop-down list, list box, list view and Presents items in a interactive list or a
grid view grid. Use these elements to let users
select a movie from a list of new
releases or manage an inventory.

Predictive text entry Auto-suggest box Saves users time when entering data or
performing queries by providing
suggestions as they type.

Selection controls check box, radio button, toggle switch Lets the user choose between different
options, such as when completing a
survey or configuring app settings.

For a complete list, see Controls and UI elements


Place commands on the right surface
You can place command elements on a number of surfaces in your app, including the app canvas (the content area
of your app) or special command elements that can act as command containers, such as command bars, menus,
dialogs, and flyouts. Here are some general recommendations for placing commands:
Whenever possible, let users directly manipulate the content on the app's canvas, rather than adding
commands that act on the content. For example, in the travel app, let users rearrange their itinerary by
dragging and dropping activities in a list on the canvas, rather than by selecting the activity and using Up or
Down command buttons.
Otherwise, place commands on one of these UI surfaces if users can't manipulate content directly:
In the command bar: You should put most commands on the command bar, which helps to organize
commands and makes them easy to access.
On the app's canvas: If the user is on a page or view that has a single purpose, you can provide
commands for that purpose directly on the canvas. There should be very few of these commands.
In a context menu: You can use context menus for clipboard actions (such as cut, copy, and paste), or for
commands that apply to content that cannot be selected (like adding a push pin to a location on a map).
Here's a list of the command surfaces that Windows provides and recommendations for when to use them.

SURFACE DESCRIPTION

App canvas (content area) If a command is critical and is constantly needed for the user
to complete the core scenarios, put it on the canvas (the
content area of your app). Because you can put commands
near (or on) the objects they affect, putting commands on the
canvas makes them easy and obvious to use.
However, choose the commands you put on the canvas
carefully. Too many commands on the app canvas takes
up valuable screen space and can overwhelm the user. If
the command won't be frequently used, consider putting
it in another command surface, such as menu or the
command bar's "More" area.

Command bar Command bars provide users with easy access to actions. You
can use a command bar to show commands or options that
are specific to the user's context, such as a photo selection or
drawing mode.
Command bars can be placed at the top of the screen, at
the bottom of the screen, or at both the top and bottom
of the screen. This design of a photo editing app shows
the content area and the command bar:

For more information about command bars, see the


Guidelines for command bar article.
Menus and context menus Sometimes it is more efficient to group multiple commands
into a command menu. Menus let you present more options
with less space. Menus can include interactive controls.
Context menus can provide shortcuts to commonly-used
actions and provide access to secondary commands that
are only relevant in certain contexts.
Context menus are for the following types of commands
and command scenarios:
Contextual actions on text selections, such as Copy,
Cut, Paste, Check Spelling, and so on.
Commands for an object that needs to be acted upon
but that can't be selected or otherwise indicated.
Showing clipboard commands.
Custom commands.
This example shows the design for a subway app that
uses a context menu to modify the route, bookmark a
route, or select another train.

For more info about context menus, see the Guidelines


for context menu article.

Dialog controls Dialogs are modal UI overlays that provide contextual app
information. In most cases, dialogs block interactions with the
app window until being explicitly dismissed, and often request
some kind of action from the user.
Dialogs can be disruptive and should only be used in
certain situations. For more info, see the When to confirm
or undo actions section.

Flyout A lightweight contextual popup that displays UI related to


what the user is doing. Use a flyout to:
Show a menu.
Show more detail about an item.
Ask the user to confirm an action without blocking
interaction with the app.
Flyouts can be dismissed by tapping or clicking
somewhere outside the flyout. For more info about flyout
controls, see the Dialogs and flyouts article.

When to confirm or undo actions


No matter how well-designed the user interface is and no matter how careful the user is, at some point, all users
will perform an action they wish they hadn't. Your app can help in these situations by requiring the user to confirm
an action, or by providing a way of undoing recent actions.
For actions that can't be undone and have major consequences, we recommend using a confirmation dialog.
Examples of such actions include:
Overwriting a file
Not saving a file before closing
Confirming permanent deletion of a file or data
Making a purchase (unless the user opts out of requiring a confirmation)
Submitting a form, such as signing up for something
For actions that can be undone, offering a simple undo command is usually enough. Examples of such actions
include:
Deleting a file
Deleting an email (not permanently)
Modifying content or editing text
Renaming a file

TIP
Be careful of how much your app uses confirmation dialogs; they can be very helpful when the user makes a mistake, but
they are a hindrance whenever the user is trying to perform an action intentionally.

Optimize for specific input types


See the Interaction primer for more detail on optimizing user experiences around a specific input type or device.
Content design basics for UWP apps
5/22/2017 3 min to read Edit Online

The main purpose of any app is to provide access to content: in a photo-editing app, the photo is the content; in a
travel app, maps and info about travel destinations is the content; and so on. Navigation elements provide access
to content; command elements enable the user to interact with content; content elements display the actual
content.
This article provides content design recommendations for the three content scenarios.

Design for the right content scenario


There are three main content scenarios:
Consumption: A primarily one-way experience where content is consumed. It includes tasks like reading,
listening to music, watching videos, and photo and image viewing.
Creation: A primarily one-way experience where the focus is creating new content. It can be broken down into
making things from scratch, like shooting a photo or video, creating a new image in a painting app, or opening
a fresh document.
Interactive: A two-way content experience that includes consuming, creating, and revising content.

Consumption-focused apps
Content elements receive the highest priority in a consumption-focused app, followed by the navigation elements
needed to help users find the content they want. Examples of consumption-focused apps include movie players,
reading apps, music apps, and photo viewers.

General recommendations for consumption-focused apps:


Consider creating dedicated navigation pages and content-viewing pages, so that when users find the content
they are looking for, they can view it on a dedicated page free of distractions.
Consider creating a full-screen view option that expands the content to fill the entire screen and hides all other
UI elements.
Creation-focused apps
Content and command elements are the most import UI elements in a creation-focused app: command elements
enable the user to create new content. Examples include painting apps, photo editing apps, video editing apps, and
word processing apps.
As an example, here's a design for a photo app that uses command bars to provide access to tools and photo
manipulation options. Because all the commands are in the command bar, the app can devote most of its screen
space to its content, the photo being edited.

General recommendations for creation-focused apps:


Minimize the use of navigation elements.
Command elements are especially important in creation-focused apps. Since users will be executing a lot of
commands, we recommend providing a command history/undo functionality.

Apps with interactive content


In an app with interactive content, users create, view, and edit content; many apps fit into this category. Examples of
these types of apps include line of business apps, inventory management apps, cooking apps that enable the user
to create or modify recipes.

These sort of apps need to balance all three UI elements:


Navigation elements help users find and view content. If viewing and finding content is the most important
scenario, prioritize navigation elements, filtering and sorting, and search.
Command elements let the user create, edit, and manipulate content.
General recommendations for apps with interactive content:
It can be difficult to balance navigation, content, and command elements when all three are important. If
possible, consider creating separate screens for browsing, creating, and editing content, or providing mode
switches.

Commonly used content elements


Here are some UI elements commonly used to display content. (For a complete list of UI elements, see Controls
and UI elements.)

CATEGORY ELEMENTS DESCRIPTION

Audio and video Media playback and transport controls Plays audio and video.

Image viewers Flip view, image Displays images. The flip view displays
images in a collection, such as photos in
an album or items in a product details
page, one image at a time.

Lists drop-down list, list box, list view and Presents items in an interactive list or a
grid view grid. Use these elements to let users
select a movie from a list of new
releases or manage an inventory.

Text and text input Text block, text box, rich edit box Displays text. Some elements enable
the user to edit text. For more info, see
Text controls
Screen sizes and break points for responsive design
8/30/2017 2 min to read Edit Online

The number of device targets and screen sizes across the Windows 10 ecosystem is too great to worry about
optimizing your UI for each one. Instead, we recommended designing for a few key widths (also called
"breakpoints"): 360, 640, 1024 and 1366 epx.

TIP
When designing for specific breakpoints, design for the amount of screen space available to your app (the app's window).
When the app is running full-screen, the app window is the same size as the screen, but in other cases, it's smaller.

Breakpoints
This table describes the different size classes and provides general recommendations for tailoring for those size
classes.

SIZE CLASS SMALL MEDIUM LARGE

Typical screen size (diagonal) 4" to 6" 7" to 12", or TVs 13" and larger

Typical devices Phones Phablets, tablets, TVs PCs, laptops, Surface Hubs

Common window sizes in 320x569, 360x640, 480x854 960x540, 1024x640 1366x768, 1920x1080
effective pixels

Window width breakpoints 640px or less 641px to 1007px 1008px or greater


in effective pixels
SIZE CLASS SMALL MEDIUM LARGE

General recommendations Set left and right Set left and right Set left and right
window margins to window margins to window margins to
12px to create a 24px to create a 24px to create a
visual separation visual separation visual separation
between the left and between the left and between the left and
right edges of the right edges of the right edges of the
app window. app window. app window.
Dock app bars to the Put command Put command
bottom of the elements like app elements like app
window for improved bars at the top of the bars at the top of the
reachability app window. app window.
Use one Up to two Up to three
column/region at a columns/regions columns/regions
time Show the search box. Show the search box.
Use an icon to Put the navigation Put the navigation
represent search pane into sliver pane into docked
(don't show a search mode so a narrow mode so that it
box). strip of icons always always shows.
Put the navigation shows.
pane in overlay Consider further
mode to conserve tailoring for TV
screen space. experiences.
If you're using the
master details
pattern, use the
stacked presentation
mode to save screen
space.

With Continuum for Phones, users can connect compatible Windows 10 mobile devices to a monitor, mouse
and keyboard to make their phones work like laptops. Keep this new capability in mind when designing for specific
breakpoints - a mobile phone will not always stay in the small size class.

Effective pixels and scale factor


The scale factor determines the size of text and UI elements on the screen. Larger values increase the number of
pixels the system uses to draw certain UI elements. Windows automatically selects a scale factor for each display
based on its DPI (dots-per-inch) and the viewing distance of the device. Users can override the default value and
by going to Settings > Display > Scale and layout settings page.
Define page layouts with XAML
5/22/2017 21 min to read Edit Online

XAML gives you a flexible layout system that lets you use automatic sizing, layout panels, visual states, and even
separate UI definitions to create a responsive UI. With a flexible design, you can make your app look great on
screens with different app window sizes, resolutions, pixel densities, and orientations.
Here, we discuss how to use XAML properties and layout panels to make your app responsive and adaptive. We
build on important info about responsive UI design and techniques found in Introduction to UWP app design. You
should understand what effective pixels are and understand each of the responsive design techniques: Reposition,
Resize, Reflow, Reveal, Replace, and Re-architect.

NOTE
Your app layout begins with the navigation model you choose, like whether to use a Pivot with the tabs and pivot model or
SplitView with the nav pane model. For more info about that, see Navigation design basics for UWP apps. Here, we talk
about techniques to make the layout of a single page or group of elements responsive. This info is applicable regardless of
which navigation model you choose for your app.

The XAML framework provides several levels of optimization you can use to create a responsive UI.
Fluid layout Use layout properties and panels to make your default UI fluid.
The foundation of a responsive layout is the appropriate use of layout properties and panels to reposition,
resize, and reflow content. You can set a fixed size on an element, or use automatic sizing to let the parent
layout panel size it. The various Panel classes, such as Canvas, Grid, RelativePanel and StackPanel,
provide different ways to size and position their children.
Adaptive layout Use visual states to make significant alterations to your UI based on window size or other
changes.
When your app window grows or shrinks beyond a certain amount, you might want to alter layout
properties to reposition, resize, reflow, reveal, or replace sections of your UI. You can define different visual
states for your UI, and apply them when the window width or window height crosses a specified threshold.
An AdaptiveTrigger provides an easy way to set the threshold (also called 'breakpoint') where a state is
applied.
Tailored layout A tailored layout is optimized for a specific device family or range of screen sizes. Within
the device family, the layout should still respond and adapt to changes within the range of supported
window sizes.

Note With Continuum for Phones, users can connect their phones to a monitor, mouse, and keyboard.
This capability blurs the lines between phone and desktop device families.

Approaches to tailoring include


Create custom trigger
You can create a device family trigger and modify its setters, as for adaptive triggers.
Use separate XAML files to define distinct views for each device family.
You can use separate XAML files with the same code file to define per-device family views of the UI.
Use separate XAML and code to provide different implementations for each device family.
You can provide different implementations of a page (XAML and code), then navigate to a particular
implementation based on the device family, screen size, or other factors.

Layout properties and panels


Layout is the process of sizing and positioning objects in your UI. To position visual objects, you must put them in a
panel or other container object. The XAML framework provides various panel classes, such as Canvas, Grid,
RelativePanel and StackPanel, which serve as containers and enable you to position and arrange the UI elements
within them.
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 clipped across different form factors and display sizes.
Fluid layouts shrink, grow, and reflow to respond to the visual space available on a device. To create a fluid layout,
use automatic or proportional sizing for elements, alignment, margins, and padding, and let layout panels position
their children as needed. You arrange child elements by specifying how they should be arranged in relationship to
each other, and how they should be sized relative to their content and/or their parent.
In practice, you use a combination of static and fluid elements to create your UI. You still use static elements and
values in some places, but make sure that the overall UI is responsive and adapts to different resolutions, layouts,
and views.
Layout properties
To control the size and position of an element, you set its layout properties. Here are some common layout
properties and their effect.
Height and Width
Set the Height and Width properties to specify the size of an element. You can use fixed values measured in
effective pixels, or you can use auto or proportional sizing. To get the size of an element at runtime, use the
ActualHeight and ActualWidth properties instead of Height and Width.
You use auto sizing to let UI elements resize to fit their content or parent container. You can also use auto sizing
with the rows and columns of a grid. To use auto sizing, set the Height and/or Width of UI elements to Auto.

NOTE
Whether an element resizes to its content or its container depends on the value of its HorizontalAlignment and
VerticalAlignment properties, and how the parent container handles sizing of its children. For more info, see and later in
Alignmentpanels
Layout

this article.

You use proportional sizing, also called star sizing, to distribute available space among the rows and columns of a
grid by weighted proportions. In XAML, star values are expressed as * (or n* for weighted star sizing). For example,
to specify that one column is 5 times wider than the second column in a 2-column layout, use "5*" and "*" for the
Width properties in the ColumnDefinition elements.
This example combines fixed, auto, and proportional sizing in a Grid with 4 columns.

Column_1 Auto The column will size to fit its content.


Column_2 * After the Auto columns are calculated,
the column gets part of the remaining
width. Column_2 will be one-half as
wide as Column_4.

Column_3 44 The column will be 44 pixels wide.

Column_4 2* After the Auto columns are calculated,


the column gets part of the remaining
width. Column_4 will be twice as wide as
Column_2.

The default column width is "*", so you don't need to explicitly set this value for the second column.

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="44"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Column 1 sizes to its conent." FontSize="24"/>
</Grid>

In the Visual Studio XAML designer, the result looks like this.

Size constraints
When you use auto sizing in your UI, you might still need to place constraints on the size of an element. You can set
the MinWidth/MaxWidth and MinHeight/MaxHeight properties to specify values that constrain the size of an
element while allowing fluid resizing.
In a Grid, MinWidth/MaxWidth can also be used with column definitions, and MinHeight/MaxHeight can be used
with row definitions.
Alignment
Use the HorizontalAlignment and VerticalAlignment properties to specify how an element should be
positioned within its parent container.
The values for HorizontalAlignment are Left, Center, Right, and Stretch.
The values for VerticalAlignment are Top, Center, Bottom, and Stretch.
With the Stretch alignment, elements fill all the space they're provided in the parent container. Stretch is the
default for both alignment properties. However, some controls, like Button, override this value in their default
style. Any element that can have child elements can treat the Stretch value for HorizontalAlignment and
VerticalAlignment properties uniquely. For example, an element using the default Stretch values placed in a Grid
stretches to fill the cell that contains it. The same element placed in a Canvas sizes to its content. For more info
about how each panel handles the Stretch value, see the Layout panels article.
For more info, see the Alignment, margin, and padding article, and the HorizontalAlignment and
VerticalAlignment reference pages.
Controls also have HorizontalContentAlignment and VerticalContentAlignment properties that you use to
specify how they position their content. Not all controls make use of these properties. They only affect layout
behavior for a control when its template uses the properties as the source of a
HorizontalAlignment/VerticalAlignment value for presenters or content areas within it.
For TextBlock, TextBox, and RichTextBlock, use the TextAlignment property to control the alignment of text in the
control.
Margins and padding
Set the Margin property to control the amount of empty space around an element. Margin does not add pixels to
the ActualHeight and ActualWidth, and is also not considered part of the element for purposes of hit testing and
sourcing input events.
Set the Padding property to control the amount of space between the inner border of an element and its content.
A positive Padding value decreases the content area of the element.
This diagram shows how Margin and Padding are applied to an element.

The left, right, top, and bottom values for Margin and Padding do not need to be symmetrical, and they can be set
to negative values. For more info, see Alignment, margin, and padding, and the Margin or Padding reference
pages.
Let's look at the effects of Margin and Padding on real controls. Heres a TextBox inside of a Grid with the default
Margin and Padding values of 0.

Heres the same TextBox and Grid with Margin and Padding values on the TextBox as shown in this XAML.
<Grid BorderBrush="Blue" BorderThickness="4" Width="200">
<TextBox Text="This is text in a TextBox." Margin="20" Padding="24,16"/>
</Grid>

Visibility
You can reveal or hide an element by setting its Visibility property to one of the Visibility enumeration values:
Visible or Collapsed. When an element is Collapsed, it doesn't take up any space in the UI layout.
You can change an element's Visibility property in code or in a visual state. When the Visibility of an element is
changed, all of its child elements are also changed. You can replace sections of your UI by revealing one panel
while collapsing another.

Tip When you have elements in your UI that are Collapsed by default, the objects are still created at startup,
even though they aren't visible. You can defer loading these elements until they are shown by setting the
x:DeferLoadStrategy attribute to "Lazy". This can improve startup performance. For more info, see
x:DeferLoadStrategy attribute.

Style resources
You don't have to set each property value individually on a control. It's typically more efficient to group property
values into a Style resource and apply the Style to a control. This is especially true when you need to apply the
same property values to many controls. For more info about using styles, see Styling controls.
Layout panels
Most app content can be organized into some form of groupings or hierarchies. You use layout panels to group
and arrange UI elements in your app. The main thing to consider when choosing a layout panel is how the panel
positions and sizes its child elements. You might also need to consider how overlapping child elements are layered
on top of each other.
Here's a comparison of the main features of the panel controls provided in the XAML framework.

PANEL CONTROL DESCRIPTION

Canvas Canvas doesnt support fluid UI; you control all aspects of
positioning and sizing child elements. You typically use it for
special cases like creating graphics or to define small static
areas of a larger adaptive UI. You can use code or visual states
to reposition elements at runtime.
Elements are positioned absolutely using Canvas.Top and
Canvas.Left attached properties.
Layering can be explicitly specified using the Canvas.ZIndex
attached property.
Stretch values for HorizontalAlignment/VerticalAlignment
are ignored. If an element's size is not set explicitly, it sizes to
its content.
Child content is not visually clipped if larger than the panel.
Child content is not constrained by the bounds of the
panel.
PANEL CONTROL DESCRIPTION

Grid Grid supports fluid resizing of child elements. You can use
code or visual states to reposition and reflow elements.
Elements are arranged in rows and columns using Grid.Row
and Grid.Column attached properties.
Elements can span multiple rows and columns using
Grid.RowSpan and Grid.ColumnSpan attached properties.
Stretch values for HorizontalAlignment/VerticalAlignment
are respected. If an element's size is not set explicitly, it
stretches to fill the available space in the grid cell.
Child content is visually clipped if larger than the panel.
Content size is constrained by the bounds of the panel, so
scrollable content shows scroll bars if needed.

RelativePanel Elements are arranged in relation to the edge or center of


the panel, and in relation to each other.
Elements are positioned using a variety of attached
properties that control panel alignment, sibling alignment, and
sibling position.
Stretch values for HorizontalAlignment/VerticalAlignment
are ignored unless RelativePanel attached properties for
alignment cause stretching (for example, an element is aligned
to both the right and left edges of the panel). If an element's
size is not set explicitly and it's not stretched, it sizes to its
content.
Child content is visually clipped if larger than the panel.
Content size is constrained by the bounds of the panel, so
scrollable content shows scroll bars if needed.

StackPanel Elements are stacked in a single line either vertically or


horizontally.
Stretch values for HorizontalAlignment/VerticalAlignment
are respected in the direction opposite the Orientation
property. If an element's size is not set explicitly, it stretches to
fill the available width (or height if the Orientation is
Horizontal). In the direction specified by the Orientation
property, an element sizes to its content.
Child content is visually clipped if larger than the panel.
Content size is not constrained by the bounds of the panel
in the direction specified by the Orientation property, so
scrollable content stretches beyond the panel bounds and
doesn't show scrollbars. You must explicitly constrain the
height (or width) of the child content to make its scrollbars
show.

VariableSizedWrapGrid Elements are arranged in rows or columns that


automatically wrap to a new row or column when the
MaximumRowsOrColumns value is reached.
Whether elements are arranged in rows or columns is
specified by the Orientation property.
Elements can span multiple rows and columns using
VariableSizedWrapGrid.RowSpan and
VariableSizedWrapGrid.ColumnSpan attached properties.
Stretch values for HorizontalAlignment/VerticalAlignment
are ignored. Elements are sized as specified by the ItemHeight
and ItemWidth properties. If these properties are not set, the
item in the first cell sizes to its content, and all other cells
inherit this size.
Child content is visually clipped if larger than the panel.
Content size is constrained by the bounds of the panel, so
scrollable content shows scroll bars if needed.
For detailed information and examples of these panels, see Layout panels. Also, see the Responsive techniques
sample.
Layout panels let you organize your UI into logical groups of controls. When you use them with appropriate
property settings, you get some support for automatic resizing, repositioning, and reflowing of UI elements.
However, most UI layouts need further modification when there are significant changes to the window size. For
this, you can use visual states.

Visual states and state triggers


Use visual states to reposition, resize, reflow, reveal, or replace sections of your UI based on screen size or other
factors. A VisualState defines property values that are applied to an element when its in a particular state. You
group visual states in a VisualStateManager that applies the appropriate VisualState when the specified
conditions are met.
Set visual states in code
To apply a visual state from code, you call the VisualStateManager.GoToState method. For example, to apply a
state when the app window is a particular size, handle the SizeChanged event and call GoToState to apply the
appropriate state.
Here, a VisualStateGroup contains 2 VisualState definitions. The first, DefaultState , is empty. When it's applied, the
values defined in the XAML page are applied. The second, WideState , changes the DisplayMode property of the
SplitView to Inline and opens the pane. This state is applied in the SizeChanged event handler if the window
width is 720 effective pixels or greater.
<Page ...>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultState">
<Storyboard>
</Storyboard>
</VisualState>

<VisualState x:Name="WideState">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="SplitView.DisplayMode"
Storyboard.TargetName="mySplitView">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SplitViewDisplayMode>Inline</SplitViewDisplayMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="SplitView.IsPaneOpen"
Storyboard.TargetName="mySplitView">
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<SplitView x:Name="mySplitView" DisplayMode="CompactInline"


IsPaneOpen="False" CompactPaneLength="20">
<!-- SplitView content -->

<SplitView.Pane>
<!-- Pane content -->
</SplitView.Pane>
</SplitView>
</Grid>
</Page>

private void CurrentWindow_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)


{
if (e.Size.Width >= 720)
VisualStateManager.GoToState(this, "WideState", false);
else
VisualStateManager.GoToState(this, "DefaultState", false);
}

Set visual states in XAML markup


Prior to Windows 10, VisualState definitions required Storyboard objects for property changes, and you had to
call GoToState in code to apply the state. This is shown in the previous example. You will still see many examples
that use this syntax, or you might have existing code that uses it.
Starting in Windows 10, you can use the simplified Setter syntax shown here, and you can use a StateTrigger in
your XAML markup to apply the state. You use state triggers to create simple rules that automatically trigger visual
state changes in response to an app event.
This example does the same thing as the previous example, but uses the simplified Setter syntax instead of a
Storyboard to define property changes. And instead of calling GoToState, it uses the built in AdaptiveTrigger state
trigger to apply the state. When you use state triggers, you don't need to define an empty DefaultState . The default
settings are reapplied automatically when the conditions of the state trigger are no longer met.
<Page ...>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<!-- VisualState to be triggered when the
window width is >=720 effective pixels. -->
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>

<VisualState.Setters>
<Setter Target="mySplitView.DisplayMode" Value="Inline"/>
<Setter Target="mySplitView.IsPaneOpen" Value="True"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<SplitView x:Name="mySplitView" DisplayMode="CompactInline"


IsPaneOpen="False" CompactPaneLength="20">
<!-- SplitView content -->

<SplitView.Pane>
<!-- Pane content -->
</SplitView.Pane>
</SplitView>
</Grid>
</Page>

Important In the previous example, the VisualStateManager.VisualStateGroups attached property is set on the
Grid element. When you use StateTriggers, always ensure that VisualStateGroups is attached to the first child
of the root in order for the triggers to take effect automatically. (Here, Grid is the first child of the root Page
element.)

Attached property syntax


In a VisualState, you typically set a value for a control property, or for one of the attached properties of the panel
that contains the control. When you set an attached property, use parentheses around the attached property name.
This example shows how to set the RelativePanel.AlignHorizontalCenterWithPanel attached property on a
TextBox named myTextBox . The first XAML uses ObjectAnimationUsingKeyFrames syntax and the second uses
Setter syntax.

<!-- Set an attached property using ObjectAnimationUsingKeyFrames. -->


<ObjectAnimationUsingKeyFrames
Storyboard.TargetProperty="(RelativePanel.AlignHorizontalCenterWithPanel)"
Storyboard.TargetName="myTextBox">
<DiscreteObjectKeyFrame KeyTime="0" Value="True"/>
</ObjectAnimationUsingKeyFrames>

<!-- Set an attached property using Setter. -->


<Setter Target="myTextBox.(RelativePanel.AlignHorizontalCenterWithPanel)" Value="True"/>

Custom state triggers


You can extend the StateTrigger class to create custom triggers for a wide range of scenarios. For example, you
can create a StateTrigger to trigger different states based on input type, then increase the margins around a control
when the input type is touch. Or create a StateTrigger to apply different states based on the device family the app is
run on. For examples of how to build custom triggers and use them to create optimized UI experiences from within
a single XAML view, see the State triggers sample.
Visual states and styles
You can use Style resources in visual states to apply a set of property changes to multiple controls. For more info
about using styles, see Styling controls.
In this simplified XAML from the State triggers sample, a Style resource is applied to a Button to adjust the size and
margins for mouse or touch input. For the complete code and the definition of the custom state trigger, see the
State triggers sample.
<Page ... >
<Page.Resources>
<!-- Styles to be used for mouse vs. touch/pen hit targets -->
<Style x:Key="MouseStyle" TargetType="Rectangle">
<Setter Property="Margin" Value="5" />
<Setter Property="Height" Value="20" />
<Setter Property="Width" Value="20" />
</Style>
<Style x:Key="TouchPenStyle" TargetType="Rectangle">
<Setter Property="Margin" Value="15" />
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="40" />
</Style>
</Page.Resources>

<RelativePanel>
<!-- ... -->
<Button Content="Color Palette Button" x:Name="MenuButton">
<Button.Flyout>
<Flyout Placement="Bottom">
<RelativePanel>
<Rectangle Name="BlueRect" Fill="Blue"/>
<Rectangle Name="GreenRect" Fill="Green" RelativePanel.RightOf="BlueRect" />
<!-- ... -->
</RelativePanel>
</Flyout>
</Button.Flyout>
</Button>
<!-- ... -->
</RelativePanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="InputTypeStates">
<!-- Second set of VisualStates for building responsive UI optimized for input type.
Take a look at InputTypeTrigger.cs class in CustomTriggers folder to see how this is implemented. -->
<VisualState>
<VisualState.StateTriggers>
<!-- This trigger indicates that this VisualState is to be applied when MenuButton is invoked using a mouse. -->
<triggers:InputTypeTrigger TargetElement="{x:Bind MenuButton}" PointerType="Mouse" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="BlueRect.Style" Value="{StaticResource MouseStyle}" />
<Setter Target="GreenRect.Style" Value="{StaticResource MouseStyle}" />
<!-- ... -->
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<!-- Multiple trigger statements can be declared in the following way to imply OR usage.
For example, the following statements indicate that this VisualState is to be applied when MenuButton is invoked using Touch OR
Pen.-->
<triggers:InputTypeTrigger TargetElement="{x:Bind MenuButton}" PointerType="Touch" />
<triggers:InputTypeTrigger TargetElement="{x:Bind MenuButton}" PointerType="Pen" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="BlueRect.Style" Value="{StaticResource TouchPenStyle}" />
<Setter Target="GreenRect.Style" Value="{StaticResource TouchPenStyle}" />
<!-- ... -->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Page>

Tailored layouts
When you make significant changes to your UI layout on different devices, you might find it more convenient to
define a separate UI file with a layout tailored to the device, rather than adapting a single UI. If the functionality is
the same across devices, you can define separate XAML views that share the same code file. If both the view and
the functionality differ significantly across devices, you can define separate Pages, and choose which Page to
navigate to when the app is loaded.
Separate XAML views per device family
Use XAML views to create different UI definitions that share the same code-behind. You can provide a unique UI
definition for each device family. Follow these steps to add a XAML view to your app.
To add a XAML view to an app
1. Select Project > Add New Item. The Add New Item dialog box opens. > Tip Make sure a folder or the project,
and not the solution, is selected in Solution Explorer.
2. Under Visual C# or Visual Basic in the left pane, pick the XAML template type.
3. In the center pane, pick XAML View.
4. Enter the name for the view. The view must be named correctly. For more info on naming, see the remainder of
this section.
5. Click Add. The file is added to the project.
The previous steps create only a XAML file, but not an associated code-behind file. Instead, the XAML view is
associated with an existing code-behind file using a "DeviceName" qualifier that's part of the file or folder name.
This qualifier name can be mapped to a string value that represents the device family of the device that your app is
currently running on, such as, "Desktop", "Mobile", and the names of the other device families (see
ResourceContext.QualifierValues).
You can add the qualifier to the file name, or add the file to a folder that has the qualifier name.
Use file name
To use the qualifier name with the file, use this format: [pageName].DeviceFamily-[qualifierString].xaml.
Let's look at an example for a file named MainPage.xaml. To create a view for mobile devices, name the XAML view
MainPage.DeviceFamily-Mobile.xaml. To create a view for PC devices, name the view MainPage.DeviceFamily-
Desktop.xaml. Here's what the solution looks like in Microsoft Visual Studio.

Use folder name


To organize the views in your Visual Studio project using folders, you can use the qualifier name with the folder. To
do so, name your folder like this: DeviceFamily-[qualifierString]. In this case, each XAML view file has the same
name. Don't include the qualifier in the file name.
Here's an example, again for a file named MainPage.xaml. To create a view for mobile devices, create a folder
named "DeviceFamily-Mobile", and place a XAML view named MainPage.xaml into it. To create a view for PC
devices, create a folder named "DeviceFamily-Desktop", and place another XAML view named MainPage.xaml into
it. Here's what the solution looks like in Visual Studio.
In both cases, a unique view is used for mobile and PC devices. The default MainPage.xaml file is used if the device
it's running on doesn't match any of the device family specific views.
Separate XAML pages per device family
To provide unique views and functionality, you can create separate Page files (XAML and code), and then navigate
to the appropriate page when the page is needed.
To add a XAML page to an app
1. 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.
2. Under Visual C# or Visual Basic in the left pane, pick the XAML template type.
3. In the center pane, pick Blank page.
4. Enter the name for the page. For example, "MainPage_Mobile". Both a MainPage_Mobile.xaml and
MainPage_Mobile.xaml.cs/vb/cpp code file are created.
5. Click Add. The file is added to the project.
At runtime, check the device family that the app is running on, and navigate to the correct page like this.

if (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile")
{
rootFrame.Navigate(typeof(MainPage_Mobile), e.Arguments);
}
else
{
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}

You can also use different criteria to determine which page to navigate to. For more examples, see the Tailored
multiple views sample, which uses the GetIntegratedDisplaySize function to check the physical size of an
integrated display.

Sample code
XAML UI basics sample
See all of the XAML controls in an interactive format.
Layout panels
5/22/2017 7 min to read Edit Online

You use layout panels to arrange and group UI elements in your app. The built-in XAML layout panels include
RelativePanel, StackPanel, Grid, VariableSizedWrapGrid, and Canvas. Here, we describe each panel and show
how to use it to layout XAML UI elements.
There are several things to consider when choosing a layout panel:
How the panel positions its child elements.
How the panel sizes its child elements.
How overlapping child elements are layered on top of each other (z-order).
The number and complexity of nested panel elements needed to create your desired layout.
Panel attached properties
Most XAML layout panels use attached properties to let their child elements inform the parent panel about how
they should be positioned in the UI. Attached properties use the syntax AttachedPropertyProvider.PropertyName.
If you have panels that are nested inside other panels, attached properties on UI elements that specify layout
characteristics to a parent are interpreted by the most immediate parent panel only.
Here is an example of how you can set the Canvas.Left attached property on a Button control in XAML. This
informs the parent Canvas that the Button should be positioned 50 effective pixels from the left edge of the
Canvas.

<Canvas>
<Button Canvas.Left="50">Hello</Button>
</Canvas>

For more info about attached properties, see Attached properties overview.

Note An attached property is a XAML concept that requires special syntax to get or set from code. To use
attached properties in code, see the Attached properties in code section of the Attached properties overview
article.

Panel borders
The RelativePanel, StackPanel, and Grid panels define border properties that let you draw a border around the
panel without wrapping them in an additional Border element. The border properties are BorderBrush,
BorderThickness, CornerRadius, and Padding.
Heres an example of how to set border properties on a Grid.

<Grid BorderBrush="Blue" BorderThickness="12" CornerRadius="12" Padding="12">


<TextBlock Text="Hello World!"/>
</Grid>
Using the built-in border properties reduces the XAML element count, which can improve the UI performance of
your app. For more info about layout panels and UI performance, see Optimize your XAML layout.

RelativePanel
RelativePanel lets you layout UI elements by specifying where they go in relation to other elements and in
relation to the panel. By default, an element is positioned in the upper left corner of the panel. You can use
RelativePanel with a VisualStateManager and AdaptiveTriggers to rearrange your UI for different window
sizes.
This table shows the attached properties you can use to align an element with the edge or center of the panel, and
align and position it in relation to other elements.

PANEL ALIGNMENT SIBLING ALIGNMENT SIBLING POSITION

AlignTopWithPanel AlignTopWith Above

AlignBottomWithPanel AlignBottomWith Below

AlignLeftWithPanel AlignLeftWith LeftOf

AlignRightWithPanel AlignRightWith RightOf

AlignHorizontalCenterWithPanel AlignHorizontalCenterWith

AlignVerticalCenterWithPanel AlignVerticalCenterWith

This XAML shows how to arrange elements in a RelativePanel.

<RelativePanel BorderBrush="Gray" BorderThickness="1">


<Rectangle x:Name="RedRect" Fill="Red" Height="44" Width="44"/>
<Rectangle x:Name="BlueRect" Fill="Blue"
Height="44" Width="88"
RelativePanel.RightOf="RedRect" />

<Rectangle x:Name="GreenRect" Fill="Green"


Height="44"
RelativePanel.Below="RedRect"
RelativePanel.AlignLeftWith="RedRect"
RelativePanel.AlignRightWith="BlueRect"/>
<Rectangle Fill="Orange"
RelativePanel.Below="GreenRect"
RelativePanel.AlignLeftWith="BlueRect"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.AlignBottomWithPanel="True"/>
</RelativePanel>

The result looks like this.


Here are a few thing to note about the sizing of the rectangles.
The red rectangle is given an explicit size of 44x44. It's placed in the upper left corner of the panel, which is the
default position.
The green rectangle is given an explicit height of 44. Its left side is aligned with the red rectangle, and its right
side is aligned with the blue rectangle, which determines its width.
The orange rectangle isn't given an explicit size. Its left side is aligned with the blue rectangle. Its right and
bottom edges are aligned with the edge of the panel. Its size is determined by these alignments and it will
resize as the panel resizes.

StackPanel
StackPanel is a simple layout panel that arranges its child elements into a single line that can be oriented
horizontally or vertically. StackPanel controls are typically used in scenarios where you want to arrange a small
subsection of the UI on your page.
You can use the Orientation property to specify the direction of the child elements. The default orientation is
Vertical.
The following XAML shows how to create a vertical StackPanel of items.

<StackPanel>
<Rectangle Fill="Red" Height="44"/>
<Rectangle Fill="Blue" Height="44"/>
<Rectangle Fill="Green" Height="44"/>
<Rectangle Fill="Orange" Height="44"/>
</StackPanel>

The result looks like this.

In a StackPanel, if a child element's size is not set explicitly, it stretches to fill the available width (or height if the
Orientation is Horizontal). In this example, the width of the rectangles is not set. The rectangles expand to fill the
entire width of the StackPanel.

Grid
The Grid panel supports arranging controls in multi-row and multi-column layouts. You can specify a Grid panel's
rows and columns by using the RowDefinitions and ColumnDefinitions properties. In XAML, use property
element syntax to declare the rows and columns within the Grid element. You can distribute space within a column
or a row by using Auto or star sizing.
You position objects in specific cells of the Grid by using the Grid.Column and Grid.Row attached properties.
You can make content span across multiple rows and columns by using the Grid.RowSpan and
Grid.ColumnSpan attached properties.
This XAML example shows how to create a Grid with two rows and two columns.

<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="44"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Red" Width="44"/>
<Rectangle Fill="Blue" Grid.Row="1"/>
<Rectangle Fill="Green" Grid.Column="1"/>
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1"/>
</Grid>

The result looks like this.

In this example, the sizing works like this:


The second row has an explicit height of 44 effective pixels. By default, the height of the first row fills whatever
space is left over.
The width of the first column is set to Auto, so it's as wide as needed for its children. In this case, it's 44
effective pixels wide to accommodate the width of the red rectangle.
There are no other size constraints on the rectangles, so each one stretches to fill the grid cell it's in.

VariableSizedWrapGrid
VariableSizedWrapGrid provides a grid-style layout panel where elements are arranged in rows or columns that
automatically wrap to a new row or column when the MaximumRowsOrColumns value is reached.
The Orientation property specifies whether the grid adds its items in rows or columns before wrapping. The
default orientation is Vertical, which means the grid adds items from top to bottom until a column is full, then
wraps to a new column. When the value is Horizontal, the grid adds items from left to right, then wraps to a new
row.
Cell dimensions are specified by the ItemHeight and ItemWidth. Each cell is the same size. If ItemHeight or
ItemWidth is not specified, then the first cell sizes to fit its content, and every other cell is the size of the first cell.
You can use the VariableSizedWrapGrid.ColumnSpan and VariableSizedWrapGrid.RowSpan attached
properties to specify how many adjacent cells a child element should fill.
Here's how to use a VariableSizedWrapGrid in XAML.

<VariableSizedWrapGrid MaximumRowsOrColumns="3" ItemHeight="44" ItemWidth="44">


<Rectangle Fill="Red"/>
<Rectangle Fill="Blue"
VariableSizedWrapGrid.RowSpan="2"/>
<Rectangle Fill="Green"
VariableSizedWrapGrid.ColumnSpan="2"/>
<Rectangle Fill="Orange"
VariableSizedWrapGrid.RowSpan="2"
VariableSizedWrapGrid.ColumnSpan="2"/>
</VariableSizedWrapGrid>

The result looks like this.

In this example, the maximum number of rows in each column is 3. The first column contains only 2 items (the red
and blue rectangles) because the blue rectangle spans 2 rows. The green rectangle then wraps to the top of the
next column.

Canvas
The Canvas panel positions its child elements using fixed coordinate points. You specify the points on individual
child elements by setting the Canvas.Left and Canvas.Top attached properties on each element. During layout,
the parent Canvas reads these attached property values from its children and uses these values during the Arrange
pass of layout.
Objects in a Canvas can overlap, where one object is drawn on top of another object. By default, the Canvas
renders child objects in the order in which theyre declared, so the last child is rendered on top (each element has a
default z-index of 0). This is the same as other built-in panels. However, Canvas also supports the Canvas.ZIndex
attached property that you can set on each of the child elements. You can set this property in code to change the
draw order of elements during run time. The element with the highest Canvas.ZIndex value draws last and
therefore draws over any other elements that share the same space or overlap in any way. Note that alpha value
(transparency) is respected, so even if elements overlap, the contents shown in overlap areas might be blended if
the top one has a non-maximum alpha value.
The Canvas does not do any sizing of its children. Each element must specify its size.
Here's an example of a Canvas in XAML.

<Canvas Width="120" Height="120">


<Rectangle Fill="Red" Height="44" Width="44"/>
<Rectangle Fill="Blue" Height="44" Width="44" Canvas.Left="20" Canvas.Top="20"/>
<Rectangle Fill="Green" Height="44" Width="44" Canvas.Left="40" Canvas.Top="40"/>
<Rectangle Fill="Orange" Height="44" Width="44" Canvas.Left="60" Canvas.Top="60"/>
</Canvas>

The result looks like this.


Use the Canvas panel with discretion. While it's convenient to be able to precisely control positions of elements in
UI for some scenarios, a fixed positioned layout panel causes that area of your UI to be less adaptive to overall app
window size changes. App window resize might come from device orientation changes, split app windows,
changing monitors, and a number of other user scenarios.

Panels for ItemsControl


There are several special-purpose panels that can be used only as an ItemsPanel to display items in an
ItemsControl. These are ItemsStackPanel, ItemsWrapGrid, VirtualizingStackPanel, and WrapGrid. You can't
use these panels for general UI layout.
XAML custom panels overview
5/22/2017 18 min to read Edit Online

A panel is an object that provides a layout behavior for child elements it contains, when the Extensible Application
Markup Language (XAML) layout system runs and your app UI is rendered.

Important APIs
Panel
ArrangeOverride
MeasureOverride

You can define custom panels for XAML layout by deriving a custom class from the Panel class. You provide
behavior for your panel by overriding the MeasureOverride and ArrangeOverride, supplying logic that measures
and arranges the child elements.

The Panel base class


To define a custom panel class, you can either derive from the Panel class directly, or derive from one of the
practical panel classes that aren't sealed, such as Grid or StackPanel. It's easier to derive from Panel, because it
can be difficult to work around the existing layout logic of a panel that already has layout behavior. Also, a panel
with behavior might have existing properties that aren't relevant for your panel's layout features.
From Panel, your custom panel inherits these APIs:
The Children property.
The Background, ChildrenTransitions and IsItemsHost properties, and the dependency property identifiers.
None of these properties are virtual, so you don't typically override or replace them. You don't typically need
these properties for custom panel scenarios, not even for reading values.
The layout override methods MeasureOverride and ArrangeOverride. These were originally defined by
FrameworkElement. The base Panel class doesn't override these, but practical panels like Grid do have
override implementations that are implemented as native code and are run by the system. Providing new (or
additive) implementations for ArrangeOverride and MeasureOverride is the bulk of the effort you need to
define a custom panel.
All the other APIs of FrameworkElement, UIElement and DependencyObject, such as Height, Visibility and
so on. You sometimes reference values of these properties in your layout overrides, but they aren't virtual so
you don't typically override or replace them.
This focus here is to describe XAML layout concepts, so you can consider all the possibilities for how a custom
panel can and should behave in layout. If you'd rather jump right in and see an example custom panel
implementation, see BoxPanel, an example custom panel.

The Children property


The Children property is relevant to a custom panel because all classes derived from Panel use the Children
property as the place to store their contained child elements in a collection. Children is designated as the XAML
content property for the Panel class, and all classes derived from Panel can inherit the XAML content property
behavior. If a property is designated the XAML content property, that means that XAML markup can omit a property
element when specifying that property in markup, and the values are set as immediate markup children (the
"content"). For example, if you derive a class named CustomPanel from Panel that defines no new behavior, you
can still use this markup:

<local:CustomPanel>
<Button Name="button1"/>
<Button Name="button2"/>
</local:CustomPanel>

When a XAML parser reads this markup, Children is known to be the XAML content property for all Panel derived
types, so the parser will add the two Button elements to the UIElementCollection value of the Children
property. The XAML content property facilitates a streamlined parent-child relationship in the XAML markup for a
UI definition. For more info about XAML content properties, and how collection properties are populated when
XAML is parsed, see the XAML syntax guide.
The collection type that's maintaining the value of the Children property is the UIElementCollection class.
UIElementCollection is a strongly typed collection that uses UIElement as its enforced item type. UIElement is a
base type that's inherited by hundreds of practical UI element types, so the type enforcement here is deliberately
loose. But it does enforce that you couldn't have a Brush as a direct child of a Panel, and it generally means that
only elements that are expected to be visible in UI and participate in layout will be found as child elements in a
Panel.
Typically, a custom panel accepts any UIElement child element by a XAML definition, by simply using the
characteristics of the Children property as-is. As an advanced scenario, you could support further type checking of
child elements, when you iterate over the collection in your layout overrides.
Besides looping through the Children collection in the overrides, your panel logic might also be influenced by
Children.Count . You might have logic that is allocating space at least partly based on the number of items, rather
than desired sizes and the other characteristics of individual items.

Overriding the layout methods


The basic model for the layout override methods (MeasureOverride and ArrangeOverride) is that they should
iterate through all the children and call each child element's specific layout method. The first layout cycle starts
when the XAML layout system sets the visual for the root window. Because each parent invokes layout on its
children, this propagates a call to layout methods to every possible UI element that is supposed to be part of a
layout. In XAML layout, there are two stages: measure, then arrange.
You don't get any built-in layout method behavior for MeasureOverride and ArrangeOverride from the base
Panel class. Items in Children won't automatically render as part of the XAML visual tree. It is up to you to make
the items known to the layout process, by invoking layout methods on each of the items you find in Children
through a layout pass within your MeasureOverride and ArrangeOverride implementations.
There's no reason to call base implementations in layout overrides unless you have your own inheritance. The
native methods for layout behavior (if they exist) run regardless, and not calling base implementation from
overrides won't prevent the native behavior from happening.
During the measure pass, your layout logic queries each child element for its desired size, by calling the Measure
method on that child element. Calling the Measure method establishes the value for the DesiredSize property.
The MeasureOverride return value is the desired size for the panel itself.
During the arrange pass, the positions and sizes of child elements are determined in x-y space and the layout
composition is prepared for rendering. Your code must call Arrange on each child element in Children so that the
layout system detects that the element belongs in the layout. The Arrange call is a precursor to composition and
rendering; it informs the layout system where that element goes, when the composition is submitted for rendering.
Many properties and values contribute to how the layout logic will work at runtime. A way to think about the layout
process is that the elements with no children (generally the most deeply nested element in the UI) are the ones that
can finalize measurements first. They don't have any dependencies on child elements that influence their desired
size. They might have their own desired sizes, and these are size suggestions until the layout actually takes place.
Then, the measure pass continues walking up the visual tree until the root element has its measurements and all
the measurements can be finalized.
The candidate layout must fit within the current app window or else parts of the UI will be clipped. Panels often are
the place where the clipping logic is determined. Panel logic can determine what size is available from within the
MeasureOverride implementation, and may have to push the size restrictions onto the children and divide space
amongst children so that everything fits as best it can. The result of layout is ideally something that uses various
properties of all parts of the layout but still fits within the app window. That requires both a good implementation
for layout logic of the panels, and also a judicious UI design on the part of any app code that builds a UI using that
panel. No panel design is going to look good if the overall UI design includes more child elements than can
possibly fit in the app.
A large part of what makes the layout system work is that any element that's based on FrameworkElement
already has some of its own inherent behavior when acting as a child in a container. For example, there are several
APIs of FrameworkElement that either inform layout behavior or are needed to make layout work at all. These
include:
DesiredSize (actually a UIElement property)
ActualHeight and ActualWidth
Height and Width
Margin
LayoutUpdated event
HorizontalAlignment and VerticalAlignment
ArrangeOverride and MeasureOverride methods
Arrange and Measure methods: these have native implementations defined at the FrameworkElement level,
which handle the element-level layout action

MeasureOverride
The MeasureOverride method has a return value that's used by the layout system as the starting DesiredSize for
the panel itself, when the Measure method is called on the panel by its parent in layout. The logic choices within
the method are just as important as what it returns, and the logic often influences what value is returned.
All MeasureOverride implementations should loop through Children, and call the Measure method on each child
element. Calling the Measure method establishes the value for the DesiredSize property. This might inform how
much space the panel itself needs, as well as how that space is divided among elements or sized for a particular
child element.
Here's a very basic skeleton of a MeasureOverride method:

protected override Size MeasureOverride(Size availableSize)


{
Size returnSize; //TODO might return availableSize, might do something else

//loop through each Child, call Measure on each


foreach (UIElement child in Children)
{
child.Measure(new Size()); // TODO determine how much space the panel allots for this child, that's what you pass to Measure
Size childDesiredSize = child.DesiredSize; //TODO determine how the returned Size is influenced by each child's DesiredSize
//TODO, logic if passed-in Size and net DesiredSize are different, does that matter?
}
return returnSize;
}
Elements often have a natural size by the time they're ready for layout. After the measure pass, the DesiredSize
might indicate that natural size, if the availableSize you passed for Measure was smaller. If the natural size is larger
than availableSize you passed for Measure, the DesiredSize is constrained to availableSize. That's how
Measure's internal implementation behaves, and your layout overrides should take that behavior into account.
Some elements don't have a natural size because they have Auto values for Height and Width. These elements
use the full availableSize, because that's what an Auto value represents: size the element to the maximum available
size, which the immediate layout parent communicates by calling Measure with availableSize. In practice, there's
always some measurement that a UI is sized to (even if that's the top level window.) Eventually, the measure pass
resolves all the Auto values to parent constraints and all Auto value elements get real measurements (which you
can get by checking ActualWidth and ActualHeight, after layout completes).
It's legal to pass a size to Measure that has at least one infinite dimension, to indicate that the panel can attempt to
size itself to fit measurements of its content. Each child element being measured sets its DesiredSize value using
its natural size. Then, during the arrange pass, the panel typically arranges using that size.
Text elements such as TextBlock have a calculated ActualWidth and ActualHeight based on their text string and
text properties even if no Height or Width value is set, and these dimensions should be respected by your panel
logic. Clipping text is a particularly bad UI experience.
Even if your implementation doesn't use the desired size measurements, it's best to call the Measure method on
each child element, because there are internal and native behaviors that are triggered by Measure being called. For
an element to participate in layout, each child element must have Measure called on it during the measure pass
and the Arrange method called on it during the arrange pass. Calling these methods sets internal flags on the
object and populates values (such as the DesiredSize property) that the system's layout logic needs when it builds
the visual tree and renders the UI.
The MeasureOverride return value is based on the panel's logic interpreting the DesiredSize or other size
considerations for each of the child elements in Children when Measure is called on them. What to do with
DesiredSize values from children and how the MeasureOverride return value should use them is up to your own
logic's interpretation. You don't typically add up the values without modification, because the input of
MeasureOverride is often a fixed available size that's being suggested by the panel's parent. If you exceed that
size, the panel itself might get clipped. You'd typically compare the total size of children to the panel's available size
and make adjustments if necessary.
Tips and guidance
Ideally, a custom panel should be suitable for being the first true visual in a UI composition, perhaps at a level
immediately under Page, UserControl or another element that is the XAML page root. In MeasureOverride
implementations, don't routinely return the input Size without examining the values. If the return Size has an
Infinity value in it, this can throw exceptions in runtime layout logic. An Infinity value can come from the main
app window, which is scrollable and therefore doesn't have a maximum height. Other scrollable content might
have the same behavior.
Another common mistake in MeasureOverride implementations is to return a new default Size (values for
height and width are 0). You might start with that value, and it might even be the correct value if your panel
determines that none of the children should be rendered. But, a default Size results in your panel not being
sized correctly by its host. It requests no space in the UI, and therefore gets no space and doesn't render. All your
panel code otherwise might be functioning fine, but you still won't see your panel or contents thereof if it's
being composed with zero height, zero width.
Within the overrides, avoid the temptation to cast child elements to FrameworkElement and use properties
that are calculated as a result of layout, particularly ActualWidth and ActualHeight. For most common
scenarios, you can base the logic on the child's DesiredSize value and you won't need any of the Height or
Width related properties of a child element. For specialized cases, where you know the type of element and
have additional information, for example the natural size of an image file, you can use your element's
specialized information because it's not a value that is actively being altered by layout systems. Including layout-
calculated properties as part of layout logic substantially increases the risk of defining an unintentional layout
loop. These loops cause a condition where a valid layout can't be created and the system can throw a
LayoutCycleException if the loop is not recoverable.
Panels typically divide their available space between multiple child elements, although exactly how space is
divided varies. For example, Grid implements layout logic that uses its RowDefinition and ColumnDefinition
values to divide the space into the Grid cells, supporting both star-sizing and pixel values. If they're pixel values,
the size available for each child is already known, so that's what is passed as input size for a grid-style Measure.
Panels themselves can introduce reserved space for padding between items. If you do this, make sure to expose
the measurements as a property that's distinct from Margin or any Padding property.
Elements might have values for their ActualWidth and ActualHeight properties based on a previous layout
pass. If values change, app UI code can put handlers for LayoutUpdated on elements if there's special logic to
run, but panel logic typically doesn't need to check for changes with event handling. The layout system is
already making the determinations of when to re-run layout because a layout-relevant property changed value,
and a panel's MeasureOverride or ArrangeOverride are called automatically in the appropriate
circumstances.

ArrangeOverride
The ArrangeOverride method has a Size return value that's used by the layout system when rendering the panel
itself, when the Arrange method is called on the panel by its parent in layout. It's typical that the input finalSize and
the ArrangeOverride returned Size are the same. If they aren't, that means the panel is attempting to make itself a
different size than what the other participants in layout claim is available. The final size was based on having
previously run the measure pass of layout through your panel code, so that's why returning a different size isn't
typical: it means you are deliberately ignoring measure logic.
Don't return a Size with an Infinity component. Trying to use such a Size throws an exception from internal
layout.
All ArrangeOverride implementations should loop through Children, and call the Arrange method on each child
element. Like Measure, Arrange doesn't have a return value. Unlike Measure, no calculated property gets set as a
result (however, the element in question typically fires a LayoutUpdated event).
Here's a very basic skeleton of an ArrangeOverride method:

protected override Size ArrangeOverride(Size finalSize)


{
//loop through each Child, call Arrange on each
foreach (UIElement child in Children)
{
Point anchorPoint = new Point(); //TODO more logic for topleft corner placement in your panel
// for this child, and based on finalSize or other internal state of your panel
child.Arrange(new Rect(anchorPoint, child.DesiredSize)); //OR, set a different Size
}
return finalSize; //OR, return a different Size, but that's rare
}

The arrange pass of layout might happen without being preceded by a measure pass. However, this only happens
when the layout system has determined no properties have changed that would have affected the previous
measurements. For example, if an alignment changes, there's no need to re-measure that particular element
because its DesiredSize would not change when its alignment choice changes. On the other hand, if ActualHeight
changes on any element in a layout, a new measure pass is needed. The layout system automatically detects true
measure changes and invokes the measure pass again, and then runs another arrange pass.
The input for Arrange takes a Rect value. The most common way to construct this Rect is to use the constructor
that has a Point input and a Size input. The Point is the point where the top left corner of the bounding box for the
element should be placed. The Size is the dimensions used to render that particular element. You often use the
DesiredSize for that element as this Size value, because establishing the DesiredSize for all elements involved in
layout was the purpose of the measure pass of layout. (The measure pass determines all-up sizing of the elements
in an iterative way so that the layout system can optimize how elements are placed once it gets to the arrange
pass.)
What typically varies between ArrangeOverride implementations is the logic by which the panel determines the
Point component of how it arranges each child. An absolute positioning panel such as Canvas uses the explicit
placement info that it gets from each element through Canvas.Left and Canvas.Top values. A space-dividing
panel such as Grid would have mathematical operations that divided the available space into cells and each cell
would have an x-y value for where its content should be placed and arranged. An adaptive panel such as
StackPanel might be expanding itself to fit content in its orientation dimension.
There are still additional positioning influences on elements in layout, beyond what you directly control and pass to
Arrange. These come from the internal native implementation of Arrange that's common to all
FrameworkElement derived types and augmented by some other types such as text elements. For example,
elements can have margin and alignment, and some can have padding. These properties often interact. For more
info, see Alignment, margin, and padding.

Panels and controls


Avoid putting functionality into a custom panel that should instead be built as a custom control. The role of a panel
is to present any child element content that exists within it, as a function of layout that happens automatically. The
panel might add decorations to content (similar to how a Border adds the border around the element it presents),
or perform other layout-related adjustments like padding. But that's about as far as you should go when extending
the visual tree output beyond reporting and using information from the children.
If there's any interaction that's accessible to the user, you should write a custom control, not a panel. For example, a
panel shouldn't add scrolling viewports to content it presents, even if the goal is to prevent clipping, because the
scrollbars, thumbs and so on are interactive control parts. (Content might have scrollbars after all, but you should
leave that up to the child's logic. Don't force it by adding scrolling as a layout operation.) You might create a control
and also write a custom panel that plays an important role in that control's visual tree, when it comes to presenting
content in that control. But the control and the panel should be distinct code objects.
One reason the distinction between control and panel is important is because of Microsoft UI Automation and
accessibility. Panels provide a visual layout behavior, not a logical behavior. How a UI element appears visually is
not an aspect of UI that is typically important to accessibility scenarios. Accessibility is about exposing the parts of
an app that are logically important to understanding a UI. When interaction is required, controls should expose the
interaction possibilities to the UI Automation infrastructure. For more info, see Custom automation peers.

Other layout API


There are some other APIs that are part of the layout system, but aren't declared by Panel. You might use these in a
panel implementation or in a custom control that uses panels.
UpdateLayout, InvalidateMeasure, and InvalidateArrange are methods that initiate a layout pass.
InvalidateArrange might not trigger a measure pass, but the other two do. Never call these methods from
within a layout method override, because they're almost sure to cause a layout loop. Control code doesn't
typically need to call them either. Most aspects of layout are triggered automatically by detecting changes to the
framework-defined layout properties such as Width and so on.
LayoutUpdated is an event that fires when some aspect of layout of the element has changed. This isn't
specific to panels; the event is defined by FrameworkElement.
SizeChanged is an event that fires only after layout passes are finalized, and indicates that ActualHeight or
ActualWidth have changed as a result. This is another FrameworkElement event. There are cases where
LayoutUpdated fires, but SizeChanged does not. For example the internal contents might be rearranged, but
the element's size didn't change.

Related topics
Reference
FrameworkElement.ArrangeOverride
FrameworkElement.MeasureOverride
Panel
Concepts
Alignment, margin, and padding
BoxPanel, an example custom panel
5/22/2017 13 min to read Edit Online

Learn to write code for a custom Panel class, implementing ArrangeOverride and MeasureOverride methods,
and using the Children property.

Important APIs
Panel
ArrangeOverride
MeasureOverride

The example code shows a custom panel implementation, but we don't devote a lot of time explaining the layout
concepts that influence how you can customize a panel for different layout scenarios. If you want more info about
these layout concepts and how they might apply to your particular layout scenario, see XAML custom panels
overview.
A panel is an object that provides a layout behavior for child elements it contains, when the XAML layout system
runs and your app UI is rendered. You can define custom panels for XAML layout by deriving a custom class from
the Panel class. You provide behavior for your panel by overriding the ArrangeOverride and MeasureOverride
methods, supplying logic that measures and arranges the child elements. This example derives from Panel. When
you start from Panel, ArrangeOverride and MeasureOverride methods don't have a starting behavior. Your
code is providing the gateway by which child elements become known to the XAML layout system and get
rendered in the UI. So, it's really important that your code accounts for all child elements and follows the patterns
the layout system expects.

Your layout scenario


When you define a custom panel, you're defining a layout scenario.
A layout scenario is expressed through:
What the panel will do when it has child elements
When the panel has constraints on its own space
How the logic of the panel determines all the measurements, placement, positions, and sizings that eventually
result in a rendered UI layout of children
With that in mind, the BoxPanel shown here is for a particular scenario. In the interest of keeping the code foremost
in this example, we won't explain the scenario in detail yet, and instead concentrate on the steps needed and the
coding patterns. If you want to know more about the scenario first, skip ahead to "The scenario for BoxPanel ", and
then come back to the code.

Start by deriving from Panel


Start by deriving a custom class from Panel. Probably the easiest way to do this is to define a separate code file for
this class, using the Add | New Item | Class context menu options for a project from the Solution Explorer in
Microsoft Visual Studio. Name the class (and file) BoxPanel .
The template file for a class doesn't start with many using statements because it's not specifically for Universal
Windows Platform (UWP) apps. So first, add using statements. The template file also starts with a few using
statements that you probably don't need, and can be deleted. Here's a suggested list of using statements that can
resolve types you'll need for typical custom panel code:

using System;
using System.Collections.Generic; // if you need to cast IEnumerable for iteration, or define your own collection properties
using Windows.Foundation; // Point, Size, and Rect
using Windows.UI.Xaml; // DependencyObject, UIElement, and FrameworkElement
using Windows.UI.Xaml.Controls; // Panel
using Windows.UI.Xaml.Media; // if you need Brushes or other utilities

Now that you can resolve Panel, make it the base class of BoxPanel . Also, make BoxPanel public:

public class BoxPanel : Panel


{
}

At the class level, define some int and double values that will be shared by several of your logic functions, but
which won't need to be exposed as public API. In the example, these are named: maxrc , rowcount , colcount , cellwidth
, cellheight , maxcellheight , aspectratio .
After you've done this, the complete code file looks like this (removing comments on using, now that you know
why we have them):

using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

public class BoxPanel : Panel


{
int maxrc, rowcount, colcount;
double cellwidth, cellheight, maxcellheight, aspectratio;
}

From here on out, we'll be showing you one member definition at a time, be that a method override or something
supporting such as a dependency property. You can add these to the skeleton above in any order, and we won't be
showing the using statements or the definition of the class scope again in the snippets until we show the final
code.

MeasureOverride
protected override Size MeasureOverride(Size availableSize)
{
Size returnSize;
// Determine the square that can contain this number of items.
maxrc = (int)Math.Ceiling(Math.Sqrt(Children.Count));
// Get an aspect ratio from availableSize, decides whether to trim row or column.
aspectratio = availableSize.Width / availableSize.Height;

// Now trim this square down to a rect, many times an entire row or column can be omitted.
if (aspectratio > 1)
{
rowcount = maxrc;
colcount = (maxrc > 2 && Children.Count < maxrc * (maxrc - 1)) ? maxrc - 1 : maxrc;
}
else
{
rowcount = (maxrc > 2 && Children.Count < maxrc * (maxrc - 1)) ? maxrc - 1 : maxrc;
colcount = maxrc;
}

// Now that we have a column count, divide available horizontal, that's our cell width.
cellwidth = (int)Math.Floor(availableSize.Width / colcount);
// Next get a cell height, same logic of dividing available vertical by rowcount.
cellheight = Double.IsInfinity(availableSize.Height) ? Double.PositiveInfinity : availableSize.Height / rowcount;

foreach (UIElement child in Children)


{
child.Measure(new Size(cellwidth, cellheight));
maxcellheight = (child.DesiredSize.Height > maxcellheight) ? child.DesiredSize.Height : maxcellheight;
}
return LimitUnboundedSize(availableSize);
}

The necessary pattern of a MeasureOverride implementation is the loop through each element in
Panel.Children. Always call the Measure method on each of these elements. Measure has a parameter of type
Size. What you're passing here is the size that your panel is committing to have available for that particular child
element. So, before you can do the loop and start calling Measure, you need to know how much space each cell
can devote. From the MeasureOverride method itself, you have the availableSize value. That is the size that the
panel's parent used when it called Measure, which was the trigger for this MeasureOverride being called in the
first place. So a typical logic is to devise a scheme whereby each child element divides the space of the panel's
overall availableSize. You then pass each division of size to Measure of each child element.
How BoxPanel divides size is fairly simple: it divides its space into a number of boxes that's largely controlled by the
number of items. Boxes are sized based on row and column count and the available size. Sometimes one row or
column from a square isn't needed, so it's dropped and the panel becomes a rectangle rather than square in terms
of its row : column ratio. For more info about how this logic was arrived at, skip ahead to "The scenario for
BoxPanel".
So what does the measure pass do? It sets a value for the read-only DesiredSize property on each element where
Measure was called. Having a DesiredSize value is possibly important once you get to the arrange pass, because
the DesiredSize communicates what the size can or should be when arranging and in the final rendering. Even if
you don't use DesiredSize in your own logic, the system still needs it.
It's possible for this panel to be used when the height component of availableSize is unbounded. If that's true, the
panel doesn't have a known height to divide. In this case, the logic for the measure pass informs each child that it
doesn't have a bounded height, yet. It does so by passing a Size to the Measure call for children where
Size.Height is infinite. That's legal. When Measure is called, the logic is that the DesiredSize is set as the
minimum of these: what was passed to Measure, or that element's natural size from factors such as explicitly-set
Height and Width.
NOTE
The internal logic of StackPanel also has this behavior: StackPanel passes an infinite dimension value to Measure on
children, indicating that there is no constraint on children in the orientation dimension. StackPanel typically sizes itself
dynamically, to accommodate all children in a stack that grows in that dimension.

However, the panel itself can't return a Size with an infinite value from MeasureOverride; that throws an
exception during layout. So, part of the logic is to find out the maximum height that any child requests, and use that
height as the cell height in case that isn't coming from the panel's own size constraints already. Here's the helper
function LimitUnboundedSize that was referenced in previous code, which then takes that maximum cell height and
uses it to give the panel a finite height to return, as well as assuring that cellheight is a finite number before the
arrange pass is initiated:

// This method is called only if one of the availableSize dimensions of measure is infinite.
// That can happen to height if the panel is close to the root of main app window.
// In this case, base the height of a cell on the max height from desired size
// and base the height of the panel on that number times the #rows.

Size LimitUnboundedSize(Size input)


{
if (Double.IsInfinity(input.Height))
{
input.Height = maxcellheight * colcount;
cellheight = maxcellheight;
}
return input;
}

ArrangeOverride
protected override Size ArrangeOverride(Size finalSize)
{
int count = 1
double x, y;
foreach (UIElement child in Children)
{
x = (count - 1) % colcount * cellwidth;
y = ((int)(count - 1) / colcount) * cellheight;
Point anchorPoint = new Point(x, y);
child.Arrange(new Rect(anchorPoint, child.DesiredSize));
count++;
}
return finalSize;
}

The necessary pattern of an ArrangeOverride implementation is the loop through each element in
Panel.Children. Always call the Arrange method on each of these elements.
Note how there aren't as many calculations as in MeasureOverride; that's typical. The size of children is already
known from the panel's own MeasureOverride logic, or from the DesiredSize value of each child set during the
measure pass. However, we still need to decide the location within the panel where each child will appear. In a
typical panel, each child should render at a different position. A panel that creates overlapping elements isn't
desirable for typical scenarios (although it's not out of the question to create panels that have purposeful overlaps,
if that's really your intended scenario).
This panel arranges by the concept of rows and columns. The number of rows and columns was already calculated
(it was necessary for measurement). So now the shape of the rows and columns plus the known sizes of each cell
contribute to the logic of defining a rendering position (the anchorPoint ) for each element that this panel contains.
That Point, along with the Size already known from measure, are used as the two components that construct a
Rect. Rect is the input type for Arrange.
Panels sometimes need to clip their content. If they do, the clipped size is the size that's present in DesiredSize,
because the Measure logic sets it as the minimum of what was passed to Measure, or other natural size factors. So
you don't typically need to specifically check for clipping during Arrange; the clipping just happens based on
passing the DesiredSize through to each Arrange call.
You don't always need a count while going through the loop if all the info you need for defining the rendering
position is known by other means. For example, in Canvas layout logic, the position in the Children collection
doesn't matter. All the info needed to position each element in a Canvas is known by reading Canvas.Left and
Canvas.Top values of children as part of the arrange logic. The BoxPanel logic happens to need a count to compare
to the colcount so it's known when to begin a new row and offset the y value.
It's typical that the input finalSize and the Size you return from a ArrangeOverride implementation are the same.
For more info about why, see "ArrangeOverride" section of XAML custom panels overview.

A refinement: controlling the row vs. column count


You could compile and use this panel just as it is now. However, we'll add one more refinement. In the code just
shown, the logic puts the extra row or column on the side that's longest in aspect ratio. But for greater control over
the shapes of cells, it might be desirable to choose a 4x3 set of cells instead of 3x4 even if the panel's own aspect
ratio is "portrait." So we'll add an optional dependency property that the panel consumer can set to control that
behavior. Here's the dependency property definition, which is very basic:

public static readonly DependencyProperty UseOppositeRCRatioProperty =


DependencyProperty.Register("UseOppositeRCRatio", typeof(bool), typeof(BoxPanel), null);

public bool UseSquareCells


{
get { return (bool)GetValue(UseOppositeRCRatioProperty); }
set { SetValue(UseOppositeRCRatioProperty, value); }
}

And here's how using UseOppositeRCRatio impacts the measure logic. Really all it's doing is changing how rowcount
and colcount are derived from maxrc and the true aspect ratio, and there are corresponding size differences for
each cell because of that. When UseOppositeRCRatio is true, it inverts the value of the true aspect ratio before using it
for row and column counts.

if (UseOppositeRCRatio) { aspectratio = 1 / aspectratio;}

The scenario for BoxPanel


The particular scenario for BoxPanel is that it's a panel where one of the main determinants of how to divide space
is by knowing the number of child items, and dividing the known available space for the panel. Panels are innately
rectangle shapes. Many panels operate by dividing that rectangle space into further rectangles; that's what Grid
does for its cells. In Grid's case, the size of the cells is set by ColumnDefinition and RowDefinition values, and
elements declare the exact cell they go into with Grid.Row and Grid.Column attached properties. Getting good
layout from a Grid usually requires knowing the number of child elements beforehand, so that there are enough
cells and each child element sets its attached properties to fit into its own cell.
But what if the number of children is dynamic? That's certainly possible; your app code can add items to collections,
in response to any dynamic run-time condition you consider to be important enough to be worth updating your UI.
If you're using data binding to backing collections/business objects, getting such updates and updating the UI is
handled automatically, so that's often the preferred technique (see Data binding in depth).
But not all app scenarios lend themselves to data binding. Sometimes, you need to create new UI elements at
runtime and make them visible. BoxPanel is for this scenario. A changing number of child items is no problem for
BoxPanel because it's using the child count in calculations, and adjusts both the existing and new child elements
into a new layout so they all fit.
An advanced scenario for extending BoxPanel further (not shown here) could both accommodate dynamic children
and use a child's DesiredSize as a stronger factor for the sizing of individual cells. This scenario might use varying
row or column sizes or non-grid shapes so that there's less "wasted" space. This requires a strategy for how
multiple rectangles of various sizes and aspect ratios can all fit into a containing rectangle both for aesthetics and
smallest size. BoxPanel doesn't do that; it's using a simpler technique for dividing space. BoxPanel 's technique is to
determine the least square number that's greater than the child count. For example, 9 items would fit in a 3x3
square. 10 items require a 4x4 square. However, you can often fit items while still removing one row or column of
the starting square, to save space. In the count=10 example, that fits in a 4x3 or 3x4 rectangle.
You might wonder why the panel wouldn't instead choose 5x2 for 10 items, because that fits the item number
neatly. However, in practice, panels are sized as rectangles that seldom have a strongly oriented aspect ratio. The
least-squares technique is a way to bias the sizing logic to work well with typical layout shapes and not encourage
sizing where the cell shapes get odd aspect ratios.

NOTE
This article is for Windows 10 developers writing Universal Windows Platform (UWP) apps. If you're developing for Windows
8.x or Windows Phone 8.x, see the archived documentation.

Related topics
Reference
FrameworkElement.ArrangeOverride
FrameworkElement.MeasureOverride
Panel
Concepts
Alignment, margin, and padding
Alignment, margin, and padding
5/22/2017 8 min to read Edit Online

In addition to dimension properties (width, height, and constraints), elements can also have alignment, margin,
and padding properties that influence the layout behavior when an element goes through a layout pass and is
rendered in a UI. There are relationships between alignment, margin, padding and dimension properties that have
a typical logic flow when a FrameworkElement object is positioned, such that values are sometimes used and
sometimes ignored depending on the circumstances.

Alignment properties
The HorizontalAlignment and VerticalAlignment properties describe how a child element should be
positioned within a parent element's allocated layout space. By using these properties together, layout logic for a
container can position child elements within the container (either a panel or a control). Alignment properties are
intended to hint the desired layout to an adaptive layout container, so basically they're set on
FrameworkElement children and interpreted by another FrameworkElement container parent. Alignment
values can specify whether elements align to one of the two edges of an orientation, or to the center. However,
the default value for both alignment properties is Stretch. With Stretch alignment, elements fill the space they're
provided in layout. Stretch is the default so that it's easier to use adaptive layout techniques in the cases where
there is no explicit measurement or no DesiredSize value that came from the measure pass of layout. With this
default, there's no risk of an explicit height/width not fitting within the container and being clipped until you size
each container.

NOTE
As a general layout principle, it's best to only apply measurements to certain key elements and use the adaptive layout
behavior for the other elements. This provides flexible layout behavior for when the user sizes the top app window, which
typically is possible to do at any time.

If there are either Height and Width values or clipping within an adaptive container, even if Stretch is set as an
alignment value, the layout is controlled by the behavior of its container. In panels, a Stretch value that's been
obviated by Height and Width acts as if the value is Center.
If there are no natural or calculated height and width values, these dimension values are mathematically NaN
(Not A Number). The elements are waiting for their layout container to give them dimensions. After layout is run,
there will be values for ActualHeight and ActualWidth properties for elements where a Stretch alignment was
used. The NaN values remain in Height and Width for the child elements so that the adaptive behavior can run
again, for example, if layout-related changes such as app window sizing causes another layout cycle.
Text elements such as TextBlock don't usually have an explicitly declared width, but they do have a calculated
width that you can query with ActualWidth, and that width also cancels out a Stretch alignment. (The FontSize
property and other text properties, as well as the text itself, are already hinting the intended layout size. You don't
typically want your text to be stretched.) Text used as content within a control has the same effect; the presence of
text that needs presenting causes an ActualWidth to be calculated, and this also commutes a desired width and
size to the containing control. Text elements also have an ActualHeight based on font size per line, line breaks,
and other text properties.
A panel such as Grid already has other logic for layout (row and column definitions, and attached properties such
as Grid.Row set on elements to indicate which cell to be drawn in). In that case, the alignment properties
influence how the content is aligned within the area of that cell, but the cell structure and sizing is controlled by
settings on the Grid.
Item controls sometimes display items where the base types of the items are data. This involves an
ItemsPresenter. Although the data itself is not a FrameworkElement derived type, ItemsPresenter is, so you
can set HorizontalAlignment and VerticalAlignment for the presenter and that alignment applies to the data
items when presented in the items control.
Alignment properties are only relevant for cases when there's extra space available in a dimension of the parent
layout container. If a layout container is already clipping content, alignment can affect the area of the element
where the clipping will apply. For example, if you set HorizontalAlignment="Left" , the right size of the element gets
clipped.

Margin
The Margin property describes the distance between an element and its peers in a layout situation, and also the
distance between an element and the content area of a container that contains the element. If you think of
elements as bounding boxes or rectangles where the dimensions are the ActualHeight and ActualWidth, the
Margin layout applies to the outside of that rectangle and does not add pixels to the ActualHeight and
ActualWidth. The margin is also not considered part of the element for purposes of hit testing and sourcing
input events.
In general layout behavior, components of a Margin value are constrained last, and are constrained only after
Height and Width are already constrained all the way to 0. So, be careful with margins when the container is
already clipping or constraining the element; otherwise, your margin could be the cause of an element not
appearing to render (because one of its dimensions has been constrained to 0 after the margin was applied).
Margin values can be uniform, by using syntax like Margin="20" . With this syntax, a uniform margin of 20 pixels
would be applied to the element, with a 20-pixel margin on the left, top, right, and bottom sides. Margin values
can also take the form of four distinct values, each value describing a distinct margin to apply to the left, top, right,
and bottom (in that order). For example, Margin="0,10,5,25" . The underlying type for the Margin property is a
Thickness structure, which has properties that hold the Left, Top, Right, and Bottom values as separate Double
values.
Margins are additive. For example, if two elements each specify a uniform margin of 10 pixels and they are
adjacent peers in any orientation, the distance between the elements is 20 pixels.
Negative margins are permitted. However, using a negative margin can often cause clipping, or overdraws of
peers, so it's not a common technique to use negative margins.
Proper use of the Margin property enables very fine control of an element's rendering position and the rendering
position of its neighbor elements and children. When you use element dragging to position elements within the
XAML designer in Visual Studio, you'll see that the modified XAML typically has values for Margin of that element
that were used to serialize your positioning changes back into the XAML.
The Block class, which is a base class for Paragraph, also has a Margin property. It has an analogous effect on
how that Paragraph is positioned within its parent container, which is typically a RichTextBlock or RichEditBox
object, and also how more than one paragraph is positioned relative to other Block peers from the
RichTextBlock.Blocks collection.

Padding
A Padding property describes the distance between an element and any child elements or content that it
contains. Content is treated as a single bounding box that encloses all the content, if it's an element that permits
more than one child. For example, if there's an ItemsControl that contains two items, the Padding is applied
around the bounding box that contains the items. Padding subtracts from the available size when it comes to the
measure and arrange pass calculations for that container and are part of the desired size values when the
container itself goes through the layout pass for whatever contains it. Unlike Margin, Padding is not a property
of FrameworkElement, and in fact there are several classes which each define their own Padding property:
Control.Padding: inherits to all Control derived classes. Not all controls have content, so for some controls
(for example AppBarSeparator) setting the property does nothing. If the control has a border (see
Control.BorderThickness), the padding applies inside that border.
Border.Padding: defines space between the rectangle line created by BorderThickness/BorderBrush and
the Child element.
ItemsPresenter.Padding: contributes to appearance of the generated visuals for items in item controls,
placing the specified padding around each item.
TextBlock.Padding and RichTextBlock.Padding: expands the bounding box around the text of the text
element. These text elements don't have a Background, so it can be visually difficult to see what's the text's
padding versus other layout behavior applied by the text element's container. For that reason, text element
padding is seldom used and it's more typical to use Margin settings on contained Block containers (for the
RichTextBlock case).
In each of these cases, the same element also has a Margin property. If both margin and padding are applied,
they are additive in the sense that the apparent distance between an outer container and any inner content will be
margin plus padding. If there are different background values applied to content, element or container, the point
at which margin ends and padding begins is potentially visible in the rendering.

Dimensions (Height, Width)


The Height and Width properties of a FrameworkElement often influence how the alignment, margin, and
padding properties behave when a layout pass happens. In particular, real-number Height and Width value
cancels Stretch alignments, and is also promoted as a possible component of the DesiredSize value that's
established during the measure pass of the layout. Height and Width have constraint properties: the Height
value can be constrained with MinHeight and MaxHeight, the Width value can be constrained with MinWidth
and MaxWidth. Also, ActualWidth and ActualHeight are calculated, read-only properties that only contain
valid values after a layout pass has completed. For more info about how the dimensions and constraints or
calculated properties interrelate, see Remarks in FrameworkElement.Height and FrameworkElement.Width.

Related topics
Reference
FrameworkElement.Height
FrameworkElement.Width
FrameworkElement.HorizontalAlignment
FrameworkElement.VerticalAlignment
FrameworkElement.Margin
Control.Padding
Create a simple weather app by using Grid and
StackPanel
8/28/2017 4 min to read Edit Online

Use XAML to create the layout for a simple weather app using the Grid and StackPanel elements. With these
tools you can make great looking apps that work on any device running Windows 10. This tutorial takes 10-20
minutes.

Important APIs: Grid class, StackPanel class

Prerequisites
Windows 10 and Microsoft Visual Studio 2015. Click here to learn how to get set up with Visual Studio.
Knowledge of how to create a basic "Hello World" app by using XAML and C#. If you don't have that yet, click
here to learn how to create a "Hello World" app.

Step 1: Create a blank app


1. In Visual Studio menu, select File > New Project.
2. In the left pane of the New Project dialog box, select Visual C# > Windows > Universal or Visual C++ >
Windows > Universal.
3. In the center pane, select Blank App.
4. In the Name box, enter WeatherPanel, and select OK.
5. To run the program, select Debug > Start Debugging from the menu, or select F5.

Step 2: Define a Grid


In XAML a Grid is made up of a series of rows and columns. By specifying the row and column of an element
within a Grid, you can place and space other elements within a user interface. Rows and columns are defined with
the RowDefinition and ColumnDefinition elements.
To start creating a layout, open MainPage.xaml by using the Solution Explorer, and replace the automatically
generated Grid element with this code.

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>

The new Grid creates a set of two rows and columns, which defines the layout of the app interface. The first
column has a Width of "3*", while the second has "5*", dividing the horizontal space between the two columns at
a ratio of 3:5. In the same way, the two rows have a Height of "2*" and "*" respectively, so the Grid allocates two
times as much space for the first row as for the second ("*" is the same as "1*"). These ratios are maintained even if
the window is resized or the device is changed.
To learn about other methods of sizing rows and columns, see Define layouts with XAML.
If you run the application now you won't see anything except a blank page, because none of the Grid areas have
any content. To show the Grid let's give it some color.

Step 3: Color the Grid


To color the Grid we add three Border elements, each with a different background color. Each is also assigned to a
row and column in the parent Grid by using the Grid.Row and Grid.Column attributes. The values of these
attributes default to 0, so you don't need to assign them to the first Border. Add the following code to the Grid
element after the row and column definitions.

<Border Background="#2f5cb6"/>
<Border Grid.Column ="1" Background="#1f3d7a"/>
<Border Grid.Row="1" Grid.ColumnSpan="2" Background="#152951"/>

Notice that for the third Border we use an extra attribute, Grid.ColumnSpan, which causes this Border to span
both columns in the lower row. You can use Grid.RowSpan in the same way, and together these attributes let you
span an element over any number of rows and columns. The upper-left corner of such a span is always the
Grid.Column and Grid.Row specified in the element attributes.
If you run the app, the result looks something like this.

Step 4: Organize content by using StackPanel elements


StackPanel is the second UI element we'll use to create our weather app. The StackPanel is a fundamental part
of many basic app layouts, allowing you to stack elements vertically or horizontally.
In the following code, we create two StackPanel elements and fill each with three TextBlocks. Add these
StackPanel elements to the Grid below the Border elements from Step 3. This causes the TextBlock elements to
render on top of the colored Grid we created earlier.
<StackPanel Grid.Column="1" Margin="40,0,0,0" VerticalAlignment="Center">
<TextBlock Foreground="White" FontSize="25" Text="Today - 64 F"/>
<TextBlock Foreground="White" FontSize="25" Text="Partially Cloudy"/>
<TextBlock Foreground="White" FontSize="25" Text="Precipitation: 25%"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal"
HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Foreground="White" FontSize="25" Text="High: 66" Margin="0,0,20,0"/>
<TextBlock Foreground="White" FontSize="25" Text="Low: 43" Margin="0,0,20,0"/>
<TextBlock Foreground="White" FontSize="25" Text="Feels like: 63"/>
</StackPanel>

In the first Stackpanel, each TextBlock stacks vertically below the next. This is the default behavior of a
StackPanel, so we don't need to set the Orientation attribute. In the second StackPanel, we want the child
elements to stack horizontally from left to right, so we set the Orientation attribute to "Horizontal". We must also
set the Grid.ColumnSpan attribute to "2", so that the text is centered over the lower Border.
If you run the app now, you'll see something like this.

Step 5: Add an image icon


Finally, let's fill the empty section in our Grid with an image that represents today's weathersomething that says
"partially cloudy."
Download the image below and save it as a PNG named "partially-cloudy".

In the Solution Explorer, right click the Assets folder, and select Add -> Existing Item... Find partially-
cloudy.png in the browser that pops up, select it, and click Add.
Next, in MainPage.xaml, add the following Image element below the StackPanels from Step 4.
<Image Margin="20" Source="Assets/partially-cloudy.png"/>

Because we want the Image in the first row and column, we don't need to set its Grid.Row or Grid.Column
attributes, allowing them to default to "0".
And that's it! You've successfully created the layout for a simple weather application. If you run the application by
pressing F5, you should see something like this:

If you like, try experimenting with the layout above, and explore different ways you might represent weather data.

Related articles
For an introduction to designing UWP app layouts, see Introduction to UWP app design
To learn about creating responsive layouts that adapt to different screen sizes, see Define Page Layouts with XAML
UWP style guide
8/29/2017 1 min to read Edit Online

The Fluent Design System helps you create modern, clean UI that incorporates light, depth, motion, material, and
scale. The guidelines in this section help you create a Fluent Design through color, typography, and new features
such as acrylic material and Reveal.

Acrylic material
Create a sense of depth with acrylic, a brush that creates stunning, translucent surfaces.
Color
Color provides intuitive wayfinding through an app's various levels of information and serves as a crucial tool for
reinforcing the interaction model.
Icons
Good icons harmonize with typography and with the rest of the design language. They dont mix metaphors, and
they communicate only whats needed, as speedily and simply as possible.
Motion and animation
Purposeful, well-designed animations bring apps to life and make the experience feel crafted and polished. Help
users understand context changes, and tie experiences together with visual transitions.
Parallax
Add three-dimensional perspective and motion to scrolling elements.
Reveal
Use light to illuminate important elements.
Sound
Sound helps complete an application's user experience, and gives them that extra audio edge they need to match
the feel of Windows across all platforms.
Typography
As the visual representation of language, typographys main task is to be clear. Its style should never get in the way
of that goal. But typography also has an important role as a layout componentwith a powerful effect on the
density and complexity of the designand on the users experience of that design.
Styling controls
You can customize the appearance of your apps in many ways by using the XAML framework. Styles let you set
control properties and reuse those settings for a consistent appearance across multiple controls.
Acrylic material
8/17/2017 9 min to read Edit Online

IMPORTANT
This article describes functionality that hasnt been released yet and may be substantially modified before it's commercially
released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

Acrylic is a type of Brush that creates a partially transparent texture. You can apply acrylic to app surfaces to add
depth and help establish a visual hierarchy.

Important APIs: AcrylicBrush class, Background property


Acrylic and the Fluent Design System
The Fluent Design System helps you create modern, bold UI that incorporates light, depth, motion, material, and
scale. Acrylic is a Fluent Design System component that adds physical texture (material) and depth to your app.

When to use acrylic


We recommend that you place supporting UI, such as in-app navigation or commanding elements, on an acrylic
surface. This material is also helpful for transient UI elements, such as dialogs and flyouts, because it helps
maintain a visual relationship with the content that triggered the transient UI. We designed acrylic to be used as a
background material and show in visually discrete panes, so don't apply acrylic to detailed foreground elements.
Surfaces behind primary app content should use solid, opaque backgrounds.
Consider having acrylic extend to one or more edges of your app, including the window title bar, to improve
visual flow. Avoid creating a striping effect by stacking acrylics of different blend types adjacent to each other.
Acrylic is a tool to bring visual harmony to your designs but, when used incorrectly, can result in visual noise.
Consider the following usage patterns to decide how best to incorporate acrylic into your app.
Vertical acrylic pane
For apps with vertical navigation, we recommend applying acrylic to the secondary pane containing navigation
elements.
NavigationView is a new common control for adding navigation to your app and includes acrylic in its visual
design. NavigationViews pane shows background acrylic when the pane is open side-by-side with primary
content, and automatically transitions to in-app acrylic when the pane is open as an overlay.
If your app is not able to leverage NavigationView and you plan on adding acrylic on your own, we recommend
using relatively transparent acrylic with 60% tint opacity.
When the pane opens as an overlay above other app content, this should be 60% in-app acrylic
When the pane opens side-by-side with main app content, this should be 60% background acrylic
Multiple acrylic panes
For apps with three distinct vertical panes, we recommend adding acrylic to non-primary content.
For the secondary pane closest to primary content, use 80% background acrylic
For the tertiary pane further away from primary content, use 60% background acrylic
Horizontal acrylic pane
For apps with horizontal navigation, commanding, or other strong horizontal elements across the top of the app,
we recommend applying 70% acrylic to this visual element.

Canvas apps with emphasis on continuous, zoomable content should use in-app acrylic in the top bar to let users
connect with this content. Examples of canvas apps include maps, painting and drawing.
For apps without a single continuous canvas, we recommend using background acrylic to connect users to their
overall desktop environment.
Acrylic in utility apps
Widgets or light-weight apps can reinforce their usage as utility apps by drawing acrylic edge-to-edge inside their
app window. Apps belonging to this category typically have brief user engagement times and are unlikely to
occupy the user's entire desktop screen. Examples include calculator and action center.

NOTE
Rendering acrylic surfaces is GPU intensive, which can increase device power consumption and shorten battery life. Acrylic
effects are automatically disabled when devices enter battery saver mode, and users can disable acrylic effects for all apps, if
they choose.

Acrylic blend types


Acrylic's most noticeable characteristic is its transparency. There are two acrylic blend types that change whats
visible through the material:
Background acrylic reveals the desktop wallpaper and other windows that are behind the currently active
app, adding depth between application windows while celebrating the users personalization preferences.
In-app acrylic adds a sense of depth within the app frame, providing both focus and hierarchy.
Layer multiple acrylic surfaces with caution. Background acrylic, as its name implies, should not be closest
to the user in z-order. Multiple layers of background acrylic tend to result in unexpected optical illusions
and should also be avoided. If you choose to layer acrylics, do so with in-app acrylic and consider making
acrylics tint lighter in value to help visually bring the layers forward to the viewer.

Usability and adaptability


Acrylic automatically adapts its appearance for a wide variety of devices and contexts.
In High Contrast mode, users continue to see the familiar background color of their choosing in place of acrylic. In
addition, both background acrylic and in-app acrylic appear as a solid color
When the user turns off transparency in Personalization settings
When battery saver mode is activated
When the app runs on low-end hardware
In addition, only background acrylic will replace its transparency and texture with a solid color
When an app window on desktop deactivates
When the UWP app is running on phone, Xbox, HoloLens or tablet mode
Legibility considerations
Its important to ensure that any text your app presents to users meets contrast ratios. Weve optimized the acrylic
recipe so that high-color black, white or even medium-color gray text meets contrast ratios on top of acrylic. The
theme resources provided by the platform default to contrasting tint colors at 80% opacity. When placing high-
color body text on acrylic, you can reduce tint opacity while maintaining legibility. In dark mode, tint opacity can
be 70%, while light mode acrylic will meet contrast ratios at 50% opacity.
We don't recommend placing accent-colored text on your acrylic surfaces because these combinations are likely
to not pass minimum contrast ratio requirements at 15px font size. Try to avoid placing hyperlinks over acrylic
elements. Also, if you choose to customize the acrylic tint color or opacity level outside of the platform defaults
provided by the theme resource, keep the impact on legibility in mind.

Acrylic theme resources


You can easily apply acrylic to your apps surfaces using the new XAML AcrylicBrush or predefined AcrylicBrush
theme resources. First, youll need to decide whether to use in-app or background acrylic. Be sure to review
common app patterns described earlier in this article for recommendations.
Weve created a collection of brush theme resources for both background and in-app acrylic types that respect the
apps theme and fall back to solid colors as needed. Resources named Acrylic\WindowBrush* represent
background acrylic, while Acrylic\ElementBrush* refers to in-app acrylic.

RESOURCE KEY TINT OPACITY FALLBACK COLOR

SystemControlAcrylicWindowBrush 80% ChromeMedium


SystemControlAcrylicElementBrush

Recommended usage: These are


general-purpose acrylic resources that
work well in a wide variety of usages. If
your app uses secondary text of
AltMedium color with text size smaller
than 18px, place an 80% acrylic
resource behind the text to meet
contrast ratio requirements.
SystemControlAcrylicMediumHighWind 70% ChromeMedium
owBrush
SystemControlAcrylicMediumHighElem
entBrush

Recommended usage: If your app


uses secondary text of AltMedium color
with a text size of 18px or larger, you
can place these more transparent 70%
acrylic resources behind the text. We
recommend using these resources in
your app's top horizontal navigation
and commanding areas.

SystemControlAcrylicMediumWindowB 60% ChromeMediumLow


rush
SystemControlAcrylicMediumElementBr
ush

Recommended usage: When placing


only primary text of AltHigh color over
acrylic, your app can utilize these 60%
resources. We recommend painting
your app's vertical navigation pane, i.e.
hamburger menu, with 60% acrylic.

In addition to color-neutral acrylic, we've also added resources that tint acrylic using the user-specified accent
color. We recommend using colored acrylic sparingly. For the dark1 and dark2 variants provided, place white or
light-colored text consistent with dark theme text color over these resources.

RESOURCE KEY TINT OPACITY TINT AND FALLBACK COLORS

SystemControlAcrylicAccentMediumHig 70% SystemAccentColor


hWindowBrush
SystemControlAcrylicAccentMediumHig
hElementBrush

SystemControlAcrylicAccentDark1Wind 80% SystemAccentColorDark1


owBrush
SystemControlAcrylicAccentDark1Elem
entBrush

SystemControlAcrylicAccentDark2Medi 70% SystemAccentColorDark2


umHighWindowBrush
SystemControlAcrylicAccentDark2Medi
umHighElementBrush

To paint a specific surface, apply one of the above theme resources to element backgrounds just as you would
apply any other brush resource.

<Grid Background="{ThemeResource SystemControlAcrylicElementBrush}">

Custom acrylic brush


You may choose to add a color tint to your apps acrylic to show branding or provide visual balance with other
elements on the page. To show color rather than greyscale, youll need to define your own acrylic brushes using
the following properties.
TintColor: the color/tint overlay layer. Consider specifying both the RGB color value and alpha channel
opacity.
TintOpacity: the opacity of the tint layer. We recommend 80% opacity as a starting point, although different
colors may look more compelling at other transparencies.
BackgroundSource: the flag to specify whether you want background or in-app acrylic.
FallbackColor: the solid color that replaces acrylic in low-battery mode. For background acrylic, fallback color
also replaces acrylic when your app isnt in the active desktop window or when the app is running on phone
and Xbox.
To add an acrylic brush, define the three resources for dark, light and high contrast themes. Note that in high
contrast, we recommend using a SolidColorBrush with the same x:Key as the dark/light AcrylicBrush.

<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<AcrylicBrush x:Key="MyAcrylicBrush"
BackgroundSource="HostBackdrop"
TintColor="#FFFF0000"
TintOpacity="0.8"
FallbackColor="#FF7F0000"/>
</ResourceDictionary>

<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="MyAcrylicBrush"
Color="{ThemeResource SystemColorWindowColor}"/>
</ResourceDictionary>

<ResourceDictionary x:Key="Light">
<AcrylicBrush x:Key="MyAcrylicBrush"
BackgroundSource="HostBackdrop"
TintColor="#FFFF0000"
TintOpacity="0.8"
FallbackColor="#FFFF7F7F"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

The following sample shows how to declare AcrylicBrush in code. If your app supports multiple OS targets, be
sure to check that this API is available on the users machine.
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.UI.Xaml.Media.XamlCompositionBrushBase"))
{
Windows.UI.Xaml.Media.AcrylicBrush myBrush = new Windows.UI.Xaml.Media.AcrylicBrush();
myBrush.BackgroundSource = Windows.UI.Xaml.Media.AcrylicBackgroundSource.HostBackdrop;
myBrush.TintColor = Color.FromArgb(255, 202, 24, 37);
myBrush.FallbackColor = Color.FromArgb(255, 202, 24, 37);
myBrush.TintOpacity = 0.6;

grid.Fill = myBrush;
}
else
{
SolidColorBrush myBrush = new SolidColorBrush(Color.FromArgb(255, 202, 24, 37));

grid.Fill = myBrush;
}

Extending acrylic into your title bar


For a seamless, flowing look within your app's window, we recommend placing acrylic in your app's title bar area.
To do so, add the following code to your App.xaml.cs.

CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;

In addition, you'll need to draw your app's title, which normally appears automatically in the title bar, with a
TextBlock using CaptionTextBlockStyle .

Do's and don'ts


Do use acrylic as the background material of non-primary app surfaces like navigation panes.
Do extend acrylic to at least one edge of your app to provide a seamless experience by subtly blending with the
apps surroundings.
Dont place in-app and background acrylics directly adjacent to avoid visual tension at the seams.
Don't place multiple acrylic panes with the same tint and opacity next to each other because this results in an
undesirable visible seam.
Dont place accent-colored text over acrylic surfaces.

How we designed acrylic


We fine-tuned acrylics key components to arrive at its unique appearance and properties. We started with
transparency, blur and noise to add visual depth and dimension to flat surfaces. We added an exclusion blend
mode layer to ensure contrast and legibility of UI placed on an acrylic background. Finally, we added color tint for
personalization opportunities. In concert these layers add up to a fresh, usable material.
The acrylic recipe: background, blur, exclusion blend, color/tint overlay, noise

Related articles
Reveal
Color
5/22/2017 4 min to read Edit Online

Color provides intuitive way of finding through an app's various levels of information and serves as a crucial tool
for reinforcing the interaction model.
In Windows, color is also personal. Users can choose a color and a light or dark theme to be reflected throughout
their experience.

Accent color
The user can pick a single color called the accent from Settings > Personalization > Colors. They have their choice
from a curated set of 48 color swatches, except on Xbox which has a palette of 21 TV-safe colors.
Default accent colors

FFB900 E74856 0078D7 0099BC 7A7574 767676

FF8C00 E81123 0063B1 2D7D9A 5D5A58 4C4A48

F7630C EA005E 8E8CD8 00B7C3 68768A 69797E

CA5010 C30052 6B69D6 038387 515C6B 4A5459

DA3B01 E3008C 8764B8 00B294 567C73 647C64

EF6950 BF0077 744DA9 018574 486860 525E54

D13438 C239B3 B146C2 00CC6A 498205 847545

FF4343 9A0089 881798 10893E 107C10 7E735F

Xbox accent colors

EB8C10 ED5588 1073D6 148282 107C10 4C4A4B


EB4910 BF1077 193E91 54A81B 737373 7E715C

E31123 B144C0 1081CA 547A72 677488 724F2F

A21025 744DA9 108272

Avoid using the accent color as a background, especially for text and icons. Because the accent color can change, if
you must use it as a background, theres some additional work you must do to ensure that foreground text is easy
to read. For example, if your text is white and the accent color is light gray, your text will be difficult to see because
the contrast ratio between white and light gray is small. You can work around the issue by testing the accent color
to determine whether its a dark color:
Use the following algorithm to determine whether a background color is light or dark.

void accentColorUpdated(FrameworkElement elementWithText)


{
var uiSettings = new Windows.UI.ViewManagement.UISettings();
Windows.UI.Color c = uiSettings.GetColorValue(UIColorType.Accent);

bool colorIsDark = (5 * c.G + 2 * c.R + c.B) <= 8 * 128;


if (colorIsDark)
{
elementWithText.RequestedTheme = ElementTheme.Light;
}
else
{
elementWithText.RequestedTheme = ElementTheme.Dark;
}
}

function accentColorUpdated(elementWithText)
{
var uiSettings = new Windows.UI.ViewManagement.UISettings();
Windows.UI.Color c = uiSettings.GetColorValue(UIColorType.Accent);
var colorIsDark (5 * c.g + 2 * c.r + c.b) <= 8 * 128;
if (colorIsDark)
{
elementWithText.RequestedTheme = ElementTheme.Light;
}
else
{
elementWithText.RequestedTheme = ElementTheme.Dark;
}
}

Once youve determined whether the accent color is light or dark, choose an appropriate foreground color. We
recommend using the SystemControlForegroundBaseHighBrush from the light theme for dark backgrounds and
using the dark-themed version for light backgrounds.

Color palette building blocks


Once an accent color is selected, light and dark shades of the accent color are created based on HSB values of
color luminosity. Apps can use shade variations to create visual hierarchy and to provide an indication of
interaction.
By default, hyperlinks will use the user's accent color. If the page background is a similar color, you can choose to
assign a lighter (or darker) shade of accent to the hyperlinks for better contrast.

THE VARIOUS LIGHT/DARK SHADES OF THE DEFAULT ACCENT COLOR.

3 shades lighter

2 shades lighter

1 shade lighter

Sample accent color

1 shade darker

2 shades darker

3 shades darker

An example of how color logic gets applied to a design spec.


NOTE
In XAML, the primary accent color is exposed as a theme resource named SystemAccentColor . The shades are available as
SystemAccentColorLight3 , SystemAccentColorLight2 , SystemAccentColorLight1 , SystemAccentColorDark1 ,
SystemAccentColorDark2 , and SystemAccentColorDark3 . Also available programmatically via UISettings.GetColorValue
and the UIColorType enum.

Color theming
The user may also choose between a light or dark theme for the system. Some apps choose to change their theme
based on the users preference, while others opt out.
Apps using light theme are for scenarios involving productivity apps. Examples would be the suite of apps
available with Microsoft Office. Light theme affords the ease of reading long lengths of text in conjunction with
prolonged periods of time-at-task.
Dark theme allows more visible contrast of content for apps that are media centric or scenarios where users are
presented with an abundance of videos or imagery. In these scenarios, reading is not necessarily the primary task,
though a movie watching experience might be, and shown under low-light ambient conditions.
If your app doesnt quite fit either of these descriptions, consider following the system theme to let the user decide
what's right for them.
To make designing for themes easier, Windows provides an additional color palette that automatically adapts to
the theme.
Light theme
Base

Alt
List

Chrome
Dark theme
Base

Alt
List

Chrome
Changing the theme
You can change themes easily by changing the RequestedTheme property in your App.xaml:

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

</Application>

Removing the RequestedTheme means that your application will honor the users app mode settings, and they
will be able to choose to view your app in either the dark or light theme.
Make sure that you take the theme into consideration when creating your app, as the theme has a big impact on
the look of your app.

Accessibility
Our palette is optimized for screen usage. We recommend maintaining a contrast ratio for text of 4.5:1 against the
background for optimal readability. There are many free tools available to test whether or not your colors pass,
like Contrast Ratio.

Related articles
XAML Styles
XAML Theme Resources
Icons for UWP apps
5/22/2017 2 min to read Edit Online

Good icons harmonize with typography and with the rest of the design language. They dont mix metaphors, and
they communicate only whats needed, as speedily and simply as possible.

Linear scaling size ramps


16px x 16px 24px x 24px 32px x 32px 48px x 48px

Common shapes
Icons should generally maximize their given space with little padding. These shapes provide starting points for
sizing basic shapes.
Use the shape that corresponds to the icon's orientation and compose around these basic parameters. Icons don't
necessarily need to fill or fit completely inside the shape and may be adjusted as needed to ensure optimal balance.

Circle Square Triangle

Horizontal rectangle Vertical rectangle


Angles
In addition to using the same grid and line weight, icons are constructed with common elements.
Using only these angles in building shapes creates consistency across all our icons, and ensures the icons render
correctly.
These lines can be combined, joined, rotated, and reflected in creating icons.

1:1 1:2 1:3 1:4


45 26.57 (vertical) 18.43 (vertical) 14.04 (vertical)
63.43 (horizontal) 71.57 (horizontal) 75.96 (horizontal)

Here are some examples:


Curves
Curved lines are constructed from sections of a whole circle and should not be skewed unless needed to snap to
the pixel grid.

1/4 circle 1/8 circle

Geometric construction
We recommend using only pure geometric shapes when constructing icons.
Filled shapes
Icons can contain filled shapes when needed, but they should not be more than 4px at 32px 32px. Filled circles
should not be larger than 6px 6px.
Badges
A "badge" is a generic term used to describe an element added to an icon that's not meant to be integrated with
the base icon element. These usually convey other pieces of information about the icon like status or action. Other
commons terms include: overlay, annotation, or modifier.
Status badges utilize a filled, colored object that is on top of the icon, whereas action badges are integrated into the
icon in the same monochrome style and line weight.

Common status badges Common action badges

Badge color
Color badging should only be used to convey the state of an icon. The colors used in status badging convey specific
emotional messages to the user.

Green - #128B44 Blue - #2C71B9 Yellow - #FDC214

Positive: done, completed Neutral: help, notification Cautionary: alert, warning

Badge position
The default position for any status or action is the bottom right. Only use the other positions when the design will
not allow it.
Badge sizing
Badges should be sized to 1018 px on a 32 px 32 px grid.

Related articles
Guidelines for tile and icon assets
Motion for UWP apps
5/22/2017 3 min to read Edit Online

Purposeful, well-designed motion brings your app to life and makes the experience feel crafted and polished.
Motion helps your users understand context changes and where they are within your apps navigation hierarchy. It
ties experiences together with visual transitions. Motion adds a sense of pacing and dimensionality to the
experience.

Benefits of motion
Motion is more than making things move. Motion is a tool for creating a physical ecosystem for the user to live
inside and manipulate through a variety of input types, like mouse, keyboard, touch, and pen. The quality of the
experience depends on how well the app responds to the user, and what kind of personality the UI communicates.
Make sure motion serves a purpose in your app. The best Universal Windows Platform (UWP) apps use motion to
bring the UI to life. Motion should:
Give feedback based on the user's behavior.
Teach the user how to interact with the UI.
Indicate how to navigate to previous or succeeding views.
As a user spends more time inside your app, or as tasks in your app become more sophisticated, high-quality
motion becomes increasingly important: it can be used to change how the user perceives their cognitive load and
your app's ease of use. Motion has many other direct benefits:
Motion supports interaction and wayfinding.
Motion is directional: it moves forward and backward, in and out of content, leaving mental "breadcrumb"
clues as to how the user arrived at the present view. Transitions can help users learn how to operate new
applications by drawing analogies to tasks that the user is already familiar with.
Motion can give the impression of enhanced performance.
When network speeds lag or the system pauses to work, animations can make the user's wait feel shorter.
Animations can be used to let the user know that the app is processing, not frozen, and it can passively
surface new information that the user may be interested in.
Motion adds personality.
Motion is often the common thread that communicates your apps personality as a user moves through an
experience.
Motion adds elegance.
Fluid, responsive, motion makes experiences feel natural, creating emotional connections to the experience.

Examples of motion
Here are some examples of motion in an app.
Here, an app uses a connected animation to animate an item image as it continues to become part of the header
of the next page. The effect helps maintain user context across the transition.
Here, a visual parallax effect moves different objects at different rates when the UI scrolls or pans to create a feeling
of depth, perspective, and movement.

Types of motion
MOTION TYPE DESCRIPTION

Add and delete List animations let you insert or remove single or multiple
items from a collection, such as a photo album or a list of
search results.

Connected animation Connected animations let you create a dynamic and


compelling navigation experience by animating the transition
of an element between two different views. This helps the user
maintain their context and provides continuity between the
views. In a connected animation, an element appears to
continue between two views during a change in UI content,
flying across the screen from its location in the source view to
its destination in the new view. This emphasizes the common
content in between the views and creates a beautiful and
dynamic effect as part of a transition.
Content transition Content transition animations let you change the content of
an area of the screen while keeping the container or
background constant. New content fades in. If there is existing
content to be replaced, that content fades out.

Drill Use a drill-in animation when a user navigates forward in a


logical hierarchy, like from a master list to a detail page. Use a
drill-out animation when a user navigates backward in a
logical hierarchy, like from a detail page to a master page.

Fade Use fade animations to bring items into a view or to take


items out of a view. The two common fade animations are
fade-in and fade-out.

Parallax A visual parallax effect helps create a feeling of depth,


perspective, and movement. It achieves this effect by moving
different objects at different rates when the UI scrolls or pans.

Press feedback Pointer press animations provide users with visual feedback
when the user taps on an item. The pointer down animation
slightly shrinks and tilts the pressed item, and plays when an
item is first tapped. The pointer up animation, which restores
the item to its original position, is played when the user
releases the pointer.
Connected animation for UWP apps
8/9/2017 5 min to read Edit Online

What is connected animation?


Connected animations let you create a dynamic and compelling navigation experience by animating the transition
of an element between two different views. This helps the user maintain their context and provides continuity
between the views. In a connected animation, an element appears to continue between two views during a
change in UI content, flying across the screen from its location in the source view to its destination in the new view.
This emphasizes the common content in between the views and creates a beautiful and dynamic effect as part of a
transition.

See it in action
In this short video, an app uses a connected animation to animate an item image as it continues to become part
of the header of the next page. The effect helps maintain user context across the transition.

Connected animation and the Fluent Design System


The Fluent Design System helps you create modern, bold UI that incorporates light, depth, motion, material, and
scale. Connected animation is a Fluent Design System component that adds motion to your app.

Why connected animation?


When navigating between pages, its important for the user to understand what new content is being presented
after the navigation and how it relates to their intent when navigating. Connected animations provide a powerful
visual metaphor that emphasizes the relationship between two views by drawing the users focus to the content
shared between them. Additionally, connected animations add visual interest and polish to page navigation that
can help differentiate the motion design of your app.

When to use connected animation


Connected animations are generally used when changing pages, though they can be applied to any experience
where you are changing content in a UI and want the user to maintain context. You should consider using a
connected animation instead of a drill in navigation transition whenever there is an image or other piece of UI
shared between the source and destination views.

How to implement
Setting up a connected animation involves two steps:
1. Prepare an animation object on the source page, which indicates to the system that the source element will
participate in the connected animation
2. Start the animation on the destination page, passing a reference to the destination element
In between the two steps, the source element will appear frozen above other UI in the app, allowing you to perform
any other transition animations simultaneously. For this reason, you shouldnt wait more than ~250 milliseconds
in between the two steps since the presence of the source element may become distracting. If you prepare an
animation and do not start it within three seconds, the system will dispose of the animation and any subsequent
calls to TryStart will fail.
You can get access to the current ConnectedAnimationService instance by calling
ConnectedAnimationService.GetForCurrentView. To prepare an animation, call PrepareToAnimate on this
instance, passing a reference to a unique key and the UI element you want to use in the transition. The unique key
allows you to retrieve the animation later, for example on a different page.

ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("image", SourceImage);

To start the animation, call ConnectedAnimation.TryStart. You can retrieve the right animation instance by
calling ConnectedAnimationService.GetAnimation with the unique key you provided when creating the
animation.

ConnectedAnimation imageAnimation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("image");
if (imageAnimation != null)
{
imageAnimation.TryStart(DestinationImage);
}

Here is a full example of using ConnectedAnimationService to create a transition between two pages.
SourcePage.xaml

<Image x:Name="SourceImage"
Width="200"
Height="200"
Stretch="Fill"
Source="Assets/StoreLogo.png" />

SourcePage.xaml.cs

private void NavigateToDestinationPage()


{
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("image", SourceImage);
Frame.Navigate(typeof(DestinationPage));
}

DestinationPage.xaml
<Image x:Name="DestinationImage"
Width="400"
Height="400"
Stretch="Fill"
Source="Assets/StoreLogo.png" />

DestinationPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)


{
base.OnNavigatedTo(e);

ConnectedAnimation imageAnimation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("image");
if (imageAnimation != null)
{
imageAnimation.TryStart(DestinationImage);
}
}

Connected animation in list and grid experiences


Often, you will want to create a connected animation from or to a list or grid control. You can use two new
methods of ListView and GridView, PrepareConnectedAnimation and TryStartConnectedAnimationAsync,
to simplify this process. For example, say you have a ListView that contains an element with the name
"PortraitEllipse" in its data template.

<ListView x:Name="ContactsListView" Loaded="ContactsListView_Loaded">


<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:ContactsItem">
<Grid>

<Ellipse x:Name="PortraitEllipse" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

To prepare a connected animation with the ellipse corresponding to a given list item, call the
PrepareConnectedAnimation method with a unique key, the item, and the name PortraitEllipse.

void PrepareAnimationWithItem(ContactsItem item)


{
ContactsListView.PrepareConnectedAnimation("portrait", item, "PortraitEllipse");
}

Alternatively, to start an animation with this element as the destination, for example when navigating back from a
detail view, use TryStartConnectedAnimationAsync. If you have just loaded the data source for the ListView,
TryStartConnectedAnimationAsync will wait to start the animation until the corresponding item container has
been created.
private void ContactsListView_Loaded(object sender, RoutedEventArgs e)
{
ContactsItem item = GetPersistedItem(); // Get persisted item
if (item != null)
{
ContactsListView.ScrollIntoView(item);
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("portrait");
if (animation != null)
{
await ContactsListView.TryStartConnectedAnimationAsync(
animation, item, "PortraitEllipse");
}
}
}

Coordinated animation

A coordinated animation is a special type of entrance animation where an element will appear alongside the
connected animation target, animating in tandem with the connected animation element as it moves across the
screen. Coordinated animations can add more visual interest to a transition and further draw the users attention to
the context that is shared between the source and destination views. In these images, the caption UI for the item is
animating using a coordinated animation.
Use the two-parameter overload of TryStart to add coordinated elements to a connected animation. This example
demonstrates a coordinated animation of a Grid layout named DescriptionRoot that will enter in tandem with a
connected animation element named CoverImage.
DestinationPage.xaml

<Grid>
<Image x:Name="CoverImage" />
<Grid x:Name="DescriptionRoot" />
</Grid>

DestinationPage.xaml.cs
void OnNavigatedTo(NavigationEventArgs e)
{
var animationService = ConnectedAnimationService.GetForCurrentView();
var animation = animationService.GetAnimation("coverImage");

if (animation != null)
{
// Dont need to capture the return value as we are not scheduling any subsequent
// animations
animation.TryStart(CoverImage, new UIElement[] { DescriptionRoot });
}
}

Dos and donts


Use a connected animation in page transitions where an element is shared between the source and destination
pages.
Dont wait on network requests or other long-running asynchronous operations in between preparing and
starting a connected animation. You may need to pre-load the necessary information to run the transition ahead
of time, or use a low-resolution placeholder image while a high-resolution image loads in the destination view.
Use SuppressNavigationTransitionInfo to prevent a transition animation in a Frame if you are using
ConnectedAnimationService, since connected animations arent meant to be used simultaneously with the
default navigation transitions. See NavigationThemeTransition for more info on how to use navigation
transitions.

Download the code samples


See the Connected Animation sample in the WindowsUIDevLabs sample gallery.

Related articles
ConnectedAnimation
ConnectedAnimationService
NavigationThemeTransition
Content transition animations
5/22/2017 1 min to read Edit Online

Content transition animations let you change the content of an area of the screen while keeping the container or
background constant. New content fades in. If there is existing content to be replaced, that content fades out.

Important APIs
ContentThemeTransition class (XAML)

Do's and don'ts


Use an entrance animation when there is a set of new items to bring into an empty container. For example, after
the initial load of an app, part of the app's content might not be immediately available for display. When that
content is ready to be shown, use a content transition animation to bring that late content into the view.
Use content transitions to replace one set of content with another set of content that already resides in the same
container within a view.
When bringing in new content, slide that content up (from bottom to top) into the view against the general page
flow or reading order.
Introduce new content in a logical manner, for example, introduce the most important piece of content last.
If you have more than one container whose content is to be updated, trigger all of the transition animations
simultaneously without any staggering or delay.
Don't use content transition animations when the entire page is changing. In that case, use the page transition
animations instead.
Don't use content transition animations if the content is only refreshing. Content transition animations are
meant to show movement. For refreshes, use fade animations.

Related articles
For developers (XAML)
Animations overview
Animating content transitions
Quickstart: Animating your UI using library animations
ContentThemeTransition class
Add and delete animations
5/22/2017 1 min to read Edit Online

List animations let you insert or remove single or multiple items from a collection, such as a photo album or a list
of search results.

Important APIs
AddDeleteThemeTransition class

Do's and don'ts


Use list animations to add a single new item to an existing set of items. For example, use them when a new
email arrives or when a new photo is imported into an existing set.
Use list animations to add several items to a set at one time. For example, use them when you import a new set
of photos to an existing collection. The addition or deletion of multiple items should happen at the same time,
with no delay between the action on the individual objects.
Use add and delete list animations as a pair. Whenever you use one of these animations, use the corresponding
animation for the opposite action.
Use list animations with a list of items to which you can add or delete one element or group of elements at once.
Don't use list animations to display or remove a container. These animations are for members of a collection or
set that is already being displayed. Use pop-up animations to show or hide a transient container on top of the
app surface. Use content transition animations to display or replace a container that is part of the app surface.
Don't use list animations on an entire set of items. Use the content transition animations to add or remove an
entire collection within your container.

Related articles
Animations overview
Animating list additions and deletions
Quickstart: Animating your UI using library animations
AddDeleteThemeTransition class
Fade animations
5/22/2017 1 min to read Edit Online

Use fade animations to bring items into a view or to take items out of a view. The two common fade animations are
fade-in and fade-out.

Important APIs
FadeInThemeAnimation class
FadeOutThemeAnimation class

Do's and don'ts


When your app transitions between unrelated or text-heavy elements, use a fade-out followed by a fade-in. This
allows the outgoing object to completely disappear before the incoming object is visible.
Fade in the incoming element or elements on top of the outgoing elements if the size of the elements remains
constant, and if you want the user to feel that they're looking at the same item. Once the fade-in is complete, the
outgoing item can be removed. This is only a viable option when the outgoing item will be completely covered
by the incoming item.
Avoid fade animations to add or delete items in a list. Instead, use the list animations created for that purpose.
Avoid fade animations to change the entire contents of a page. Instead, use the page transition animations
created for that purpose.
Fade-out is a subtle way to remove an element.

Related articles
Animations overview
Animating fades
Quickstart: Animating your UI using library animations
FadeInThemeAnimation class
FadeOutThemeAnimation class
Pointer click animations
3/6/2017 1 min to read Edit Online

Use pointer animations to provide users with visual feedback when the user taps on an item. The pointer down
animation slightly shrinks and tilts the pressed item, and plays when an item is first tapped. The pointer up
animation, which restores the item to its original position, is played when the user releases the pointer.

Important APIs
PointerUpThemeAnimation class
PointerDownThemeAnimation class

Do's and don'ts


When you use a pointer up animation, immediately trigger the animation when the user releases the pointer.
This provides instant feedback to the user that their action has been recognized, even if the action triggered by
the tap (such as navigating to a new page) is slower to respond.

Related articles
Animations overview
Animating pointer clicks
Quickstart: Animating your UI using library animations
PointerUpThemeAnimation class
PointerDownThemeAnimation class
Parallax
8/9/2017 3 min to read Edit Online

IMPORTANT
This article describes functionality that hasnt been released yet and may be substantially modified before it's commercially
released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

Parallax is a visual effect where items closer to the viewer move faster than items in the background. Parallax
creates a feeling of depth, perspective, and movement. In a UWP app, you can use the ParallaxView control to
create a parallax effect.

Important APIs: ParallaxView class, VerticalShift property, HorizontalShift property

Parallax and the Fluent Design System


The Fluent Design System helps you create modern, bold UI that incorporates light, depth, motion, material, and
scale. Parallax is a Fluent Design System component that adds motion, depth, and scale to your app.

How it works in a user interface


In a UI, you can create a parallax effect by moving different objects at different rates when the UI scrolls or pans. To
demonstrate, lets look at two layers of content, a list and a background image. The list is placed on top of the
background image which already gives the illusion that the list might be closer to the viewer. Now, to achieve the
parallax effect, we want the object closest to us to travel faster than the object that is farther away. As the user
scrolls the interface, the list moves at a faster rate than the background image, which creates the illusion of depth.

Using the ParallaxView control to create a parallax effect


To create a parallax effect, you use the ParallaxView control. This control ties the scroll position of a foreground
element, such as a list, to a background element, such as an image. As you scroll through the foreground element,
it animates the background element to create a parallax effect.
To use the ParallaxView control, you provide a Source element, a background element, and set the VerticalShift
(for vertical scrolling) and/or HorizontalShift (for horizontal scrolling) properties to a value greater than zero.
The Source property takes a reference to the foreground element. For the parallax effect to occur, the
foreground should be a ScrollViewer or an element that contains a ScrollViewer, such as a ListView or a
RichTextBox.
To set the background element, you add that element as a child of the ParallaxView control. The
background element can be any UIElement, such as an Image or a panel that contains additional UI
elements.
To create a parallax effect, the ParallaxView must be behind the foreground element. The Grid and Canvas panels
let you layer items on top of each other, so they work well with the ParallaxView control.
This example creates a parallax effect for a list:

<Grid>
<ParallaxView Source="{x:Bind ForegroundElement}" VerticalShift="50">

<!-- Background element -->


<Image x:Name="BackgroundImage" Source="Assets/turntable.png"
Stretch="UniformToFill"/>
</ParallaxView>

<!-- Foreground element -->


<ListView x:Name="ForegroundElement">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
<x:String>Item 4</x:String>
<x:String>Item 5</x:String>
<x:String>Item 6</x:String>
<x:String>Item 7</x:String>
<x:String>Item 8</x:String>
<x:String>Item 9</x:String>
<x:String>Item 10</x:String>
<x:String>Item 11</x:String>
<x:String>Item 13</x:String>
<x:String>Item 14</x:String>
<x:String>Item 15</x:String>
<x:String>Item 16</x:String>
<x:String>Item 17</x:String>
<x:String>Item 18</x:String>
<x:String>Item 19</x:String>
<x:String>Item 20</x:String>
<x:String>Item 21</x:String>
</ListView>
</Grid>

The ParallaxView automatically adjusts the size of the image so it works for the parallax operation so you dont
have to worry about the image scrolling out of view.

Customizing the parallax effect


The VerticalShift and HorizontalShift properties let you control degree of the parallax effect.
The VerticalShift property specifies how far we want the background to vertically shift during the entire parallax
operation. A value of 0 means the the background doesn't move at all.
The HorizontalShift property specifies how far we want the background to horizontally shift during the entire
parallax operation. A value of 0 means the the background doesn't move at all.
Larger values create a more dramatic effect.
For the complete list of ways to customize parallax, see the ParallaxView class.

Dos and donts


Use parallax in lists with a background image
Consider using parallax in ListViewItems when ListViewItems contain an image
Dont use it everywhere, overuse can diminish its impact

Related articles
ParallaxView class
Reveal
8/9/2017 3 min to read Edit Online

IMPORTANT
This article describes functionality that hasnt been released yet and may be substantially modified before it's commercially
released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

Reveal is a lighting effect that helps bring depth and focus to your app's interactive elements.

Important APIs: RevealBrush class, RevealBackgroundBrush class, RevealBorderBrush class,


RevealBrushHelper class, VisualState class

The Reveal behavior does this by revealing pieces of elements around hero (or focal) content when the mouse or
focus rectangle is over the desired areas.

Through exposing the hidden borders around objects, Reveal gives users a better understanding of the space that
they are interacting with, and helps them understand the actions available. This is especially important in list
controls and controls with backplates.

Reveal and the Fluent Design System


The Fluent Design System helps you create modern, bold UI that incorporates light, depth, motion, material, and
scale. Reveal is a Fluent Design System component that adds light to your app.

What is reveal?
There are two main visual components to Reveal: the Hover Reveal behavior, and the Border Reveal behavior.
The Hover Reveal is tied directly to the content being hovered over (via pointer or focus input), and applies a
gentle halo shape around the hovered or focused item, letting you know you can interact with it.
The Border Reveal is applied to the focused item and items nearby. This shows you that those nearby objects can
take actions similar to the one currently focused.
The Reveal recipe breakdown is:
Border Reveal will be on top of all content but on the designated edges
Text and content will be displayed directly under Border Reveal
Hover Reveal will be beneath content and text
The backplate (that turns on and enables Hover Reveal)
The background (background of control)

How to use it
Reveal exposes geometry around your cursor when you need it, and seamlessly fades it out once youve moved
on.
Reveal is best used when enabled on the main content of your app (hero content) that has implied boundries and
backplates to them. Reveal should additionally be used on collection or list-like controls.
Controls that automatically use Reveal
ListView
TreeView
NavigationView
AutosuggestBox

Enabling Reveal on other common controls


If you have a scenario where Reveal should be applied (these controls are main content and/or are used in a list or
collection orientation), we've provided opt-in resourse styles that allow you to enable Reveal for those types of
situations.
These controls do not have Reveal by default as they are smaller controls that are usually helper controls to the
main focal points of your application; but every app is different, and if these controls are used the most in your
app, we've provided some styles to aid with that:

CONTROL NAME RESOURCE NAME

Button ButtonRevealStyle

ToggleButton ToggleButtonRevealStyle

RepeatButton RepeatButtonRevealStyle

AppBarButton AppBarButtonRevealStyle

SemanticZoom SemanticZoomRevealStyle

ComboBoxItem ComboxBoxItemRevealStyle

To apply these styles, simply update the Style property like so:

<Button Content="Button Content" Style="{StaticResource ButtonRevealStyle}"/>

NOTE
The 16190 version of the SDK does not make these styles automatically available. To get them, you need to manually copy
them from generic.xaml into your app. Generic.xaml is typically located at C:\Program Files (x86)\Windows
Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.16190.0\Generic. This issue will be fixed in a later build.

Enabling Reveal on custom controls


To enable Reveal on custom controls or re-templated controls, you can go into the style for that control in the
Visual States of that control's template, specify Reveal on the root grid:
<VisualState x:Name="PointerOver">
<VisualState.Setters>
<Setter Target="RootGrid.(RevealBrushHelper.State)" Value="PointerOver" />
<Setter Target="RootGrid.Background" Value="{ThemeResource ButtonRevealBackgroundPointerOver}"/>
<Setter Target="ContentPresenter.BorderBrush" Value="{ThemeResource ButtonRevealBorderBrushPointerOver}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource ButtonForegroundPointerOver}"/>
</VisualState.Setters>
</VisualState>

To get the pull effect of Reveal you'll need to add the same RevealBrushHelper to the PressedState as well:

<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="RootGrid.(RevealBrushHelper.State)" Value="Pressed" />
<Setter Target="RootGrid.Background" Value="{ThemeResource ButtonRevealBackgroundPressed}"/>
<Setter Target="ContentPresenter.BorderBrush" Value="{ThemeResource ButtonRevealBorderBrushPressed}"/>
<Setter Target="ContentPresenter.Foreground" Value="{ThemeResource ButtonForegroundPressed}"/>
</VisualState.Setters>
</VisualState>

Using our system resource Reveal means we will handle all the theme changes for you.

Do's and don'ts


Do have Reveal on elements that the user can take actions on - Reveal should not be on static content
Do show Reveal in lists or collections of data
Do apply Reveal to clearly contained content with backplates
Dont show Reveal on static backgrounds, text, or images that you cant interact with
Dont apply Reveal to unrelated floating content
Dont use Reveal in one-off, isolated situations, like content dialogs or notifications
Dont use Reveal in security decisions, as it may draw attention away from the message you need to deliver to
your user

Related articles
RevealBrush class
Acrylic
Composition Effects
Sound
5/22/2017 4 min to read Edit Online

There are many ways to use sound to enhance your app. You can use to sound to supplement other UI elements,
enabling users to recognize events audibly. Sound can be an effective user interface element for people with visual
disabilities. You can use sound to create an atmosphere that immerses the user; for example, you might play a
whimsical soundtrack in the background of puzzle game, or use ominous sound effects for a horror/survival game.

Sound Global API


UWP provides an easily accessible sound system that allows you to simply "flip a switch" and get an immersive
audio experience across your entire app.
The ElementSoundPlayer is an integrated sound system within XAML, and when turned on all default controls
will play sounds automatically.

ElementSoundPlayer.State = ElementSoundPlayerState.On;

The ElementSoundPlayer has three different states: On Off and Auto.


If set to Off, no matter where your app is run, sound will never play. If set to On sounds for your app will play on
every platform.
Sound for TV and Xbox
Sound is a key part of the 10-foot experience, and by default, the ElementSoundPlayer's state is Auto, meaning
that you will only get sound when your app is running on Xbox. To understand more about designing for Xbox and
TV, please see Designing for Xbox and TV.

Sound Volume Override


All sounds within the app can be dimmed with the Volume control. However, sounds within the app cannot get
louder than the system volume.
To set the app volume level, call:

ElementSoundPlayer.Volume = 0.5f;

Where maximum volume (relative to system volume) is 1.0, and minimum is 0.0 (essentially silent).

Control Level State


If a control's default sound is not desired, it can be disabled. This is done through the ElementSoundMode on the
control.
The ElementSoundMode has two states: Off and Default. When not set, it is Default. If set to Off, every sound
that control plays will be muted except for focus.

<Button Name="ButtonName" Content="More Info" ElementSoundMode="Off"/>


ButtonName.ElementSoundState = ElementSoundMode.Off;

Is This The Right Sound?


When creating a custom control, or changing an existing control's sound, it is important to understand the usages
of all the sounds the system provides.
Each sound relates to a certain basic user interaction, and although sounds can be customized to play on any
interaction, this section serves to illustrate the scenarios where sounds should be used to maintain a consistent
experience across all UWP apps.
Invoking an Element
The most common control-triggered sound in our system today is the Invoke sound. This sound plays when a
user invokes a control through a tap/click/enter/space or press of the 'A' button on a gamepad.
Typically, this sound is only played when a user explicitly targets a simple control or control part through an input
device.
To play this sound from any control event, simply call the Play method from ElementSoundPlayer and pass in
ElementSound.Invoke:

ElementSoundPlayer.Play(ElementSoundKind.Invoke);

Showing & Hiding Content


There are many flyouts, dialogs and dismissible UIs in XAML, and any action that triggers one of these overlays
should call a Show or Hide sound.
When an overlay content window is brought into view, the Show sound should be called:

ElementSoundPlayer.Play(ElementSoundKind.Show);

Conversely when an overlay content window is closed (or is light dismissed), the Hide sound should be called:

ElementSoundPlayer.Play(ElementSoundKind.Hide);

Navigation Within a Page


When navigating between panels or views within an app's page (see Hub or Tabs and Pivots), there is typically
bidirectional movement. Meaning you can move to the next view/panel or the previous one, without leaving the
current app page you're on.
The audio experience around this navigation concept is encompassed by the MovePrevious and MoveNext
sounds.
When moving to a view/panel that is considered the next item in a list, call:

ElementSoundPlayer.Play(ElementSoundKind.MoveNext);

And when moving to a previous view/panel in a list considered the previous item, call:

ElementSoundPlayer.Play(ElementSoundKind.MovePrevious);
Back Navigation
When navigating from the current page to the previous page within an app the GoBack sound should be called:

ElementSoundPlayer.Play(ElementSoundKind.GoBack);

Focusing on an Element
The Focus sound is the only implicit sound in our system. Meaning a user isn't directly interacting with anything,
but is still hearing a sound.
Focusing happens when a user navigates through an app, this can be with the gamepad/keyboard/remote or
kinect. Typically the Focus sound does not play on PointerEntered or mouse hover events.
To set up a control to play the Focus sound when your control receives focus, call:

ElementSoundPlayer.Play(ElementSoundKind.Focus);

Cycling Focus Sounds


As an added feature to calling ElementSound.Focus, the sound system will, by default, cycle through 4 different
sounds on each navigation trigger. Meaning that no two exact focus sounds will play right after the other.
The purpose behind this cycling feature is to keep the focus sounds from becoming monotonous and from being
noticeable by the user; focus sounds will be played most often and therefore should be the most subtle.

Related articles
Designing for Xbox and TV
Typography
6/22/2017 6 min to read Edit Online

As the visual representation of language, typographys main task is to be clear. Its style should never get in the way
of that goal. But typography also has an important role as a layout componentwith a powerful effect on the
density and complexity of the designand on the users experience of that design.

Typeface
Weve selected Segoe UI for use on all Microsoft digital designs. Segoe UI provides a wide range of characters and
is designed to maintain optimal legibility across sizes and pixel densities. It offers a clean, light, and open aesthetic
that complements the content of the system.

Weights
We approach typography with an eye to simplicity and efficiency. We choose to use one typeface, a minimum of
weights and sizes, and a clear hierarchy. Positioning and alignment follow the default style for the given language.
In English the sequence runs left to right, top to bottom. Relationships between text and images are clear and
straightforward.
Line spacing

Line spacing should be calculated at 125% of the font size, rounding to the closest multiple of four when necessary.
For example with 15px Segoe UI, 125% of 15px is 18.75px. We recommend rounding up and setting line height to
20px to stay on the 4px grid. This ensures a good reading experience and adequate space for diacritical marks. See
the Type ramp section below for specific examples.
When stacking larger type on top of smaller type, the distance from the last baseline of the larger type to the first
baseline of the smaller type should be equal to the larger types line height.

In XAML, this is accomplished by stacking two TextBlocks and setting the appropriate margin.

<StackPanel Width="200">
<!-- Setting a bottom margin of 3px on the header
puts the baseline of the body text exactly 24px
below the baseline of the header. 24px is the
recommended line height for a 20px font size,
which is whats set in SubtitleTextBlockStyle.
The bottom margin will be different for
different font size pairings. -->
<TextBlock
Style="{StaticResource SubtitleTextBlockStyle}"
Margin="0,0,0,3"
Text="Header text" />
<TextBlock
Style="{StaticResource BodyTextBlockStyle}"
TextWrapping="Wrap"
Text="This line of text should be positioned where the above header would have wrapped." />
</StackPanel>

Kerning and tracking


Segoe is a humanist typeface, with a soft, friendly appearance, it has organic, open forms based on handwritten
text. To ensure optimum legibility and maintain its humanist integrity, the kerning and tracking settings must have
specific values. Kerning should be set to metrics and tracking should be set to 0.

Word and letter spacing


Similar to kerning and tracking, word spacing and letter spacing use specific settings to ensure optimum legibility
and humanist integrity. Word spacing by default is always 100% and letter spacing should be set to 0.
NOTE
In a XAML text control use Typogrphy.Kerning to control kerning and FontStretch to control tracking. By default
Typography.Kerning is set to true and FontStretch is set to Normal, which are the recommended values.

Alignment
Generally, we recommend that visual elements and columns of type be left-aligned. In most instances, this flush-
left and ragged-right approach provides consistent anchoring of the content and a uniform layout.

Line endings
When typography is not positioned as flush left and ragged right, try to ensure even line endings and avoid
hyphenation.

Paragraphs
To provide aligned column edges, paragraphs should be indicated by skipping a line without indentation.
Character count
If a line is too short, the eye will have to travel left and right too often, breaking the readers rhythm. If possible, 50
60 letters per line is best for ease of reading.
Segoe provides a wide range of characters and is designed to maintain optimal legibility in both small and large
sizes as well as low and high pixel densities. Using the optimal number of letters in a text column line ensures good
legibility in an application.
Lines that are too long will strain the eye and may disorient the user. Lines that are too short force the readers eye
to travel too much and can cause fatigue.

Hanging text alignment


The horizontal alignment of icons with text can be handled in a number of ways depending on the size of the icon
and the amount of text. When the text, either single or multiple lines, fits within the height of the icon, the text
should be vertically centered.
Once the height of the text extends beyond the height of the icon, the first line of text should align vertically and the
additional text should flow on naturally below. When using characters with larger cap, ascender and descender
heights, care should be taken to observe the same alignment guidance.

NOTE
XAMLs TextBlock.TextLineBounds property provides access to the cap height and baseline font metrics. It can be used to
visually vertically center or top-align type.

Clipping and ellipses


Clip by defaultassume that text will wrap unless the redline specifies otherwise. When using non-wrapping text,
we recommend clipping rather than using ellipses. Clipping can occur at the edge of the container, at the edge of
the device, at the edge of a scrollbar, etc.
Exceptionsfor containers which are not well-defined (e.g. no differentiating background color), then non-
wrapping text can be redlined to use the ellipse .
Type ramp
The type ramp establishes a crucial design relationship from headlines to body text and ensures a clear and
understandable hierarchy between the different levels. This hierarchy builds a structure which enables users to
easily navigate through written communication.

All sizes are in effective pixels. For more details, see Intro to UWP app design.
NOTE
Most levels of the ramp are available as XAML static resources that follow the *TextBlockStyle naming convention (ex:
HeaderTextBlockStyle ).

Primary and secondary text


To create additional hierarchy beyond the type ramp, set secondary text to 60% opacity. In the theming color
palette, you would use BaseMedium. Primary text should always be at 100% opacity, or BaseHigh.

All caps titles


Certain page titles should be in ALL CAPS to add yet another dimension of hierarchy. These titles should use
BaseAlt with the character spacing set to 75 thousandths of an em. This treatment may also be used to help with
app navigation.
However, proper names change their meaning when capitalized in certain languages, so any page titles based on
names or user input should not be converted to all caps.

Dos and donts


Use Body for most text
Use Base for titles when space is constrained
Incorporate SubtitleAlt to create contrast and hierarchy by emphasizing top level content
Dont use Caption for long strings or any primary action
Dont use Header or Subheader if text needs to wrap
Dont combine Subtitle and SubtitleAlt on the same page

Related articles
Text controls
Fonts
Segoe MDL2 icons
Fonts for UWP apps
5/22/2017 3 min to read Edit Online

This article lists the recommended fonts for UWP apps. These fonts are guaranteed to be available in all Windows
10 editions that support UWP apps.

Important APIs
FontFamily property

The UWP typography guide recommends that apps use the Segoe UI font, and although Segoe UI is a great choice
for most apps, you don't have to use it for everything. You might use other fonts for certain scenarios, such as
reading, or when displaying text in certain non-English languages.

Sans-serif fonts
Sans-serif fonts are a great choice for headings and UI elements.

FONT-FAMILY STYLES NOTES

Arial Regular, Italic, Bold, Bold Italic, Black Supports European and Middle Eastern
scripts (Latin, Greek, Cyrillic, Arabic,
Armenian, and Hebrew) Black weight
supports European scripts only.

Calibri Regular, Italic, Bold, Bold Italic, Light, Supports European and Middle Eastern
Light Italic scripts (Latin, Greek, Cyrillic, Arabic and
Hebrew). Arabic available in the
uprights only.

Consolas Regular, Italic, Bold, Bold Italic Fixed width font that supports
European scripts (Latin, Greek and
Cyrillic).

Segoe UI Regular, Italic, Light Italic, Black Italic, User-interface font for European and
Bold, Bold Italic, Light, Semilight, Middle East scripts (Arabic, Armenian,
Semibold, Black Cyrillic, Georgian, Greek, Hebrew, Latin),
and also Lisu script.

Segoe UI Historic Regular Fallback font for historic scripts

Selawik Regular, Semilight, Light, Bold, Semibold An open-source font that's metrically
compatible with Segoe UI, intended for
apps on other platforms that dont
want to bundle Segoe UI. Get Selawik
on GitHub.

Verdana Regular, Italic, Bold, Bold Italic Supports European scripts (Latin, Greek,
Cyrillic and Armenian).

Serif fonts
Serif fonts are good for presenting large amounts of text.

FONT-FAMILY STYLES NOTES

Cambria Regular Serif font that supports European


scripts (Latin, Greek, Cyrillic).

Courier New Regular, Italic, Bold, Bold Italic Serif fixed width font supports European
and Middle Eastern scripts (Latin, Greek,
Cyrillic, Arabic, Armenian, and Hebrew).

Georgia Regular, Italic, Bold, Bold Italic Supports European scripts (Latin, Greek
and Cyrillic).

Times New Roman Regular, Italic, Bold, Bold Italic Legacy font that supports European
scripts (Latin, Greek, Cyrillic, Arabic,
Armenian, Hebrew).

Symbols and icons


FONT-FAMILY STYLES NOTES

Segoe MDL2 Assets Regular User-interface font for app icons. For
more info, see the Segoe MDL2 assets
article.

Segoe UI Emoji Regular

Segoe UI Symbol Regular Fallback font for symbols

Fonts for non-Latin languages


Although many of these fonts provide Latin characters.

FONT-FAMILY STYLES NOTES

Ebrima Regular, Bold User-interface font for African scripts


(Ethiopic, N'Ko, Osmanya, Tifinagh, Vai).

Gadugi Regular, Bold User-interface font for North American


scripts (Canadian Syllabics, Cherokee).

Javanese Text Regular Fallback font for Regular Fallback font for Javanese script
Javanese script

Leelawadee UI Regular, Semilight, Bold User-interface font for Southeast Asian


scripts (Buginese, Lao, Khmer, Thai).

Malgun Gothic Regular User-interface font for Korean.

Microsoft Himalaya Regular Fallback font for Tibetan script.

Microsoft JhengHei UI Regular, Bold, Light User-interface font for Traditional


Chinese.
FONT-FAMILY STYLES NOTES

Microsoft New Tai Lue Regular Fallback font for New Tai Lue script.

Microsoft PhagsPa Regular Fallback font for Phags-pa script.

Microsoft Tai Le Regular Fallback font for Tai Le script.

Microsoft YaHei UI Regular, Bold, Light User-interface font for Simplified


Chinese.

Microsoft Yi Baiti Regular Fallback font for Yi script.

Mongolian Baiti Regular Fallback font for Mongolian script.

MV Boli Regular Fallback font for Thaana script.

Myanmar Text Regular Fallback font for Myanmar script.

Nirmala UI Regular, Semilight, Bold User-interface font for South Asian


scripts (Bangla, Devanagari, Gujarati,
Gurmukhi, Kannada, Malayalam, Odia,
Ol Chiki, Sinhala, Sora Sompeng, Tamil,
Telugu)

SimSun Regular A legacy Chinese UI font.

Yu Gothic Light, Regular, Medium, Bold Use Yu Gothic Medium for body text
and similar content.

Yu Gothic UI Light, Semilight, Regular, Semibold, Bold User-interface font for Japanese.

Globalizing/localizing fonts
Use the LanguageFont font-mapping APIs for programmatic access to the recommended font family, size, weight,
and style for a particular language. The LanguageFont object provides access to the correct font info for various
categories of content including UI headers, notifications, body text, and user-editable document body fonts. For
more info, see Adjusting layout and fonts to support globalization.

Get the samples


Downloadable fonts sample
UI basics sample
Line spacing with DirectWrite sample

Related articles
Adjusting layout and fonts to support globalization
Segoe MDL2
Text controls)
XAML theme resources
Segoe MDL2 icons
6/22/2017 15 min to read Edit Online

This article lists the icons provided by the Segoe MDL2 Assets font.

Important APIs
Symbol enumeration (XAML)

About Segoe MDL2 Assets


With the release Windows 10, the Segoe MDL2 Assets font replaced the Windows 8/8.1 Segoe UI Symbol icon
font. ( Segoe UI Symbol will still be available as a "legacy" resource, but we recommend updating your app to use
the new Segoe MDL2 Assets.)
Most of the icons and UI controls included in the Segoe MDL2 Assets font are mapped to the Private Use Area of
Unicode (PUA). The PUA allows font developers to assign private Unicode values to glyphs that dont map to
existing code points. This is useful when creating a symbol font, but it creates an interoperability problem. If the
font is not available, the glyphs wont show up. Only use these glyphs when you can specify the Segoe MDL2
Assets font.
Use these glyphs only when you can explicitly specify the Segoe MDL2 Assets font. If you are working with tiles,
you can't use these glyphs because you can't specify the tile font and PUA glyphs are not available via font-
fallback.
Unlike with Segoe UI Symbol, the icons in the Segoe MDL2 Assets font are not intended for use in-line with text.
This means that some older "tricks" like the progressive disclosure arrows no longer apply. Likewise, since all of
the new icons are sized and positioned the same, they do not have to be made with zero width; we have just made
sure they work as a set. Ideally, you can overlay two icons that were designed as a set and they will fall into place.
We may do this to allow colorization in the code. For example, U+EA3A and U+EA3B were created for the Start tile
Badge status. Because these are already centered the circle fill can be colored for different states.

Layering and mirroring


All glyphs in Segoe MDL2 Assets have the same fixed width with a consistent height and left origin point, so
layering and colorization effects can be achieved by drawing glyphs directly on top of each other. This example
show a black outline drawn on top of the zero-width red heart.

Many of the icons also have mirrored forms available for use in languages that use right-to-left text directionality
such as Arabic, Farsi, and Hebrew.

Symbol enumeration
If you are developing an app in C#/VB/C++ and XAML, you can use the Symbol enumeration to use icons from
the Segoe MDL2 Assets font.

How do I get this font?


To obtain Segoe MDL2 Assets, you must install Windows 10.

Icon list
Symbol Unicode point Description

E001 CheckMarkLegacy

E002 CheckboxFillLegacy

E003 CheckboxLegacy

E004 CheckboxIndeterminateLegacy

E005 CheckboxCompositeReversedLegacy

E006 HeartLegacy

E007 HeartBrokenLegacy

E008 CheckMarkZeroWidthLegacy

E009 CheckboxFillZeroWidthLegacy

E00A RatingStarFillZeroWidthLegacy

E00B HeartFillZeroWidthLegacy

E00C HeartBrokenZeroWidthLegacy

E00E ScrollChevronLeftLegacy

E00F ScrollChevronRightLegacy

E010 ScrollChevronUpLegacy

E011 ScrollChevronDownLegacy

E012 ChevronLeft3Legacy
E013 ChevronRight3Legacy

E014 ChevronUp3Legacy

E015 ChevronDown3Legacy

E016 ScrollChevronLeftBoldLegacy

E017 ScrollChevronRightBoldLegacy

E018 ScrollChevronUpBoldLegacy

E019 ScrollChevronDownBoldLegacy

E052 RevealPasswordLegacy

E07F EaseOfAccessLegacy

E081 CheckmarkListviewLegacy

E082 RatingStarFillReducedPaddingHTMLLeg
acy

E087 KeyboardStandardLegacy

E08F KeyboardSplitLegacy

E094 SearchboxLegacy

E096 ChevronLeft1Legacy

E097 ChevronRight1Legacy

E098 ChevronUp1Legacy

E099 ChevronDown1Legacy

E09A ChevronLeft2Legacy
E09B ChevronRight2Legacy

E09C ChevronUp2Legacy

E09D ChevronDown2Legacy

E09E ChevronLeft4Legacy

E09F ChevronRight4Legacy

E0A0 ChevronUp4Legacy

E0A1 ChevronDown4Legacy

E0A2 CheckboxCompositeLegacy

E0A5 HeartFillLegacy

E0A6 BackBttnArrow42Legacy

E0AB BackBttnMirroredArrow42Legacy

E0AD BackBttnMirroredArrow20Legacy

E0AE ArrowHTMLLegacyMirrored

E0B4 RatingStarFillLegacy

E0B5 RatingStarFillSmallLegacy

E0B8 SemanticZoomLegacy

E0C4 BackBttnArrow20Legacy

E0D5 ArrowHTMLLegacy

E0E2 ChevronFlipLeftLegacy
E0E3 ChevronFlipRightLegacy

E0E4 ChevronFlipUpLegacy

E0E5 ChevronFlipDownLegacy

E0E7 CheckmarkMenuLegacy

E100 PreviousLegacy

E101 NextLegacy

E102 PlayLegacy

E103 PauseLegacy

E104 EditLegacy

E105 SaveLegacy

E106 ClearLegacy

E107 DeleteLegacy

E108 RemoveLegacy

E109 AddLegacy

E10A CancelLegacy

E10B AcceptLegacy

E10C MoreLegacy

E10D RedoLegacy

E10E UndoLegacy
E10F HomeLegacy

E110 UpLegacy

E111 ForwardLegacy

E112 BackLegacy

E113 FavoriteLegacy

E114 CameraLegacy

E115 SettingsLegacy

E116 VideoLegacy

E117 SyncLegacy

E118 DownloadLegacy

E119 MailLegacy

E11A FindLegacy

E11B HelpLegacy

E11C UploadLegacy

E11D EmojiLegacy

E11E TwoPageLegacy

E11F LeaveChatLegacy

E120 MailForwardLegacy

E121 ClockLegacy
E122 SendLegacy

E123 CropLegacy

E124 RotateCameraLegacy

E125 PeopleLegacy

E126 ClosePaneLegacy

E127 OpenPaneLegacy

E128 WorldLegacy

E129 FlagLegacy

E12A PreviewLinkLegacy

E12B GlobeLegacy

E12C TrimLegacy

E12D AttachCameraLegacy

E12E ZoomInLegacy

E12F BookmarksLegacy

E130 DocumentLegacy

E131 ProtectedDocumentLegacy

E132 PageFillLegacy

E133 MultiSelectLegacy

E134 CommentLegacy
E135 MailFillLegacy

E136 ContactInfoLegacy

E137 HangUpLegacy

E138 ViewAllLegacy

E139 MapPinLegacy

E13A PhoneLegacy

E13B VideoChatLegacy

E13C SwitchLegacy

E13D ContactLegacy

E13E RenameLegacy

E13F ExpandTileLegacy

E140 ReduceTileLegacy

E141 PinLegacy

E142 MusicInfoLegacy

E143 GoLegacy

E144 KeyBoardLegacy

E145 DockLeftLegacy

E146 DockRightLegacy

E147 DockBottomLegacy
E148 RemoteLegacy

E149 RefreshLegacy

E14A RotateLegacy

E14B ShuffleLegacy

E14C ListLegacy

E14D ShopLegacy

E14E SelectAllLegacy

E14F OrientationLegacy

E150 ImportLegacy

E151 ImportAllLegacy

E152 ShowAllFiles3Legacy

E153 ShowAllFiles1Legacy

E154 ShowAllFilesLegacy

E155 BrowsePhotosLegacy

E156 WebcamLegacy

E158 PictureLegacy

E159 SaveLocalLegacy

E15A CaptionLegacy

E15B StopLegacy
E15C ShowResultsLegacy

E15D VolumeLegacy

E15E RepairLegacy

E15F MessageLegacy

E160 PageLegacy

E161 CalendarDayLegacy

E162 CalendarWeekLegacy

E163 CalendarLegacy

E164 CharactersLegacy

E165 MailReplyAllLegacy

E166 ReadLegacy

E167 LinkLegacy

E168 AccountsLegacy

E169 ShowBccLegacy

E16A HideBccLegacy

E16B CutLegacy

E16C AttachLegacy

E16D PasteLegacy

E16E FilterLegacy
E16F CopyLegacy

E170 Emoji2Legacy

E171 ImportantLegacy

E172 MailReplyLegacy

E173 SlideshowLegacy

E174 SortLegacy

E175 ListLegacyMirrored

E176 ExpandTileLegacyMirrored

E177 ReduceTileLegacyMirrored

E178 ManageLegacy

E179 AllAppsLegacy

E17A DisconnectDriveLegacy

E17B MapDriveLegacy

E17C NewWindowLegacy

E17D OpenWithLegacy

E181 ContactPresenceLegacy

E182 PriorityLegacy

E183 UploadSkyDriveLegacy

E184 GotoTodayLegacy
E185 FontLegacy

E186 FontColorLegacy

E187 Contact2Legacy

E188 FolderLegacy

E189 AudioLegacy

E18A PlaceFolderLegacy

E18B ViewLegacy

E18C SetlockScreenLegacy

E18D SetTileLegacy

E18E CCJapanLegacy

E18F CCEuroLegacy

E190 CCLegacy

E191 StopSlideshowLegacy

E192 PermissionsLegacy

E193 HighlightLegacy

E194 DisableUpdatesLegacy

E195 UnfavoriteLegacy

E196 UnpinLegacy

E197 OpenLocalLegacy
E198 MuteLegacy

E199 ItalicLegacy

E19A UnderlineLegacy

E19B BoldLegacy

E19C MoveToFolderLegacy

E19D LikeDislikeLegacy

E19E DislikeLegacy

E19F LikeLegacy

E1A0 AlignRightLegacy

E1A1 AlignCenterLegacy

E1A2 AlignLeftLegacy

E1A3 ZoomLegacy

E1A4 ZoomOutLegacy

E1A5 OpenFileLegacy

E1A6 OtherUserLegacy

E1A7 AdminLegacy

E1A8 MailForwardLegacyMirrored

E1AA GoLegacyMirrored

E1AB DockLeftLegacyMirrored
E1AC DockRightLegacyMirrored

E1AD ImportLegacyMirrored

E1AE ImportAllLegacyMirrored

E1AF MailReplyLegacyMirrored

E1B0 ItalicCLegacy

E1B1 BoldGLegacy

E1B2 UnderlineSLegacy

E1B3 BoldFLegacy

E1B4 ItalicKLegacy

E1B5 UnderlineULegacy

E1B6 ItalicILegacy

E1B7 BoldNLegacy

E1B8 UnderlineRussianLegacy

E1B9 BoldRussionLegacy

E1BA FontStyleKoreanLegacy

E1BB UnderlineLKoreanLegacy

E1BC ItalicKoreanLegacy

E1BD BoldKoreanLegacy

E1BE FontColorKoreanLegacy
E1BF ClosePaneLegacyMirrored

E1C0 OpenPaneLegacyMirrored

E1C2 EditLegacyMirrored

E1C3 StreetLegacy

E1C4 MapLegacy

E1C5 ClearSelectionLegacy

E1C6 FontDecreaseLegacy

E1C7 FontIncreaseLegacy

E1C8 FontSizeLegacy

E1C9 CellPhoneLegacy

E1CA ReshareLegacy

E1CB TagLegacy

E1CC RepeatOneLegacy

E1CD RepeatAllLegacy

E1CE OutlineStarLegacy

E1CF SolidStarLegacy

E1D0 CalculatorLegacy

E1D1 DirectionsLegacy

E1D2 LocationLegacy
E1D3 LibraryLegacy

E1D4 PhoneBookLegacy

E1D5 MemoLegacy

E1D6 MicrophoneLegacy

E1D7 PostUpdateLegacy

E1D8 BackToWindowLegacy

E1D9 FullScreenLegacy

E1DA NewFolderLegacy

E1DB CalendarReplyLegacy

E1DC CalendarLegacyMirrored

E1DD UnsyncFolderLegacy

E1DE ReportHackedLegacy

E1DF SyncFolderLegacy

E1E0 BlockContactLegacy

E1E1 SwitchAppsLegacy

E1E2 AddFriendLegacy

E1E3 TouchPointerLegacy

E1E4 GoToStartLegacy

E1E5 ZeroBarsLegacy
E1E6 OneBarLegacy

E1E7 TwoBarsLegacy

E1E8 ThreeBarsLegacy

E1E9 FourBarsLegacy

E1EA ItalicRussianLegacy

E1EC AllAppsLegacyMirrored

E1ED OpenWithLegacyMirrored

E1EE BookmarksLegacyMirrored

E1EF MultiSelectLegacyMirrored

E1F1 ShowResultsLegacyMirrored

E1F2 MailReplyAllLegacyMirrored

E1F3 HelpLegacyMirrored

E1F4 ClearSelectionLegacyMirrored

E1F5 RecordLegacy

E1F6 LockLegacy

E1F7 UnlockLegacy

E1FD DownLegacy

E206 CommentInlineLegacy

E208 FavoriteInlineLegacy
E209 LikeInlineLegacy

E20A VideoInlineLegacy

E20B MailMessageLegacy

E211 PC1Legacy

E212 DevicesLegacy

E224 RatingStarLegacy

E228 ChevronDownSmLegacy

E248 ReplyLegacy

E249 Favorite2Legacy

E24A Unfavorite2Legacy

E25A MobileContactLegacy

E25B BlockedLegacy

E25C TypingIndicatorLegacy

E25D PresenceChickletVideoLegacy

E25E PresenceChickletLegacy

E26B ChevronRightSmLegacy

E26C ChevronLeftSmLegacy

E28F SaveAsLegacy

E290 DecreaseIndentLegacy
E291 IncreaseIndentLegacy

E292 BulletedListLegacy

E294 ScanLegacy

E295 PreviewLegacy

E297 DecreaseIndentLegacyMirrored

E298 IncreaseIndentLegacyMirrored

E299 BulletedListLegacyMirrored

E29B PlayOnLegacy

E2AC ResolutionLegacy

E2AD LengthLegacy

E2AE LayoutLegacy

E2AF Contact3Legacy

E2B0 TypeLegacy

E2B1 ColorLegacy

E2B2 SizeLegacy

E2B3 ReturnToWindowLegacy

E2B4 OpenInNewWindowLegacy

E2F6 PrintLegacy

E2F7 Printer3DLegacy
E700 GlobalNavigationButton

E701 Wifi

E702 Bluetooth

E703 Connect

E704 InternetSharing

E705 VPN

E706 Brightness

E707 MapPin

E708 QuietHours

E709 Airplane

E70A Tablet

E70B QuickNote

E70C RememberedDevice

E70D ChevronDown

E70E ChevronUp

E70F Edit

E710 Add

E711 Cancel

E712 More
E713 Settings

E714 Video

E715 Mail

E716 People

E717 Phone

E718 Pin

E719 Shop

E71A Stop

E71B Link

E71C Filter

E71D AllApps

E71E Zoom

E71F ZoomOut

E720 Microphone

E721 Search

E722 Camera

E723 Attach

E724 Send

E725 SendFill
E726 WalkSolid

E727 InPrivate

E728 FavoriteList

E729 PageSolid

E72A Forward

E72B Back

E72C Refresh

E72D Share

E72E Lock

E730 ReportHacked

E734 FavoriteStar

E735 FavoriteStarFill

E738 Remove

E739 Checkbox

E73A CheckboxComposite

E73B CheckboxFill

E73C CheckboxIndeterminate

E73D CheckboxCompositeReversed

E73E CheckMark
E73F BackToWindow

E740 FullScreen

E741 ResizeTouchLarger

E742 ResizeTouchSmaller

E743 ResizeMouseSmall

E744 ResizeMouseMedium

E745 ResizeMouseWide

E746 ResizeMouseTall

E747 ResizeMouseLarge

E748 SwitchUser

E749 Print

E74A Up

E74B Down

E74C OEM

E74D Delete

E74E Save

E74F Mute

E750 BackSpaceQWERTY

E751 ReturnKey
E752 UpArrowShiftKey

E753 Cloud

E754 Flashlight

E755 RotationLock

E756 CommandPrompt

E759 SIPMove

E75A SIPUndock

E75B SIPRedock

E75C EraseTool

E75D UnderscoreSpace

E75E GripperTool

E75F Dialpad

E760 PageLeft

E761 PageRight

E762 MultiSelect

E763 KeyboardLeftHanded

E764 KeyboardRightHanded

E765 KeyboardClassic

E766 KeyboardSplit
E767 Volume

E768 Play

E769 Pause

E76B ChevronLeft

E76C ChevronRight

E76D InkingTool

E76E Emoji2

E76F GripperBarHorizontal

E770 System

E771 Personalize

E772 Devices

E773 SearchAndApps

E774 Globe

E775 TimeLanguage

E776 EaseOfAccess

E777 UpdateRestore

E778 HangUp

E779 ContactInfo

E77A Unpin
E77B Contact

E77C Memo

E77F Paste

E780 PhoneBook

E781 LEDLight

E783 Error

E784 GripperBarVertical

E785 Unlock

E786 Slideshow

E787 Calendar

E788 GripperResize

E789 Megaphone

E78A Trim

E78B NewWindow

E78C SaveLocal

E790 Color

E791 DataSense

E792 SaveAs

E793 Light
E799 AspectRatio

E7A5 DataSenseBar

E7A6 Redo

E7A7 Undo

E7A8 Crop

E7AC OpenWith

E7AD Rotate

E7B5 SetlockScreen

E7B7 MapPin2

E7B8 Package

E7BA Warning

E7BC ReadingList

E7BE Education

E7BF ShoppingCart

E7C0 Train

E7C1 Flag

E7C3 Page

E7C4 Multitask

E7C5 BrowsePhotos
E7C6 HalfStarLeft

E7C7 HalfStarRight

E7C8 Record

E7C9 TouchPointer

E7DE LangJPN

E7E3 Ferry

E7E6 Highlight

E7E7 ActionCenterNotification

E7E8 PowerButton

E7EA ResizeTouchNarrower

E7EB ResizeTouchShorter

E7EC DrivingMode

E7ED RingerSilent

E7EE OtherUser

E7EF Admin

E7F0 CC

E7F1 SDCard

E7F2 CallForwarding

E7F3 SettingsDisplaySound
E7F4 TVMonitor

E7F5 Speakers

E7F6 Headphone

E7F7 DeviceLaptopPic

E7F8 DeviceLaptopNoPic

E7F9 DeviceMonitorRightPic

E7FA DeviceMonitorLeftPic

E7FB DeviceMonitorNoPic

E7FC Game

E7FD HorizontalTabKey

E802 StreetsideSplitMinimize

E803 StreetsideSplitExpand

E804 Car

E805 Walk

E806 Bus

E809 TiltUp

E80A TiltDown

E80C RotateMapRight

E80D RotateMapLeft
E80F Home

E811 ParkingLocation

E812 MapCompassTop

E813 MapCompassBottom

E814 IncidentTriangle

E815 Touch

E816 MapDirections

E819 StartPoint

E81A StopPoint

E81B EndPoint

E81C History

E81D Location

E81E MapLayers

E81F Accident

E821 Work

E822 Construction

E823 Recent

E825 Bank

E826 DownloadMap
E829 InkingToolFill2

E82A HighlightFill2

E82B EraseToolFill

E82C EraseToolFill2

E82D Dictionary

E82E DictionaryAdd

E82F ToolTip

E830 ChromeBack

E835 ProvisioningPackage

E836 AddRemoteDevice

E839 Ethernet

E83A ShareBroadband

E83B DirectAccess

E83C DialUp

E83D DefenderApp

E83E BatteryCharging9

E83F Battery10

E840 Pinned

E841 PinFill
E842 PinnedFill

E843 PeriodKey

E844 PuncKey

E845 RevToggleKey

E846 RightArrowKeyTime1

E847 RightArrowKeyTime2

E848 LeftQuote

E849 RightQuote

E84A DownShiftKey

E84B UpShiftKey

E84C PuncKey0

E84D PuncKeyLeftBottom

E84E RightArrowKeyTime3

E84F RightArrowKeyTime4

E850 Battery0

E851 Battery1

E852 Battery2

E853 Battery3

E854 Battery4
E855 Battery5

E856 Battery6

E857 Battery7

E858 Battery8

E859 Battery9

E85A BatteryCharging0

E85B BatteryCharging1

E85C BatteryCharging2

E85D BatteryCharging3

E85E BatteryCharging4

E85F BatteryCharging5

E860 BatteryCharging6

E861 BatteryCharging7

E862 BatteryCharging8

E863 BatterySaver0

E864 BatterySaver1

E865 BatterySaver2

E866 BatterySaver3

E867 BatterySaver4
E868 BatterySaver5

E869 BatterySaver6

E86A BatterySaver7

E86B BatterySaver8

E86C SignalBars1

E86D SignalBars2

E86E SignalBars3

E86F SignalBars4

E870 SignalBars5

E871 SignalNotConnected

E872 Wifi1

E873 Wifi2

E874 Wifi3

E875 SIMLock

E876 SIMMissing

E877 Vibrate

E878 RoamingInternational

E879 RoamingDomestic

E87A CallForwardInternational
E87B CallForwardRoaming

E87C JpnRomanji

E87D JpnRomanjiLock

E87E JpnRomanjiShift

E87F JpnRomanjiShiftLock

E880 StatusDataTransfer

E881 StatusDataTransferVPN

E882 StatusDualSIM2

E883 StatusDualSIM2VPN

E884 StatusDualSIM1

E885 StatusDualSIM1VPN

E886 StatusSGLTE

E887 StatusSGLTECell

E888 StatusSGLTEDataVPN

E889 StatusVPN

E88A WifiHotspot

E88B LanguageKor

E88C LanguageCht

E88D LanguageChs
E88E USB

E88F InkingToolFill

E890 View

E891 HighlightFill

E892 Previous

E893 Next

E894 Clear

E895 Sync

E896 Download

E897 Help

E898 Upload

E899 Emoji

E89A TwoPage

E89B LeaveChat

E89C MailForward

E89E RotateCamera

E89F ClosePane

E8A0 OpenPane

E8A1 PreviewLink
E8A2 AttachCamera

E8A3 ZoomIn

E8A4 Bookmarks

E8A5 Document

E8A6 ProtectedDocument

E8A7 OpenInNewWindow

E8A8 MailFill

E8A9 ViewAll

E8AA VideoChat

E8AB Switch

E8AC Rename

E8AD Go

E8AE SurfaceHub

E8AF Remote

E8B0 Click

E8B1 Shuffle

E8B2 Movies

E8B3 SelectAll

E8B4 Orientation
E8B5 Import

E8B6 ImportAll

E8B7 Folder

E8B8 Webcam

E8B9 Picture

E8BA Caption

E8BB ChromeClose

E8BC ShowResults

E8BD Message

E8BE Leaf

E8BF CalendarDay

E8C0 CalendarWeek

E8C1 Characters

E8C2 MailReplyAll

E8C3 Read

E8C4 ShowBcc

E8C5 HideBcc

E8C6 Cut

E8C8 Copy
E8C9 Important

E8CA MailReply

E8CB Sort

E8CC MobileTablet

E8CD DisconnectDrive

E8CE MapDrive

E8CF ContactPresence

E8D0 Priority

E8D1 GotoToday

E8D2 Font

E8D3 FontColor

E8D4 Contact2

E8D5 FolderFill

E8D6 Audio

E8D7 Permissions

E8D8 DisableUpdates

E8D9 Unfavorite

E8DA OpenLocal

E8DB Italic
E8DC Underline

E8DD Bold

E8DE MoveToFolder

E8DF LikeDislike

E8E0 Dislike

E8E1 Like

E8E2 AlignRight

E8E3 AlignCenter

E8E4 AlignLeft

E8E5 OpenFile

E8E6 ClearSelection

E8E7 FontDecrease

E8E8 FontIncrease

E8E9 FontSize

E8EA CellPhone

E8EB Reshare

E8EC Tag

E8ED RepeatOne

E8EE RepeatAll
E8EF Calculator

E8F0 Directions

E8F1 Library

E8F2 ChatBubbles

E8F3 PostUpdate

E8F4 NewFolder

E8F5 CalendarReply

E8F6 UnsyncFolder

E8F7 SyncFolder

E8F8 BlockContact

E8F9 SwitchApps

E8FA AddFriend

E8FB Accept

E8FC GoToStart

E8FD BulletedList

E8FE Scan

E8FF Preview

E904 ZeroBars

E905 OneBar
E906 TwoBars

E907 ThreeBars

E908 FourBars

E909 World

E90A Comment

E90B MusicInfo

E90C DockLeft

E90D DockRight

E90E DockBottom

E90F Repair

E910 Accounts

E911 DullSound

E912 Manage

E913 Street

E914 Printer3D

E915 RadioBullet

E916 Stopwatch

E91B Photo

E91C ActionCenter
E91F FullCircleMask

E921 ChromeMinimize

E922 ChromeMaximize

E923 ChromeRestore

E924 Annotation

E925 BackSpaceQWERTYSm

E926 BackSpaceQWERTYMd

E927 Swipe

E928 Fingerprint

E929 Handwriting

E92C ChromeBackToWindow

E92D ChromeFullScreen

E92E KeyboardStandard

E92F KeyboardDismiss

E930 Completed

E931 ChromeAnnotate

E932 Label

E933 IBeam

E934 IBeamOutline
E935 FlickDown

E936 FlickUp

E937 FlickLeft

E938 FlickRight

E939 FeedbackApp

E93C MusicAlbum

E93E Streaming

E943 Code

E944 ReturnToWindow

E945 LightningBolt

E946 Info

E947 CalculatorMultiply

E948 CalculatorAddition

E949 CalculatorSubtract

E94A CalculatorDivide

E94B CalculatorSquareroot

E94C CalculatorPercentage

E94D CalculatorNegate

E94E CalculatorEqualTo
E94F CalculatorBackspace

E950 Component

E951 DMC

E952 Dock

E953 MultimediaDMS

E954 MultimediaDVR

E955 MultimediaPMP

E956 PrintfaxPrinterFile

E957 Sensor

E958 StorageOptical

E95A Communications

E95B Headset

E95D Projector

E95E Health

E960 Webcam2

E961 Input

E962 Mouse

E963 Smartcard

E964 SmartcardVirtual
E965 MediaStorageTower

E966 ReturnKeySm

E967 GameConsole

E968 Network

E969 StorageNetworkWireless

E96A StorageTape

E96D ChevronUpSmall

E96E ChevronDownSmall

E96F ChevronLeftSmall

E970 ChevronRightSmall

E971 ChevronUpMed

E972 ChevronDownMed

E973 ChevronLeftMed

E974 ChevronRightMed

E975 Devices2

E976 ExpandTile

E977 PC1

E978 PresenceChicklet

E979 PresenceChickletVideo
E97A Reply

E97B SetTile

E97C Type

E97D Korean

E97E HalfAlpha

E97F FullAlpha

E980 Key12On

E981 ChineseChangjie

E982 QWERTYOn

E983 QWERTYOff

E984 ChineseQuick

E985 Japanese

E986 FullHiragana

E987 FullKatakana

E988 HalfKatakana

E989 ChineseBoPoMoFo

E98A ChinesePinyin

E98F ConstructionCone

E990 XboxOneConsole
E992 Volume0

E993 Volume1

E994 Volume2

E995 Volume3

E996 BatteryUnknown

E998 WifiAttentionOverlay

E99A Robot

E9A1 TapAndSend

E9A8 PasswordKeyShow

E9A9 PasswordKeyHide

E9AA BidiLtr

E9AB BidiRtl

E9AC ForwardSm

E9AD CommaKey

E9AE DashKey

E9AF DullSoundKey

E9B0 HalfDullSound

E9B1 RightDoubleQuote

E9B2 LeftDoubleQuote
E9B3 PuncKeyRightBottom

E9B4 PuncKey1

E9B5 PuncKey2

E9B6 PuncKey3

E9B7 PuncKey4

E9B8 PuncKey5

E9B9 PuncKey6

E9BA PuncKey9

E9BB PuncKey7

E9BC PuncKey8

E9CA Frigid

E9D9 Diagnostic

E9F3 Process

EA14 DisconnectDisplay

EA1F Info2

EA21 ActionCenterAsterisk

EA24 Beta

EA35 SaveCopy

EA37 List
EA38 Asterisk

EA39 ErrorBadge

EA3A CircleRing

EA3B CircleFill

EA40 AllAppsMirrored

EA41 BookmarksMirrored

EA42 BulletedListMirrored

EA43 CallForwardInternationalMirrored

EA44 CallForwardRoamingMirrored

EA47 ChromeBackMirrored

EA48 ClearSelectionMirrored

EA49 ClosePaneMirrored

EA4A ContactInfoMirrored

EA4B DockRightMirrored

EA4C DockLeftMirrored

EA4E ExpandTileMirrored

EA4F GoMirrored

EA50 GripperResizeMirrored

EA51 HelpMirrored
EA52 ImportMirrored

EA53 ImportAllMirrored

EA54 LeaveChatMirrored

EA55 ListMirrored

EA56 MailForwardMirrored

EA57 MailReplyMirrored

EA58 MailReplyAllMirrored

EA5B OpenPaneMirrored

EA5C OpenWithMirrored

EA5E ParkingLocationMirrored

EA5F ResizeMouseMediumMirrored

EA60 ResizeMouseSmallMirrored

EA61 ResizeMouseTallMirrored

EA62 ResizeTouchNarrowerMirrored

EA63 SendMirrored

EA64 SendFillMirrored

EA65 ShowResultsMirrored

EA69 Media

EA6A SyncError
EA6C Devices3

EA80 Lightbulb

EA81 StatusCircle

EA82 StatusTriangle

EA83 StatusError

EA84 StatusWarning

EA86 Puzzle

EA89 CalendarSolid

EA8A HomeSolid

EA8B ParkingLocationSolid

EA8C ContactSolid

EA8D ConstructionSolid

EA8E AccidentSolid

EA8F Ringer

EA91 ThoughtBubble

EA92 HeartBroken

EA93 BatteryCharging10

EA94 BatterySaver9

EA95 BatterySaver10
EA97 CallForwardingMirrored

EA98 MultiSelectMirrored

EA99 Broom

EADF Trackers

EB05 PieSingle

EB0F StockDown

EB11 StockUp

EB42 Drop

EB47 BusSolid

EB48 FerrySolid

EB49 StartPointSolid

EB4A StopPointSolid

EB4B EndPointSolid

EB4C AirplaneSolid

EB4D TrainSolid

EB4E WorkSolid

EB4F ReminderFill

EB50 Reminder

EB51 Heart
EB52 HeartFill

EB55 EthernetError

EB56 EthernetWarning

EB57 StatusConnecting1

EB58 StatusConnecting2

EB59 StatusUnsecure

EB5A WifiError0

EB5B WifiError1

EB5C WifiError2

EB5D WifiError3

EB5E WifiError4

EB5F WifiWarning0

EB60 WifiWarning1

EB61 WifiWarning2

EB62 WifiWarning3

EB63 WifiWarning4

EB66 Devices4

EB67 NUIIris

EB68 NUIFace
EB7E EditMirrored

EB82 NUIFPStartSlideHand

EB83 NUIFPStartSlideAction

EB84 NUIFPContinueSlideHand

EB85 NUIFPContinueSlideAction

EB86 NUIFPRollRightHand

EB87 NUIFPRollRightHandAction

EB88 NUIFPRollLeftHand

EB89 NUIFPRollLeftAction

EB8A NUIFPPressHand

EB8B NUIFPPressAction

EB8C NUIFPPressRepeatHand

EB8D NUIFPPressRepeatAction

EB90 StatusErrorFull

EB91 MultitaskExpanded

EB95 Certificate

EB96 BackSpaceQWERTYLg

EB97 ReturnKeyLg

EB9D FastForward
EB9E Rewind

EB9F Photo2

EBA0 MobBattery0

EBA1 MobBattery1

EBA2 MobBattery2

EBA3 MobBattery3

EBA4 MobBattery4

EBA5 MobBattery5

EBA6 MobBattery6

EBA7 MobBattery7

EBA8 MobBattery8

EBA9 MobBattery9

EBAA MobBattery10

EBAB MobBatteryCharging0

EBAC MobBatteryCharging1

EBAD MobBatteryCharging2

EBAE MobBatteryCharging3

EBAF MobBatteryCharging4

EBB0 MobBatteryCharging5
EBB1 MobBatteryCharging6

EBB2 MobBatteryCharging7

EBB3 MobBatteryCharging8

EBB4 MobBatteryCharging9

EBB5 MobBatteryCharging10

EBB6 MobBatterySaver0

EBB7 MobBatterySaver1

EBB8 MobBatterySaver2

EBB9 MobBatterySaver3

EBBA MobBatterySaver4

EBBB MobBatterySaver5

EBBC MobBatterySaver6

EBBD MobBatterySaver7

EBBE MobBatterySaver8

EBBF MobBatterySaver9

EBC0 MobBatterySaver10

EBC3 DictionaryCloud

EBC4 ResetDrive

EBC5 VolumeBars
EBC6 Project

EBD2 AdjustHologram

EBD4 WifiCallBars

EBD5 WifiCall0

EBD6 WifiCall1

EBD7 WifiCall2

EBD8 WifiCall3

EBD9 WifiCall4

EBDE DeviceDiscovery

EBE6 WindDirection

EBE7 RightArrowKeyTime0

EBFC TabletMode

EBFD StatusCircleLeft

EBFE StatusTriangleLeft

EBFF StatusErrorLeft

EC00 StatusWarningLeft

EC02 MobBatteryUnknown

EC05 NetworkTower

EC06 CityNext
EC07 CityNext2

EC08 Courthouse

EC09 Groceries

EC0A Sustainable

EC0B BuildingEnergy

EC11 ToggleFilled

EC12 ToggleBorder

EC13 SliderThumb

EC14 ToggleThumb

EC15 MiracastLogoSmall

EC16 MiracastLogoLarge

EC19 PLAP

EC1B Badge

EC1E SignalRoaming

EC20 MobileLocked

EC24 InsiderHubApp

EC25 PersonalFolder

EC26 HomeGroup

EC27 MyNetwork
EC31 KeyboardFull

EC37 MobSignal1

EC38 MobSignal2

EC39 MobSignal3

EC3A MobSignal4

EC3B MobSignal5

EC3C MobWifi1

EC3D MobWifi2

EC3E MobWifi3

EC3F MobWifi4

EC40 MobAirplane

EC41 MobBluetooth

EC42 MobActionCenter

EC43 MobLocation

EC44 MobWifiHotspot

EC45 LanguageJpn

EC46 MobQuietHours

EC47 MobDrivingMode

EC48 SpeedOff
EC49 SpeedMedium

EC4A SpeedHigh

EC4E ThisPC

EC4F MusicNote

EC50 FileExplorer

EC51 FileExplorerApp

EC52 LeftArrowKeyTime0

EC54 MicOff

EC55 MicSleep

EC56 MicError

EC57 PlaybackRate1x

EC58 PlaybackRateOther

EC59 CashDrawer

EC5A BarcodeScanner

EC5B ReceiptPrinter

EC5C MagStripeReader

EC61 CompletedSolid

EC64 CompanionApp

EC6D SwipeRevealArt
EC71 MicOn

EC72 MicClipping

EC74 TabletSelected

EC75 MobileSelected

EC76 LaptopSelected

EC77 TVMonitorSelected

EC7A DeveloperTools

EC7E MobCallForwarding

EC7F MobCallForwardingMirrored

EC80 BodyCam

EC81 PoliceCar

EC87 Draw

EC88 DrawSolid

EC8A LowerBrightness

EC8F ScrollUpDown

EC92 DateTime

ECA5 Tiles

ECA7 PartyLeader

ECAA AppIconDefault
ECC4 AddSurfaceHub

ECC5 DevUpdate

ECC6 Unit

ECC8 AddTo

ECC9 RemoveFrom

ECCA RadioBtnOff

ECCB RadioBtnOn

ECCC RadioBullet2

ECCD ExploreContent

ECE7 ScrollMode

ECE8 ZoomMode

ECE9 PanMode

ECF0 WiredUSB

ECF1 WirelessUSB

ECF3 USBSafeConnect

ED0C ActionCenterNotificationMirrored

ED0D ActionCenterMirrored

ED10 ResetDevice

ED15 Feedback
ED1E Subtitles

ED1F SubtitlesAudio

ED28 CalendarMirrored

ED2A eSIM

ED2B eSIMNoProfile

ED2C eSIMLocked

ED2D eSIMBusy

ED2E SignalError

ED2F StreamingEnterprise

ED30 Headphone0

ED31 Headphone1

ED32 Headphone2

ED33 Headphone3

ED39 KeyboardBrightness

ED3A KeyboardLowerBrightness

ED3C SkipBack10

ED3D SkipForward30

ED41 TreeFolderFolder

ED42 TreeFolderFolderFill
ED43 TreeFolderFolderOpen

ED44 TreeFolderFolderOpenFill

ED47 MultimediaDMP

ED4C KeyboardOneHanded

ED4D Narrator

ED53 EmojiTabPeople

ED54 EmojiTabSmilesAnimals

ED55 EmojiTabCelebrationObjects

ED56 EmojiTabFoodPlants

ED57 EmojiTabTransitPlaces

ED58 EmojiTabSymbols

ED59 EmojiTabTextSmiles

ED5A EmojiTabFavorites

ED5B EmojiSwatch

ED5C ConnectApp

ED5D CompanionDeviceFramework

ED5E Ruler

ED5F FingerInking

ED60 StrokeErase
ED61 PointErase

ED62 ClearAllInk

ED63 Pencil

ED64 Marker

ED65 InkingCaret

ED66 InkingColorOutline

ED67 InkingColorFill

EDA2 HardDrive

EDA3 NetworkAdapter

EDA4 Touchscreen

EDA5 NetworkPrinter

EDA6 CloudPrinter

EDA7 KeyboardShortcut

EDA8 BrushSize

EDA9 NarratorForward

EDAA NarratorForwardMirrored

EDAB SyncBadge12

EDAC RingerBadge12

EDAD AsteriskBadge12
EDAE ErrorBadge12

EDAF CircleRingBadge12

EDB0 CircleFillBadge12

EDB1 ImportantBadge12

EDB3 MailBadge12

EDB4 PauseBadge12

EDB5 PlayBadge12

EDC6 PenWorkspace

EDE1 Export

EDE2 ExportMirrored

EDFB CaligraphyPen

EE35 ReplyMirrored

EE3F LockscreenDesktop

EE40 Multitask16

EE4A Play36

EE56 PenPalette

EE57 GuestUser

EE63 SettingsBattery

EE64 TaskbarPhone
EE65 LockScreenGlance

EE71 ImageExport

EE77 WifiEthernet

EE79 ActionCenterQuiet

EE7A ActionCenterQuietNotification

EE92 TrackersMirrored

EE93 DateTimeMirrored

EE94 Wheel

EF15 PenWorkspaceMirrored

EF16 PenPaletteMirrored

EF17 StrokeEraseMirrored

EF18 PointEraseMirrored

EF19 ClearAllInkMirrored

EF1F BackgroundToggle

EF20 Marquee

Related articles
Guidelines for fonts
Symbol enumeration
XAML styles
7/11/2017 6 min to read Edit Online

You can customize the appearance of your apps in many ways by using the XAML framework. Styles let you set
control properties and reuse those settings for a consistent appearance across multiple controls.

Style basics
Use styles to extract visual property settings into reusable resources. Here's an example that shows 3 buttons with
a style that sets the BorderBrush, BorderThickness and Foreground properties. By applying a style, you can make
the controls appear the same without having to set these properties on each control separately.

You can define a style inline in the XAML for a control, or as a reusable resource. Define resources in an individual
page's XAML file, in the App.xaml file, or in a separate resource dictionary XAML file. A resource dictionary XAML
file can be shared across apps, and more than one resource dictionary can be merged in a single app. Where the
resource is defined determines the scope in which it can be used. Page-level 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. If a resource is defined in a separate resource dictionary
file, it's scope is determined by where the resource dictionary is referenced.
In the Style definition, you need a TargetType attribute and a collection of one or more Setter elements. The
TargetType attribute is a string that specifies a FrameworkElement type to apply the style to. The TargetType
value must specify a FrameworkElement-derived type that's defined by the Windows Runtime or a custom type
that's available in a referenced assembly. If you try to apply a style to a control and the control's type doesn't match
the TargetType attribute of the style you're trying to apply, an exception occurs.
Each Setter element requires a Property and a Value. These property settings indicate what control property the
setting applies to, and the value to set for that property. You can set the Setter.Value with either attribute or
property element syntax. The XAML here shows the style applied to the buttons shown previously. In this XAML, the
first two Setter elements use attribute syntax, but the last Setter, for the BorderBrush property, uses property
element syntax. The example doesn't use the x:Key attribute attribute, so the style is implicitly applied to the
buttons. Applying styles implicitly or explicitly is explained in the next section.
<Page.Resources>
<Style TargetType="Button">
<Setter Property="BorderThickness" Value="5" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" >
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>

Apply an implicit or explicit style


If you define a style as a resource, there are two ways to apply it to your controls:
Implicitly, by specifying only a TargetType for the Style.
Explicitly, by specifying a TargetType and an x:Key attribute attribute for the Style and then by setting the target
control's Style property with a {StaticResource} markup extension reference that uses the explicit key.
If a style contains the x:Key attribute, you can only apply it to a control by setting the Style property of the control to
the keyed style. In contrast, a style without an x:Key attribute is automatically applied to every control of its target
type, that doesn't otherwise have an explicit style setting.
Here are two buttons that demonstrate implicit and explicit styles.

In this example, the first style has an x:Key attribute and its target type is Button. The first button's Style property is
set to this key, so this style is applied explicitly. The second style is applied implicitly to the second button because
its target type is Button and the style doesn't have an x:Key attribute.
<Page.Resources>
<Style x:Key="PurpleStyle" TargetType="Button">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="Purple"/>
</Style>

<Style TargetType="Button">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="25"/>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" Value="Green"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Foreground" Value="Green"/>
</Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
<Button Content="Button" Style="{StaticResource PurpleStyle}"/>
<Button Content="Button"/>
</Grid>

Use based-on styles


To make styles easier to maintain and to optimize style reuse, you can create styles that inherit from other styles.
You use the BasedOn property to create inherited styles. Styles that inherit from other styles must target the same
type of control or a control that derives from the type targeted by the base style. For example, if a base style targets
ContentControl, styles that are based on this style can target ContentControl or types that derive from
ContentControl such as Button and ScrollViewer. If a value is not set in the based-on style, it's inherited from the
base style. To change a value from the base style, the based-on style overrides that value. The next example shows
a Button and a CheckBox with styles that inherit from the same base style.

The base style targets ContentControl, and sets the Height, and Width properties. The styles based on this style
target CheckBox and Button, which derive from ContentControl. The based-on styles set different colors for the
BorderBrush and Foreground properties. (You don't typically put a border around a CheckBox. We do it here to
show the effects of the style.)
<Page.Resources>
<Style x:Key="BasicStyle" TargetType="ContentControl">
<Setter Property="Width" Value="130" />
<Setter Property="Height" Value="30" />
</Style>

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


BasedOn="{StaticResource BasicStyle}">
<Setter Property="BorderBrush" Value="Orange" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Foreground" Value="Red" />
</Style>

<Style x:Key="CheckBoxStyle" TargetType="CheckBox"


BasedOn="{StaticResource BasicStyle}">
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Foreground" Value="Green" />
</Style>
</Page.Resources>

<StackPanel>
<Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
<CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

Use tools to work with styles easily


A fast way to apply styles to your controls is to right-click on a control on the Microsoft Visual Studio XAML design
surface and select Edit Style or Edit Template (depending on the control you are right-clicking on). You can then
apply an existing style by selecting Apply Resource or define a new style by selecting Create Empty. If you create
an empty style, you are given the option to define it in the page, in the App.xaml file, or in a separate resource
dictionary.

Lightweight styling
Overriding the system brushes is generally done at the App or Page level, and in either case the color override will
affect all controls that reference that brush and in XAML many controls can reference the same system brush.
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
<SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
<SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>

For states like PointerOver (mouse is hovered over the button), PointerPressed (button has been invoked), or
Disabled (button is not interactable). These endings are appended onto the original Lightweight styling names:
ButtonBackgroundPointerOver, ButtonForegroundPointerPressed, ButtonBorderBrushDisabled, etc.
Modifying those brushes as well, will make sure that your controls are colored consistently to your app's theme.
Placing these brush overrides at the App.Resources level, will alter all the buttons within the entire app, instead of
on a single page.
Per-control styling
In other cases, changing a single control on one page only to look a certain way, without altering any other versions
of that control, is desired:

<CheckBox Content="Normal CheckBox" Margin="5"/>


<CheckBox Content="Special CheckBox" Margin="5">
<CheckBox.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
Color="Purple"/>
<SolidColorBrush x:Key="CheckBoxForegroundChecked"
Color="Purple"/>
<SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
Color="White"/>
<SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"
Color="Purple"/>
<SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
Color="Purple"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

This would only effect that one Special CheckBox on the page where that control existed.

Modify the default system styles


You should use the styles that come from the Windows Runtime default XAML resources when you can. When you
have to define your own styles, try to base your styles on the default ones when possible (using based-on styles as
explained earlier, or start by editing a copy of the original default style).

The template property


A style setter can be used for the Template property of a Control, and in fact this makes up the majority of a typical
XAML style and an app's XAML resources. This is discussed in more detail in the topic Control templates.
Control templates
5/22/2017 7 min to read Edit Online

You can customize a control's visual structure and visual behavior by creating a control template in the XAML
framework. Controls have many properties, such as Background, Foreground, and FontFamily, that you can set
to specify different aspects of the control's appearance. But the changes that you can make by setting these
properties are limited. You can specify additional customizations by creating a template using the
ControlTemplate class. Here, we show you how to create a ControlTemplate to customize the appearance of a
CheckBox control.

Important APIs: ControlTemplate class, Control.Template property

Custom control template example


By default, a CheckBox control puts its content (the string or object next to the CheckBox) to the right of the
selection box, and a check mark indicates that a user selected the CheckBox. These characteristics represent the
visual structure and visual behavior of the CheckBox.
Here's a CheckBox using the default ControlTemplate shown in the Unchecked , Checked , and Indeterminate states.

You can change these characteristics by creating a ControlTemplate for the CheckBox. For example, if you want
the content of the check box to be below the selection box, and you want to use an X to indicate that a user
selected the check box. You specify these characteristics in the ControlTemplate of the CheckBox.
To use a custom template with a control, assign the ControlTemplate to the Template property of the control.
Here's a CheckBox using a ControlTemplate called CheckBoxTemplate1 . We show the Extensible Application
Markup Language (XAML) for the ControlTemplate in the next section.

<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

Here's how this CheckBox looks in the Unchecked , Checked , and Indeterminate states after we apply our template.

Specify the visual structure of a control


When you create a ControlTemplate, you combine FrameworkElement objects to build a single control. A
ControlTemplate must have only one FrameworkElement as its root element. The root element usually contains
other FrameworkElement objects. The combination of objects makes up the control's visual structure.
This XAML creates a ControlTemplate for a CheckBox that specifies that the content of the control is below the
selection box. The root element is a Border. The example specifies a Path to create an X that indicates that a user
selected the CheckBox, and an Ellipse that indicates an indeterminate state. Note that the Opacity is set to 0 on
the Path and the Ellipse so that by default, neither appear.

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">


<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
UseLayoutRounding="False"/>
<!-- Create an X to indicate that the CheckBox is selected. -->
<Path x:Name="CheckGlyph"
Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
FlowDirection="LeftToRight"
Height="14" Width="16" Opacity="0" Stretch="Fill"/>
<Ellipse x:Name="IndeterminateGlyph"
Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
<ContentPresenter x:Name="ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}" Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
</ControlTemplate>

Specify the visual behavior of a control


A visual behavior specifies the appearance of a control when it is in a certain state. The CheckBox control has 3
check states: Checked , Unchecked , and Indeterminate . The value of the IsChecked property determines the state of
the CheckBox, and its state determines what appears in the box.
This table lists the possible values of IsChecked, the corresponding states of the CheckBox, and the appearance of
the CheckBox.

IsChecked value CheckBox state CheckBox appearance

true Checked Contains an "X".

false Unchecked Empty.

null Indeterminate Contains a circle.

You specify the appearance of a control when it is in a certain state by using VisualState objects. A VisualState
contains a Setter or Storyboard that changes the appearance of the elements in the ControlTemplate. When the
control enters the state that the VisualState.Name property specifies, the property changes in the Setter or
Storyboard are applied. When the control exits the state, the changes are removed. You add VisualState objects
to VisualStateGroup objects. You add VisualStateGroup objects to the
VisualStateManager.VisualStateGroups attached property, which you set on the root FrameworkElement of
the ControlTemplate.
This XAML shows the VisualState objects for the Checked , Unchecked , and Indeterminate states. The example sets
the VisualStateManager.VisualStateGroups attached property on the Border, which is the root element of the
ControlTemplate. The Checked VisualState specifies that the Opacity of the Path named CheckGlyph (which we
show in the previous example) is 1. The Indeterminate VisualState specifies that the Opacity of the Ellipse named
IndeterminateGlyph is 1. The Unchecked VisualState has no Setter or Storyboard, so the CheckBox returns to its
default appearance.
<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Target="CheckGlyph.Opacity" Value="1"/>
</VisualState.Setters>
<!-- This Storyboard is equivalent to the Setter. -->
<!--<Storyboard>
<DoubleAnimation Duration="0" To="1"
Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity"/>
</Storyboard>-->
</VisualState>
<VisualState x:Name="Unchecked"/>
<VisualState x:Name="Indeterminate">
<VisualState.Setters>
<Setter Target="IndeterminateGlyph.Opacity" Value="1"/>
</VisualState.Setters>
<!-- This Storyboard is equivalent to the Setter. -->
<!--<Storyboard>
<DoubleAnimation Duration="0" To="1"
Storyboard.TargetName="IndeterminateGlyph" Storyboard.TargetProperty="Opacity"/>
</Storyboard>-->
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
UseLayoutRounding="False"/>
<!-- Create an X to indicate that the CheckBox is selected. -->
<Path x:Name="CheckGlyph"
Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
FlowDirection="LeftToRight"
Height="14" Width="16" Opacity="0" Stretch="Fill"/>
<Ellipse x:Name="IndeterminateGlyph"
Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
<ContentPresenter x:Name="ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}" Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
</ControlTemplate>

To better understand how VisualState objects work, consider what happens when the CheckBox goes from the
Unchecked state to the Checked state, then to the Indeterminate state, and then back to the Unchecked state. Here are
the transitions.
State transition What happens CheckBox appearance when the
transition completes

From Unchecked to Checked . The Setter value of the Checked An X is displayed.


VisualState is applied, so the Opacity
of CheckGlyph is 1.

From Checked to Indeterminate . The Setter value of the A circle is displayed.


Indeterminate VisualState is applied,
so the Opacity of
IndeterminateGlyph is 1. The Setter
value of the Checked VisualState is
removed, so the Opacity of
CheckGlyph is 0.

From Indeterminate to Unchecked . The Setter value of the Nothing is displayed.


Indeterminate VisualState is
removed, so the Opacity of
IndeterminateGlyph is 0.

For more info about how to create visual states for controls, and in particular how to use the Storyboard class and
the animation types, see Storyboarded animations for visual states.

Use tools to work with themes easily


A fast way to apply themes to your controls is to right-click on a control on the Microsoft Visual Studio Document
Outline and select Edit Theme or Edit Style (depending on the control you are right-clicking on). You can then
apply an existing theme by selecting Apply Resource or define a new one by selecting Create Empty.

Controls and accessibility


When you create a new template for a control, in addition to possibly changing the control's behavior and visual
appearance, you might also be changing how the control represents itself to accessibility frameworks. The
Universal Windows Platform (UWP) supports the Microsoft UI Automation framework for accessibility. All of the
default controls and their templates have support for common UI Automation control types and patterns that are
appropriate for the control's purpose and function. These control types and patterns are interpreted by UI
Automation clients such as assistive technologies, and this enables a control to be accessible as a part of a larger
accessible app UI.
To separate the basic control logic and also to satisfy some of the architectural requirements of UI Automation,
control classes include their accessibility support in a separate class, an automation peer. The automation peers
sometimes have interactions with the control templates because the peers expect certain named parts to exist in
the templates, so that functionality such as enabling assistive technologies to invoke actions of buttons is possible.
When you create a completely new custom control, you sometimes also will want to create a new automation peer
to go along with it. For more info, see Custom automation peers.

Learn more about a control's default template


The topics that document the styles and templates for XAML controls show you excerpts of the same starting
XAML you'd see if you used the Edit Theme or Edit Style techniques explained previously. Each topic lists the
names of the visual states, the theme resources used, and the full XAML for the style that contains the template.
The topics can be useful guidance if you've already started modifying a template and want to see what the original
template looked like, or to verify that your new template has all of the required named visual states.
Theme resources in control templates
For some of the attributes in the XAML examples, you may have noticed resource references that use the
{ThemeResource} markup extension. This is a technique that enables a single control template to use resources
that can be different values depending on which theme is currently active. This is particularly important for brushes
and colors, because the main purpose of the themes is to enable users to choose whether they want a dark, light,
or high contrast theme applied to the system overall. Apps that use the XAML resource system can use a resource
set that's appropriate for that theme, so that the theme choices in an app's UI are reflective of the user's
systemwide theme choice.

Get the sample code


XAML UI basics sample
Custom text edit control sample
ResourceDictionary and XAML resource references
5/22/2017 21 min to read Edit Online

You can define the UI or resources for your app using XAML. Resources are typically definitions of some object that
you expect to use more than once. To refer to a XAML resource later, you specify a key for a resource that acts like
its name. You can reference a resource throughout an app or from any XAML page within it. You can define your
resources using a ResourceDictionary element from the Windows Runtime XAML. Then, you can reference your
resources by using a StaticResource markup extension or ThemeResource markup extension.
The XAML elements you might want to declare most often as XAML resources include Style, ControlTemplate,
animation components, and Brush subclasses. Here, we explain how to define a ResourceDictionary and keyed
resources, and how XAML resources relate to other resources that you define as part of your app or app package.
We also explain resource dictionary advanced features such as MergedDictionaries and ThemeDictionaries.
Prerequisites
We assume that you understand XAML markup and have read the XAML overview.

Define and use XAML resources


XAML resources are objects that are referenced from markup more than once. Resources are defined in a
ResourceDictionary, typically in a separate file or at the top of the markup page, like this.

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<x:String x:Key="greeting">Hello world</x:String>
<x:String x:Key="goodbye">Goodbye world</x:String>
</Page.Resources>

<TextBlock Text="{StaticResource greeting}" Foreground="Gray" VerticalAlignment="Center"/>


</Page>

In this example:
<Page.Resources></Page.Resources> - Defines the resource dictionary.
<x:String> - Defines the resource with the key "greeting".
{StaticResource greeting} - Looks up the resource with the key "greeting", which is assigned to the Text property of
the TextBlock.

Note Don't confuse the concepts related to ResourceDictionary with the Resource build action, resource
(.resw) files, or other "resources" that are discussed in the context of structuring the code project that produces
your app package.

Resources don't have to be strings; they can be any shareable object, such as styles, templates, brushes, and colors.
However, controls, shapes, and other FrameworkElements are not shareable, so they can't be declared as reusable
resources. For more info about sharing, see the XAML resources must be shareable section later in this topic.
Here, both a brush and a string are declared as resources and used by controls in a page.
<Page
x:Class="SpiderMSDN.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<SolidColorBrush x:Key="myFavoriteColor" Color="green"/>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources>

<TextBlock Foreground="{StaticResource myFavoriteColor}" Text="{StaticResource greeting}" VerticalAlignment="Top"/>


<Button Foreground="{StaticResource myFavoriteColor}" Content="{StaticResource greeting}" VerticalAlignment="Center"/>
</Page>

All resources need to have a key. Usually that key is a string defined with x:Key=myString . However, there are a few
other ways to specify a key:
Style and ControlTemplate require a TargetType, and will use the TargetType as the key if x:Key is not
specified. In this case, the key is the actual Type object, not a string. (See examples below)
DataTemplate resources that have a TargetType will use the TargetType as the key if x:Key is not specified. In
this case, the key is the actual Type object, not a string.
x:Name can be used instead of x:Key. However, x:Name also generates a code behind field for the resource. As a
result, x:Name is less efficient than x:Key because that field needs to be initialized when the page is loaded.
The StaticResource markup extension can retrieve resources only with a string name (x:Key or x:Name). However,
the XAML framework also looks for implicit style resources (those which use TargetType rather than x:Key or
x:Name) when it decides which style & template to use for a control that hasn't set the Style and ContentTemplate
or ItemTemplate properties.
Here, the Style has an implicit key of typeof(Button), and since the Button at the bottom of the page doesn't
specify a Style property, it looks for a style with key of typeof(Button):

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="red"/>
</Style>
</Page.Resources>
<!-- This button will have a red background. -->
<Button Content="Button" Height="100" VerticalAlignment="Center" Width="100"/>
</Page>

For more info about implicit styles and how they work, see Styling controls and Control templates.

Look up resources in code


You access members of the resource dictionary like any other dictionary.

Caution When you perform a resource lookup in code, only the resources in the Page.Resources dictionary are
looked at. Unlike the StaticResource markup extension, the code doesn't fall back to the Application.Resources
dictionary if the resources arent found in the first dictionary.

This example shows how to retrieve the redButtonStyle resource out of a pages resource dictionary:
<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<Style TargetType="Button" x:Key="redButtonStyle">
<Setter Property="Background" Value="red"/>
</Style>
</Page.Resources>
</Page>

public sealed partial class MainPage : Page


{
public MainPage()
{
this.InitializeComponent();
Style redButtonStyle = (Style)this.Resources["redButtonStyle"];
}
}

To look up app-wide resources from code, use Application.Current.Resources to get the app's resource
dictionary, as shown here.

<Application
x:Class="MSDNSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:SpiderMSDN">
<Application.Resources>
<Style TargetType="Button" x:Key="appButtonStyle">
<Setter Property="Background" Value="red"/>
</Style>
</Application.Resources>

</Application>

public sealed partial class MainPage : Page


{
public MainPage()
{
this.InitializeComponent();
Style appButtonStyle = (Style)Application.Current.Resources["appButtonStyle"];
}
}

You can also add an application resource in code.


There are two things to keep in mind when doing this.
First, you need to add the resources before any page tries to use the resource.
Second, you cant add resources in the Apps constructor.
You can avoid both problems if you add the resource in the Application.OnLaunched method, like this.
// App.xaml.cs

sealed partial class App : Application


{
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
SolidColorBrush brush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 0, 255, 0)); // green
this.Resources["brush"] = brush;
// Other code that VS generates for you
}
}
}

Every FrameworkElement can have a ResourceDictionary


FrameworkElement is a base class that controls inherit from, and it has a Resources property. So, you can add a
local resource dictionary to any FrameworkElement.
Here, a resource dictionary is added to a page element.

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources>

<Border>
<Border.Resources>
<x:String x:Key="greeting">Hola mundo</x:String>
</Border.Resources>
<TextBlock Text="{StaticResource greeting}" Foreground="Gray" VerticalAlignment="Center"/>
</Border>
</Page>

Here, both the Page and the Border have resource dictionaries, and they both have a resource called "greeting". The
TextBlock is inside the Border, so its resource lookup looks first to the Borders resources, then the Pages
resources, and then the Application resources. The TextBlock will read "Hola mundo".
To access that elements resources from code, use that elements Resources property. Accessing a
FrameworkElements resources in code, rather than XAML, will look only in that dictionary, not in parent elements
dictionaries.
<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Page.Resources>
<x:String x:Key="greeting">Hello world</x:String>
</Page.Resources>

<Border x:Name="border">
<Border.Resources>
<x:String x:Key="greeting">Hola mundo</x:String>
</Border.Resources>
</Border>
</Page>

public sealed partial class MainPage : Page


{
public MainPage()
{
this.InitializeComponent();
string str = (string)border.Resources["greeting"];
}
}

Merged resource dictionaries


A merged resource dictionary combines one resource dictionary into another, usually in another file.

Tip You can create a resource dictionary file in Microsoft Visual Studio by using the Add > New Item >
Resource Dictionary option from the Project menu.

Here, you define a resource dictionary in a separate XAML file called Dictionary1.xaml.

<!-- Dictionary1.xaml -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">

<SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

To use that dictionary, you merge it with your pages dictionary:


<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>

<x:String x:Key="greeting">Hello world</x:String>

</ResourceDictionary>
</Page.Resources>

<TextBlock Foreground="{StaticResource brush}" Text="{StaticResource greeting}" VerticalAlignment="Center"/>


</Page>

Here's what happens in this example. In <Page.Resources> , you declare <ResourceDictionary> . The XAML framework
implicitly creates a resource dictionary for you when you add resources to <Page.Resources> ; however, in this case,
you dont want just any resource dictionary, you want one that contains merged dictionaries.
So you declare <ResourceDictionary> , then add things to its <ResourceDictionary.MergedDictionaries> collection. Each of
those entries takes the form <ResourceDictionary Source="Dictionary1.xaml"/> . To add more than one dictionary, just add a
<ResourceDictionary Source="Dictionary2.xaml"/> entry after the first entry.

After <ResourceDictionary.MergedDictionaries></ResourceDictionary.MergedDictionaries> , you can optionally put additional


resources in your main dictionary. You use resources from a merged to dictionary just like a regular dictionary. In
the example above, {StaticResource brush} finds the resource in the child/merged dictionary (Dictionary1.xaml), while
{StaticResource greeting} finds its resource in the main page dictionary.

In the resource-lookup sequence, a MergedDictionaries dictionary is checked only after a check of all the other
keyed resources of that ResourceDictionary. After searching that level, the lookup reaches the merged dictionaries,
and each item in MergedDictionaries is checked. If multiple merged dictionaries exist, these dictionaries are
checked in the inverse of the order in which they are declared in the MergedDictionaries property. In the
following example, if both Dictionary2.xaml and Dictionary1.xaml declared the same key, the key from
Dictionary2.xaml is used first because it's last in the MergedDictionaries set.

<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
<ResourceDictionary Source="Dictionary2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>

<TextBlock Foreground="{StaticResource brush}" Text="greetings!" VerticalAlignment="Center"/>


</Page>

Within the scope of any one ResourceDictionary, the dictionary is checked for key uniqueness. However, that scope
does not extend across different items in different MergedDictionaries files.
You can use the combination of the lookup sequence and lack of unique key enforcement across merged-dictionary
scopes to create a fallback value sequence of ResourceDictionary resources. For example, you might store user
preferences for a particular brush color in the last merged resource dictionary in the sequence, using a resource
dictionary that synchronizes to your app's state and user preference data. However, if no user preferences exist yet,
you can define that same key string for a ResourceDictionary resource in the initial MergedDictionaries file, and it
can serve as the fallback value. Remember that any value you provide in a primary resource dictionary is always
checked before the merged dictionaries are checked, so if you want to use the fallback technique, don't define that
resource in a primary resource dictionary.

Theme resources and theme dictionaries


A ThemeResource is similar to a StaticResource, but the resource lookup is reevaluated when the theme changes.
In this example, you set the foreground of a TextBlock to a value from the current theme.

<TextBlock Text="hello world" Foreground="{ThemeResource FocusVisualWhiteStrokeThemeBrush}" VerticalAlignment="Center"/>

A theme dictionary is a special type of merged dictionary that holds the resources that vary with the theme a user is
currently using on his or her device. For example, the "light" theme might use a white color brush whereas the
"dark" theme might use a dark color brush. The brush changes the resource that it resolves to, but otherwise the
composition of a control that uses the brush as a resource could be the same. To reproduce the theme-switching
behavior in your own templates and styles, instead of using MergedDictionaries as the property to merge items
into the main dictionaries, use the ThemeDictionaries property.
Each ResourceDictionary element within ThemeDictionaries must have an x:Key value. The value is a string that
names the relevant themefor example, "Default", "Dark", "Light", or "HighContrast". Typically, Dictionary1 and
Dictionary2 will define resources that have the same names but different values.

Here, you use red text for the light theme and blue text for the dark theme.

<!-- Dictionary1.xaml -->


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">

<SolidColorBrush x:Key="brush" Color="Red"/>

</ResourceDictionary>

<!Dictionary2.xaml -->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">

<SolidColorBrush x:Key="brush" Color="blue"/>

</ResourceDictionary>

In this example, you set the foreground of a TextBlock to a value from the current theme.
<Page
x:Class="MSDNSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" x:Key="Light"/>
<ResourceDictionary Source="Dictionary2.xaml" x:Key="Dark"/>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>
<TextBlock Foreground="{StaticResource brush}" Text="hello world" VerticalAlignment="Center"/>
</Page>

For theme dictionaries, the active dictionary to be used for resource lookup changes dynamically, whenever
ThemeResource markup extension is used to make the reference and the system detects a theme change. The
lookup behavior that is done by the system is based on mapping the active theme to the x:Key of a specific theme
dictionary.
It can be useful to examine the way that the theme dictionaries are structured in the default XAML design resources,
which parallel the templates that the Windows Runtime uses by default for its controls. Open the XAML files in \
(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic using
a text editor or your IDE. Note how the theme dictionaries are defined first in generic.xaml, and how each theme
dictionary defines the same keys. Each such key is then referenced by elements of composition in the various keyed
elements that are outside the theme dictionaries and defined later in the XAML. There's also a separate
themeresources.xaml file for design that contains only the theme resources and extra templates, not the default
control templates. The theme areas are duplicates of what you'd see in generic.xaml.
When you use XAML design tools to edit copies of styles and templates, the design tools extract sections from the
XAML design resource dictionaries and place them as local copies of XAML dictionary elements that are part of
your app and project.
For more info and for a list of the theme-specific and system resources that are available to your app, see XAML
theme resources.

Lookup behavior for XAML resource references


Lookup behavior is the term that describes how the XAML resources system tries to find a XAML resource. The
lookup occurs when a key is referenced as a XAML resource reference from somewhere in the app's XAML. First,
the resources system has predictable behavior for where it will check for the existence of a resource based on
scope. If a resource isn't found in the initial scope, the scope expands. The lookup behavior continues on
throughout the locations and scopes that a XAML resource could possibly be defined by an app or by the system. If
all possible resource lookup attempts fail, an error often results. It's usually possible to eliminate these errors
during the development process.
The lookup behavior for XAML resource references starts with the object where the actual usage is applied and its
own Resources property. If a ResourceDictionary exists there, that ResourceDictionary is checked for an item that
has the requested key. This first level of lookup is rarely relevant because you usually do not define and then
reference a resource on the same object. In fact, a Resources property often doesn't exist here. You can make
XAML resource references from nearly anywhere in XAML; you aren't limited to properties of FrameworkElement
subclasses.
The lookup sequence then checks the next parent object in the runtime object tree of the app. If a
FrameworkElement.Resources exists and holds a ResourceDictionary, the dictionary item with the specified key
string is requested. If the resource is found, the lookup sequence stops and the object is provided to the location
where the reference was made. Otherwise, the lookup behavior advances to the next parent level towards the
object tree root. The search continues recursively upwards until the root element of the XAML is reached,
exhausting the search of all possible immediate resource locations.

Note It is a common practice to define all the immediate resources at the root level of a page, both to take
advantage of this resource-lookup behavior and also as a convention of XAML markup style.

If the requested resource is not found in the immediate resources, the next lookup step is to check the
Application.Resources property. Application.Resources is the best place to put any app-specific resources that are
referenced by multiple pages in your app's navigation structure.
Control templates have another possible location in the reference lookup: theme dictionaries. A theme dictionary is
a single XAML file that has a ResourceDictionary element as its root. The theme dictionary might be a merged
dictionary from Application.Resources. The theme dictionary might also be the control-specific theme dictionary for
a templated custom control.
Finally, there is a resource lookup against platform resources. Platform resources include the control templates that
are defined for each of the system UI themes, and which define the default appearance of all the controls that you
use for UI in a Windows Runtime app. Platform resources also include a set of named resources that relate to
system-wide appearance and themes. These resources are technically a MergedDictionaries item, and thus are
available for lookup from XAML or code once the app has loaded. For example, the system theme resources include
a resource named "SystemColorWindowTextColor" that provides a Color definition to match app text color to a
system window's text color that comes from the operating system and user preferences. Other XAML styles for
your app can refer to this style, or your code can get a resource lookup value (and cast it to Color in the example
case).
For more info and for a list of the theme-specific and system resources that are available to a Windows Store app
that uses XAML, see XAML theme resources.
If the requested key is still not found in any of these locations, a XAML parsing error/exception occurs. In certain
circumstances, the XAML parse exception may be a run-time exception that is not detected either by a XAML
markup compile action, or by a XAML design environment.
Because of the tiered lookup behavior for resource dictionaries, you can deliberately define multiple resource items
that each have the same string value as the key, as long as each resource is defined at a different level. In other
words, although keys must be unique within any given ResourceDictionary, the uniqueness requirement does not
extend to the lookup behavior sequence as a whole. During lookup, only the first such object that's successfully
retrieved is used for the XAML resource reference, and then the lookup stops. You could use this behavior to
request the same XAML resource by key at various positions within your app's XAML but get different resources
back, depending on the scope from which the XAML resource reference was made and how that particular lookup
behaves.

Forward references within a ResourceDictionary


XAML resource references within a particular resource dictionary must reference a resource that has already been
defined with a key, and that resource must appear lexically before the resource reference. Forward references
cannot be resolved by a XAML resource reference. For this reason, if you use XAML resource references from within
another resource, you must design your resource dictionary structure so that the resources that are used by other
resources are defined first in a resource dictionary.
Resources defined at the app level cannot make references to immediate resources. This is equivalent to attempting
a forward reference, because the app resources are actually processed first (when the app first starts, and before
any navigation-page content is loaded). However, any immediate resource can make a reference to an app
resource, and this can be a useful technique for avoiding forward-reference situations.
XAML resources must be shareable
For an object to exist in a ResourceDictionary, that object must be shareable.
Being shareable is required because, when the object tree of an app is constructed and used at run time, objects
cannot exist at multiple locations in the tree. Internally, the resource system creates copies of resource values to use
in the object graph of your app when each XAML resource is requested.
A ResourceDictionary and Windows Runtime XAML in general supports these objects for shareable usage:
Styles and templates (Style and classes derived from FrameworkTemplate)
Brushes and colors (classes derived from Brush, and Color values)
Animation types including Storyboard
Transforms (classes derived from GeneralTransform)
Matrix and Matrix3D
Point values
Certain other UI-related structures such as Thickness and CornerRadius
XAML intrinsic data types
You can also use custom types as a shareable resource if you follow the necessary implementation patterns. You
define such classes in your backing code (or in runtime components that you include) and then instantiate those
classes in XAML as a resource. Examples are object data sources and IValueConverter implementations for data
binding.
Custom types must have a default constructor, because that's what a XAML parser uses to instantiate a class.
Custom types used as resources can't have the UIElement class in their inheritance, because a UIElement can
never be shareable (it's always intended to represent exactly one UI element that exists at one position in the object
graph of your runtime app).

UserControl usage scope


A UserControl element has a special situation for resource-lookup behavior because it has the inherent concepts of
a definition scope and a usage scope. A UserControl that makes a XAML resource reference from its definition
scope must be able to support the lookup of that resource within its own definition-scope lookup sequencethat
is, it cannot access app resources. From a UserControl usage scope, a resource reference is treated as being within
the lookup sequence towards its usage page root (just like any other resource reference made from an object in a
loaded object tree) and can access app resources.

ResourceDictionary and XamlReader.Load


You can use a ResourceDictionary as either the root or a part of the XAML input for the XamlReader.Load method.
You can also include XAML resource references in that XAML if all such references are completely self-contained in
the XAML submitted for loading. XamlReader.Load parses the XAML in a context that is not aware of any other
ResourceDictionary objects, not even Application.Resources. Also, don't use {ThemeResource} from within XAML
submitted to XamlReader.Load.

Using a ResourceDictionary from code


Most of the scenarios for a ResourceDictionary are handled exclusively in XAML. You declare the
ResourceDictionary container and the resources within as a XAML file or set of XAML nodes in a UI definition file.
And then you use XAML resource references to request those resources from other parts of XAML. Still, there are
certain scenarios where your app might want to adjust the contents of a ResourceDictionary using code that
executes while the app is running, or at least to query the contents of a ResourceDictionary to see if a resource is
already defined. These code calls are made on a ResourceDictionary instance, so you must first retrieve one
either an immediate ResourceDictionary somewhere in the object tree by getting FrameworkElement.Resources,
or Application.Current.Resources .
In C# or Microsoft Visual Basic code, you can reference a resource in a given ResourceDictionary by using the
indexer (Item). A ResourceDictionary is a string-keyed dictionary, so the indexer uses the string key instead of an
integer index. In Visual C++ component extensions (C++/CX) code, use Lookup.
When using code to examine or change a ResourceDictionary, the behavior for APIs like Lookup or Item does not
traverse from immediate resources to app resources; that's a XAML parser behavior that only happens as XAML
pages are loaded. At run time, scope for keys is self-contained to the ResourceDictionary instance that you are
using at the time. However, that scope does extend into MergedDictionaries.
Also, if you request a key that does not exist in the ResourceDictionary, there may not be an error; the return value
may simply be provided as null. You may still get an error, though, if you try to use the returned null as a value.
The error would come from the property's setter, not your ResourceDictionary call. The only way you'd avoid an
error is if the property accepted null as a valid value. Note how this behavior contrasts with XAML lookup behavior
at XAML parse time; a failure to resolve the provided key from XAML at parse time results in a XAML parse error,
even in cases where the property could have accepted null.
Merged resource dictionaries are included into the index scope of the primary resource dictionary that references
the merged dictionary at run time. In other words, you can use Item or Lookup of the primary dictionary to find
any objects that were actually defined in the merged dictionary. In this case, the lookup behavior does resemble the
parse-time XAML lookup behavior: if there are multiple objects in merged dictionaries that each have the same key,
the object from the last-added dictionary is returned.
You are permitted to add items to an existing ResourceDictionary by calling Add (C# or Visual Basic) or Insert
(C++/CX). You could add the items to either immediate resources or app resources. Either of these API calls
requires a key, which satisfies the requirement that each item in a ResourceDictionary must have a key. However,
items that you add to a ResourceDictionary at run time are not relevant to XAML resource references. The
necessary lookup for XAML resource references happens when that XAML is first parsed as the app is loaded (or a
theme change is detected). Resources added to collections at run time weren't available then, and altering the
ResourceDictionary doesn't invalidate an already retrieved resource from it even if you change the value of that
resource.
You also can remove items from a ResourceDictionary at run time, make copies of some or all items, or other
operations. The members listing for ResourceDictionary indicates which APIs are available. Note that because
ResourceDictionary has a projected API to support its underlying collection interfaces, your API options differ
depending on whether you are using C# or Visual Basic versus C++/CX.

ResourceDictionary and localization


A XAML ResourceDictionary might initially contain strings that are to be localized. If so, store these strings as
project resources instead of in a ResourceDictionary. Take the strings out of the XAML, and instead give the
owning element an x:Uid directive value. Then, define a resource in a resources file. Provide a resource name in the
form XUIDValue.PropertyName and a resource value of the string that should be localized.

Custom resource lookup


For advanced scenarios, you can implement a class that can have different behavior than the XAML resource
reference lookup behavior described in this topic. To do this, you implement the class CustomXamlResourceLoader,
and then you can access that behavior by using the CustomResource markup extension for resource references
rather than using StaticResource or ThemeResource. Most apps won't have scenarios that require this. For more
info, see CustomXamlResourceLoader.
Related topics
ResourceDictionary
XAML overview
StaticResource markup extension
ThemeResource markup extension
XAML theme resources
Styling controls
x:Key attribute
XAML theme resources
5/22/2017 13 min to read Edit Online

Theme resources in XAML are a set of resources that apply different values depending on which system theme is
active. There are 3 themes that the XAML framework supports: "Light", "Dark", and "HighContrast".
Prerequisites
This topic assumes that you have read ResourceDictionary and XAML resource references.

How theme resources differ from static resources


There are two XAML markup extensions that can reference a XAML resource from an existing XAML resource
dictionary: {StaticResource} markup extension and {ThemeResource} markup extension.
Evaluation of a {ThemeResource} markup extension occurs when the app loads and subsequently each time the
theme changes at runtime. This is typically the result of the user changing their device settings or from a
programmatic change within the app that alters its current theme.
In contrast, a {StaticResource} markup extension is evaluated only when the XAML is first loaded by the app. It does
not update. Its similar to a find and replace in your XAML with the actual runtime value at app launch.

Theme resources and where they fit in the resource dictionary


structure
Each theme resource is part of the XAML file themeresources.xaml. For design purposes, themeresources.xaml is
available in the \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK
version>\Generic folder from a Windows Software Development Kit (SDK) installation. The resource dictionaries in
themeresources.xaml are also reproduced in generic.xaml in the same directory.

Note The Windows Runtime doesn't use these physical files for runtime lookup. That's why they are
specifically in a DesignTime folder, and they aren't copied into apps by default. Instead, these resource
dictionaries exist in memory as part of the Windows Runtime itself, and your app's XAML resource references
to theme resources (or system resources) resolve there at runtime.

Guidelines for using theme resources


Follow these guidelines when you define and consume your own custom theme resources.
DO:
Specify theme dictionaries for both "Light" and "Dark" in addition to your "HighContrast" dictionary. Although
you can create a ResourceDictionary with "Default" as the key, its preferred to be explicit and instead use
"Light", "Dark", and "HighContrast".
Use the {ThemeResource} markup extension in: Styles, Setters, Control templates, Property setters, and
Animations.
DO NOT:
Use the {ThemeResource} markup extension in your resource definitions inside your ThemeDictionaries.
Use {StaticResource} markup extension instead.
EXCEPTION: it is alright to use the {ThemeResource} markup extension to reference resources that are
agnostic to the app theme in your ThemeDictionaries. Examples of these resources are accent color
resources like SystemAccentColor , or system color resources, which are typically prefixed with "SystemColor"
like SystemColorButtonFaceColor .
Caution If you dont follow these guidelines, you might see unexpected behavior related to themes in your app.
For more info, see the Troubleshooting theme resources section.

The XAML color ramp and theme-dependent brushes


The combined set of colors for "Light", "Dark", and "HighContrast" themes make up the Windows color ramp in
XAML. Whether you want to modify the system themes, or apply a system theme to your own XAML elements, its
important to understand how the color resources are structured.
Light and Dark theme colors
The XAML framework provides a set of named Color resources with values that are tailored for the "Light" and
"Dark" themes. The keys you use to reference these follow the naming format: System[Simple Light/Dark Name]Color .
This table lists the key, simple name, and string representation of the color (using the #aarrggbb format) for the
"Light" and "Dark" resources provided by the XAML framework. The key is used to reference the resource in an
app. The "Simple light/dark name" is used as part of the brush naming convention that we explain later.

KEY SIMPLE LIGHT/DARK NAME LIGHT DARK

SystemAltHighColor AltHigh #FFFFFFFF #FF000000

SystemAltLowColor AltLow #33FFFFFF #33000000

SystemAltMediumColor AltMedium #99FFFFFF #99000000

SystemAltMediumHighColor AltMediumHigh #CCFFFFFF #CC000000

SystemAltMediumLowColor AltMediumLow #66FFFFFF #66000000

SystemBaseHighColor BaseHigh #FF000000 #FFFFFFFF

SystemBaseLowColor BaseLow #33000000 #33FFFFFF

SystemBaseMediumColor BaseMedium #99000000 #99FFFFFF

SystemBaseMediumHighCol BaseMediumHigh #CC000000 #CCFFFFFF


or

SystemBaseMediumLowColo BaseMediumLow #66000000 #66FFFFFF


r

SystemChromeAltLowColor ChromeAltLow #FF171717 #FFF2F2F2

SystemChromeBlackHighCol ChromeBlackHigh #FF000000 #FF000000


or

SystemChromeBlackLowCol ChromeBlackLow #33000000 #33000000


or
KEY SIMPLE LIGHT/DARK NAME LIGHT DARK

SystemChromeBlackMedium ChromeBlackMediumLow #66000000 #66000000


LowColor

SystemChromeBlackMedium ChromeBlackMedium #CC000000 #CC000000


Color

SystemChromeDisabledHigh ChromeDisabledHigh #FFCCCCCC #FF333333


Color

SystemChromeDisabledLow ChromeDisabledLow #FF7A7A7A #FF858585


Color

SystemChromeHighColor ChromeHigh #FFCCCCCC #FF767676

SystemChromeLowColor ChromeLow #FFF2F2F2 #FF171717

SystemChromeMediumColo ChromeMedium #FFE6E6E6 #FF1F1F1F


r

SystemChromeMediumLow ChromeMediumLow #FFF2F2F2 #FF2B2B2B


Color

SystemChromeWhiteColor ChromeWhite #FFFFFFFF #FFFFFFFF

SystemListLowColor ListLow #19000000 #19FFFFFF

SystemListMediumColor ListMedium #33000000 #33FFFFFF

Windows system high-contrast colors


In addition to the set of resources provided by the XAML framework, there's a set of color values derived from the
Windows system palette. These colors are not specific to the Windows Runtime or Universal Windows Platform
(UWP) apps. However, many of the XAML Brush resources consume these colors when the system is operating
(and the app is running) using the "HighContrast" theme. The XAML framework provides these system-wide colors
as keyed resources. The keys follow the naming format: SystemColor[name]Color .
This table lists the system-wide colors that XAML provides as resource objects derived from the Windows system
palette. The "Ease of Access name" column shows how color is labeled in the Windows settings UI. The "Simple
HighContrast name" column is a one word description of how the color is applied across the XAML common
controls. It's used as part of the brush naming convention that we explain later. The "Initial default" column shows
the values you'd get if the system is not running in high contrast at all.

KEY EASE OF ACCESS NAME SIMPLE HIGHCONTRAST NAME INITIAL DEFAULT

SystemColorButtonFaceColo Button Text (background) Background #FFF0F0F0


r

SystemColorButtonTextColo Button Text (foreground) Foreground #FF000000


r

SystemColorGrayTextColor Disabled Text Disabled #FF6D6D6D

SystemColorHighlightColor Selected Text (background) Highlight #FF3399FF


KEY EASE OF ACCESS NAME SIMPLE HIGHCONTRAST NAME INITIAL DEFAULT

SystemColorHighlightTextCo Selected Text (foreground) HighlightAlt #FFFFFFFF


lor

SystemColorHotlightColor Hyperlinks Hyperlink #FF0066CC

SystemColorWindowColor Background PageBackground #FFFFFFFF

SystemColorWindowTextCol Text PageText #FF000000


or

Windows provides different high-contrast themes, and enables the user to set the specific colors to for their high-
contrast settings through the Ease of Access Center, as shown here. Therefore, it's not possible to provide a
definitive list of high-contrast color values.

For more info about supporting high-contrast themes, see High-contrast themes.
System accent color
In addition to the system high-contrast theme colors, the system accent color is provided as a special color
resource using the key SystemAccentColor . At runtime, this resource gets the color that the user has specified as the
accent color in the Windows personalization settings.

Note Its possible to override the system color resources for high-contrast color and accent color by creating
resources with the same names, but its a best practice to respect the users color choices, especially for high-
contrast settings.

Theme-dependent brushes
The color resources shown in the preceding sections are used to set the Color property of SolidColorBrush
resources in the system theme resource dictionaries. You use the brush resources to apply the color to XAML
elements. The keys for the brush resources follow the naming format:
SystemControl[Simple HighContrast name][Simple light/dark name]Brush . For example, SystemControlBackroundAltHighBrush .

Lets look at how the color value for this brush is determined at run-time. In the "Light" and "Dark" resource
dictionaries, this brush is defined like this:
<SolidColorBrush x:Key="SystemControlBackgroundAltHighBrush" Color="{StaticResource SystemAltHighColor}"/>

In the "HighContrast" resource dictionary, this brush is defined like this:


<SolidColorBrush x:Key="SystemControlBackgroundAltHighBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>

When this brush is applied to a XAML element, its color is determined at run-time by the current theme, as shown
in this table.

THEME COLOR SIMPLE NAME COLOR RESOURCE RUNTIME VALUE

Light AltHigh SystemAltHighColor #FFFFFFFF

Dark AltHigh SystemAltHighColor #FF000000

HighContrast Background SystemColorButtonFaceColo The color specified in


r settings for the button
background.

You can use the SystemControl[Simple HighContrast name][Simple light/dark name]Brush naming scheme to determine which
brush to apply to your own XAML elements.

Note Not every combination of [Simple HighContrast name][Simple light/dark name] is provided as a brush
resource.

The XAML type ramp


The themeresources.xaml file defines several resources that define a Style that you can apply to text containers in
your UI, specifically for either TextBlock or RichTextBlock. These are not the default implicit styles. They are
provided to make it easier for you to create XAML UI definitions that match the Windows type ramp documented
in Guidelines for fonts.
These styles are for text attributes that you want applied to the whole text container. If you want styles applied just
to sections of the text, set attributes on the text elements within the container, such as on a Run in TextBlock.Inlines
or on a Paragraph in RichTextBlock.Blocks.
The styles look like this when applied to a TextBlock:
BaseTextBlockStyle
TargetType: TextBlock
Supplies the common properties for all the other TextBlock container styles.

<!-- Usage -->


<TextBlock Text="Base" Style="{StaticResource BaseTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="BaseTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="TextTrimming" Value="None"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="LineStackingStrategy" Value="MaxHeight"/>
<Setter Property="TextLineBounds" Value="Full"/>
</Style>

HeaderTextBlockStyle

<!-- Usage -->


<TextBlock Text="Header" Style="{StaticResource HeaderTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="HeaderTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="46"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

SubheaderTextBlockStyle

<!-- Usage -->


<TextBlock Text="SubHeader" Style="{StaticResource SubheaderTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="SubheaderTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="34"/>
<Setter Property="FontWeight" Value="Light"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>
TitleTextBlockStyle

<!-- Usage -->


<TextBlock Text="Title" Style="{StaticResource TitleTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="TitleTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontWeight" Value="SemiLight"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

SubtitleTextBlockStyle

<!-- Usage -->


<TextBlock Text="SubTitle" Style="{StaticResource SubtitleTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="SubtitleTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

BodyTextBlockStyle

<!-- Usage -->


<TextBlock Text="Body" Style="{StaticResource BodyTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="BodyTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="FontSize" Value="15"/>
</Style>

CaptionTextBlockStyle

<!-- Usage -->


<TextBlock Text="Caption" Style="{StaticResource CaptionTextBlockStyle}"/>

<!-- Style definition -->


<Style x:Key="CaptionTextBlockStyle" TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Normal"/>
</Style>

BaseRichTextBlockStyle
TargetType: RichTextBlock
Supplies the common properties for all the other RichTextBlock container styles.
<!-- Usage -->
<RichTextBlock Style="{StaticResource BaseRichTextBlockStyle}">
<Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->


<Style x:Key="BaseRichTextBlockStyle" TargetType="RichTextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="15"/>
<Setter Property="TextTrimming" Value="None"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="LineStackingStrategy" Value="MaxHeight"/>
<Setter Property="TextLineBounds" Value="Full"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

BodyRichTextBlockStyle

<!-- Usage -->


<RichTextBlock Style="{StaticResource BodyRichTextBlockStyle}">
<Paragraph>Rich text.</Paragraph>
</RichTextBlock>

<!-- Style definition -->


<Style x:Key="BodyRichTextBlockStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaseRichTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
</Style>

Note The RichTextBlock styles don't have all the text ramp styles that TextBlock does, mainly because the
block-based document object model for RichTextBlock makes it easier to set attributes on the individual text
elements. Also, setting TextBlock.Text using the XAML content property introduces a situation where there is no
text element to style and thus you'd have to style the container. That isn't an issue for RichTextBlock because
its text content always has to be in specific text elements like Paragraph, which is where you might apply XAML
styles for page header, page subheader and similar text ramp definitions.

Miscellaneous Named styles


There's an additional set of keyed Style definitions you can apply to style a Button differently than its default
implicit style.
TextBlockButtonStyle
TargetType: ButtonBase
Apply this style to a Button when you need to show text that a user can click to take action. The text is styled using
the current accent color to distinguish it as interactive and has focus rectangles that work well for text. Unlike the
implicit style of a HyperlinkButton, the TextBlockButtonStyle does not underline the text.
The template also styles the presented text to use SystemControlHyperlinkBaseMediumBrush (for
"PointerOver" state), SystemControlHighlightBaseMediumLowBrush (for "Pressed" state) and
SystemControlDisabledBaseLowBrush (for "Disabled" state).
Here's a Button with the TextBlockButtonStyle resource applied to it.

<Button Content="Clickable text" Style="{StaticResource TextBlockButtonStyle}"


Click="Button_Click"/>
It looks like this:

NavigationBackButtonNormalStyle
TargetType: Button
This Style provides a complete template for a Button that can be the navigation back button for a navigation app. It
includes theme resource references that make this button use the Segoe MDL2 Assets symbol font, so you should
use a Symbol value as the content rather than text. The default dimensions are 40 x 40 pixels. To tailor the styling
you can either explicitly set the Height, Width, FontSize, and other properties on your Button or create a derived
style using BasedOn.
Here's a Button with the NavigationBackButtonNormalStyle resource applied to it.

<Button Content="&amp;#xE830;" Style="{StaticResource NavigationBackButtonNormalStyle}"


Click="Button_Click"/>

It looks like this:

NavigationBackButtonSmallStyle
TargetType: Button
This Style provides a complete template for a Button that can be the navigation back button for a navigation app.
It's similar to NavigationBackButtonNormalStyle, but its dimensions are 30 by 30 pixels.
Here's a Button with the NavigationBackButtonSmallStyle resource applied to it.

<Button Content="&amp;#xE830;" Style="{StaticResource NavigationBackButtonSmallStyle}"


Click="Button_Click"/>

Troubleshooting theme resources


If you dont follow the guidelines for using theme resources, you might see unexpected behavior related to themes
in your app.
For example, when you open a light-themed flyout, parts of your dark-themed app also change as if they were in
the light theme. Or if you navigate to a light-themed page and then navigate back, the original dark-themed page
(or parts of it) now looks as though it is in the light theme.
Typically, these types of issues occur when you provide a "Default" theme and a "HighContrast" theme to support
high-contrast scenarios, and then use both "Light" and "Dark" themes in different parts of your app.
For example, consider this theme dictionary definition:
<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemBaseHighColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Intuitively, this looks correct. You want to change the color pointed to by myBrush when in high-contrast, but when
not in high-contrast, you rely on the {ThemeResource} markup extension to make sure that myBrush points to the
right color for your theme. If your app never has FrameworkElement.RequestedTheme set on elements within its
visual tree, this will typically work as expected. However, you run into problems in your app as soon as you start to
re-theme different parts of your visual tree.
The problem occurs because brushes are shared resources, unlike most other XAML types. If you have 2 elements
in XAML sub-trees with different themes that reference the same brush resource, then as the framework walks
each sub-tree to update its {ThemeResource} markup extension expressions, changes to the shared brush resource
are reflected in the other sub-tree, which is not your intended result.
To fix this, replace the "Default" dictionary with separate theme dictionaries for both "Light" and "Dark" themes in
addition to "HighContrast":

<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->


<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemBaseHighColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemBaseHighColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

However, problems still occur if any of these resources are referenced in inherited properties like Foreground.
Your custom control template might specify the foreground color of an element using the {ThemeResource}
markup extension, but when the framework propagates the inherited value to child elements, it provides a direct
reference to the resource that was resolved by the {ThemeResource} markup extension expression. This causes
problems when the framework processes theme changes as it walks your control's visual tree. It re-evaluates the
{ThemeResource} markup extension expression to get a new brush resource but doesnt yet propagate this
reference down to the children of your control; this happens later, such as during the next measure pass.
As a result, after walking the control visual tree in response to a theme change, the framework walks the children
and updates any {ThemeResource} markup extension expressions set on them, or on objects set on their
properties. This is where the problem occurs; the framework walks the brush resource and because it specifies its
color using a {ThemeResource} markup extension, it's re-evaluated.
At this point, the framework appears to have polluted your theme dictionary because it now has a resource from
one dictionary that has its color set from another dictionary.
To fix this problem, use the {StaticResource} markup extension instead of {ThemeResource} markup extension.
With the guidelines applied, the theme dictionaries look like this:

<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="myBrush" Color="{StaticResource SystemBaseHighColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="myBrush" Color="{StaticResource SystemBaseHighColor}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

Notice that the {ThemeResource} markup extension is still used in the "HighContrast" dictionary instead of
{StaticResource} markup extension. This situation falls under the exception given earlier in the guidelines. Most of
the brush values that are used for the "HighContrast" theme are using color choices that are globally controlled by
the system, but exposed to XAML as a specially-named resource (those prefixed with SystemColor in the name).
The system enables the user to set the specific colors that should be used for their high contrast settings through
the Ease of Access Center. Those color choices are applied to the specially-named resources. The XAML framework
uses the same theme changed event to also update these brushes when it detects theyve changed at the system
level. This is why the {ThemeResource} markup extension is used here.
Controls and patterns for UWP apps
8/9/2017 1 min to read Edit Online

In UWP app development, a control is a UI element that displays content or enables interaction. Controls are the
building blocks of the user interface. A pattern is a recipe for combining several controls to make something new.
We provide 45+ controls for you to use, ranging from simple buttons to powerful data controls like the grid view.
These controls are a part of the Fluent Design System and can help you create a bold, scalable UI that looks great
on all devices and screen sizes.
The articles in this section provide design guidance and coding instructions for adding controls & patterns to your
UWP app.

Intro
General instructions and code examples for adding and styling controls in XAML and C#.

Add controls and handle events


There are 3 key steps to adding controls to your app: Add a control to your app UI, set properties on the control,
and add code to the control's event handlers so that it does something.

Styling controls
You can customize the appearance of your apps in many ways by using the XAML framework. Styles let you set
control properties and reuse those settings for a consistent appearance across multiple controls.

Alphabetical index
Detailed information about specific controls and patterns. (For a list sorted by function, see Index of controls by
function.)

Auto-suggest box
Bars
Buttons
Checkbox
Color picker
Date and time controls
Dialogs and flyouts
Flip view
Hub
Hyperlinks
Images and image brushes
Inking controls
Lists
Map control
Master/details
Media playback
Menus and context menus
Nav view
Person picture
Progress controls
Radio button
Rating control
Scrolling and panning controls
Search
Semantic zoom
Slider
Split view
Tabs and pivots
Text controls
Tiles, badges, and notifications
Toggle
Tooltips
Tree view
Web view

Additional controls
Additional controls for UWP development are available from companies such as Telerik, SyncFusion, DevExpress,
Infragistics, ComponentOne, and ActiPro. These controls provide additional support for enterprise and .NET
developers by augmenting the standard system controls with custom controls and services.
If you're interested in learning more about these controls, check out the Customer orders database sample on
GitHub. This sample makes use of the data grid control and data entry validation from Telerik, which is part of their
UI for UWP suite. The UI for UWP suite is a collection of over 20 controls that is available as an open source project
through the .NET foundation.
Intro to controls and patterns
5/22/2017 6 min to read Edit Online

In UWP app development, a control is a UI element that displays content or enables interaction. You create the UI
for your app by using controls such as buttons, text boxes, and combo boxes to display data and get user input.

Important APIs: Windows.UI.Xaml.Controls namespace

A pattern is a recipe for modifying a control or combining several controls to make something new. For example,
the Nav pane pattern is a way that you can use a SplitView control for app navigation. Similarly, you can customize
the template of a Pivot control to implement the tab pattern.
In many cases, you can use a control as-is. But XAML controls separate function from structure and appearance, so
you can make various levels of modification to make them fit your needs. In the Style section, you can learn how to
use XAML styles and control templates to modify a control.
In this section, we provide guidance for each of the XAML controls you can use to build your app UI. To start, this
article shows you how to add controls to your app. There are 3 key steps to using controls to your app:
Add a control to your app UI.
Set properties on the control, such as width, height, or foreground color.
Add code to the control's event handlers so that it does something.

Add a control
You can add a control to an app in several ways:
Use a design tool like Blend for Visual Studio or the Microsoft Visual Studio Extensible Application Markup
Language (XAML) designer.
Add the control to the XAML markup in the Visual Studio XAML editor.
Add the control in code. Controls that you add in code are visible when the app runs, but are not visible in the
Visual Studio XAML designer.
In Visual Studio, when you add and manipulate controls in your app, you can use many of the program's features,
including the Toolbox, XAML designer, XAML editor, and the Properties window.
The Visual Studio Toolbox displays many of the controls that you can use in your app. To add a control to your app,
double-click it in the Toolbox. For example, when you double-click the TextBox control, this XAML is added to the
XAML view.

<TextBox HorizontalAlignment="Left" Text="TextBox" VerticalAlignment="Top"/>

You can also drag the control from the Toolbox to the XAML designer.

Set the name of a control


To work with a control in code, you set its x:Name attribute and reference it by name in your code. You can set the
name in the Visual Studio Properties window or in XAML. Here's how to set the name of the currently selected
control by using the Name text box at the top of the Properties window.
To name a control
1. Select the element to name.
2. In the Properties panel, type a name into the Name text box.
3. Press Enter to commit the name.

Here's how to set the name of a control in the XAML editor by adding the x:Name attribute.

<Button x:Name="Button1" Content="Button"/>

Set the control properties


You use properties to specify the appearance, content, and other attributes of controls. When you add a control
using a design tool, some properties that control size, position, and content might be set for you by Visual Studio.
You can change some properties, such as Width, Height or Margin, by selecting and manipulating the control in the
Design view. This illustration shows some of the resizing tools available in Design view.

You might want to let the control be sized and positioned automatically. In this case, you can reset the size and
position properties that Visual Studio set for you.
To reset a property
1. In the Properties panel, click the property marker next to the property value. The property menu opens.
2. In the property menu, click Reset.

You can set control properties in the Properties window, in XAML, or in code. For example, to change the
foreground color for a Button, you set the control's Foreground property. This illustration shows how to set the
Foreground property by using the color picker in the Properties window.
Here's how to set the Foreground property in the XAML editor. Notice the Visual Studio IntelliSense window that
opens to help you with the syntax.

Here's the resulting XAML after you set the Foreground property.

<Button x:Name="Button1" Content="Button"


HorizontalAlignment="Left" VerticalAlignment="Top"
Foreground="Beige"/>

Here's how to set the Foreground property in code.

Button1.Foreground = new SolidColorBrush(Windows.UI.Colors.Beige);


Create an event handler
Each control has events that enable you to respond to actions from your user or other changes in your app. For
example, a Button control has a Click event that is raised when a user clicks the Button. You create a method, called
an event handler, to handle the event. You can associate a control's event with an event handler method in the
Properties window, in XAML, or in code. For more info about events, see Events and routed events overview.
To create an event handler, select the control and then click the Events tab at the top of the Properties window. The
Properties window lists all of the events available for that control. Here are some of the events for a Button.

To create an event handler with the default name, double-click the text box next to the event name in the Properties
window. To create an event handler with a custom name, type the name of your choice into the text box and press
enter. The event handler is created and the code-behind file is opened in the code editor. The event handler method
has 2 parameters. The first is sender , which is a reference to the object where the handler is attached. The sender
parameter is an Object type. You typically cast sender to a more precise type if you expect to check or change the
state on the sender object itself. Based on your own app design, you expect a type that is safe to cast the sender to,
based on where the handler is attached. The second value is event data, which generally appears in signatures as
the e or args parameter.
Here's code that handles the Click event of a Button named Button1 . When you click the button, the Foreground
property of the Button you clicked is set to blue.

private void Button_Click(object sender, RoutedEventArgs e)


{
Button b = (Button)sender;
b.Foreground = new SolidColorBrush(Windows.UI.Colors.Blue);
}

You can also associate an event handler in XAML. In the XAML editor, type in the event name that you want to
handle. Visual Studio shows an IntelliSense window when you begin typing. After you specify the event, you can
double-click <New Event Handler> in the IntelliSense window to create a new event handler with the default name, or
select an existing event handler from the list.
Here's the IntelliSense window that appears. It helps you create a new event handler or select an existing event
handler.
This example shows how to associate a Click event with an event handler named Button_Click in XAML.

<Button Name="Button1" Content="Button" Click="Button_Click"/>

You can also associate an event with its event handler in the code-behind. Here's how to associate an event handler
in code.

Button1.Click += new RoutedEventHandler(Button_Click);

Related topics
Index of controls by function
Windows.UI.Xaml.Controls namespace
Layout
Style
Usability
Controls by function
6/13/2017 9 min to read Edit Online

The XAML UI framework for Windows provides an extensive library of controls that support UI development. Some
of these controls have a visual representation; others function as the containers for other controls or content, such
as images and media.
You can see many of the Windows UI controls in action by downloading the XAML UI Basics sample.
Here's a list by function of the common XAML controls you can use in your app.

Appbars and commands


App bar
A toolbar for displaying application-specific commands. See Command bar.
Reference: AppBar
App bar button
A button for showing commands using app bar styling.

Reference: AppBarButton, SymbolIcon, BitmapIcon, FontIcon, PathIcon


Design and how-to: App bar and command bar control guide
Sample code: XAML Commanding sample
App bar separator
Visually separates groups of commands in a command bar.
Reference: AppBarSeparator
Sample code: XAML Commanding sample
App bar toggle button
A button for toggling commands in a command bar.
Reference: AppBarToggleButton
Sample code: XAML Commanding sample
Command bar
A specialized app bar that handles the resizing of app bar button elements.
<CommandBar>
<AppBarButton Icon="Back" Label="Back" Click="AppBarButton_Click"/>
<AppBarButton Icon="Stop" Label="Stop" Click="AppBarButton_Click"/>
<AppBarButton Icon="Play" Label="Play" Click="AppBarButton_Click"/>
</CommandBar>

Reference: CommandBar
Design and how-to: App bar and command bar control guide
Sample code: XAML Commanding sample

Buttons
Button
A control that responds to user input and raises a Click event.

<Button x:Name="button1" Content="Button"


Click="Button_Click" />

Reference: Button
Design and how-to: Buttons control guide
Hyperlink
See Hyperlink button.
Hyperlink button
A button that appears as marked up text and opens the specified URI in a browser.

<HyperlinkButton Content="www.microsoft.com"
NavigateUri="http://www.microsoft.com"/>

Reference: HyperlinkButton
Design and how-to: Hyperlinks control guide
Repeat button
A button that raises its Click event repeatedly from the time it's pressed until it's released.
<RepeatButton x:Name="repeatButton1" Content="Repeat Button"
Click="RepeatButton_Click" />

Reference: RepeatButton
Design and how-to: Buttons control guide

Collection/data controls
Flip view
A control that presents a collection of items that the user can flip through, one item at a time.

<FlipView x:Name="flipView1" SelectionChanged="FlipView_SelectionChanged">


<Image Source="Assets/Logo.png" />
<Image Source="Assets/SplashScreen.png" />
<Image Source="Assets/SmallLogo.png" />
</FlipView>

Reference: FlipView
Design and how-to: Flip view control guide
Grid view
A control that presents a collection of items in rows and columns that can scroll vertically.

<GridView x:Name="gridView1" SelectionChanged="GridView_SelectionChanged">


<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
</GridView>

Reference: GridView
Design and how-to: Lists
Sample code: ListView sample
Items control
A control that presents a collection of items in a UI specified by a data template.

<ItemsControl/>

Reference: ItemsControl
List view
A control that presents a collection of items in a list that can scroll vertically.
<ListView x:Name="listView1" SelectionChanged="ListView_SelectionChanged">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
</ListView>

Reference: ListView
Design and how-to: Lists
Sample code: ListView sample

Date and time controls


Calendar date picker
A control that lets a user select a date using a drop-down calendar display.

<CalendarDatePicker/>

Reference: CalendarDatePicker
Design and how-to: Calendar, date, and time controls
Calendar view
A configurable calendar display that lets a user select single or multiple dates.

<CalendarView/>

Reference: CalendarView
Design and how-to: Calendar, date, and time controls
Date picker
A control that lets a user select a date.

<DatePicker Header="Arrival Date"/>

Reference: DatePicker
Design and how-to: Calendar, date, and time controls
Time picker
A control that lets a user set a time value.

<TimePicker Header="Arrival Time"/>

Reference: TimePicker
Design and how-to: Calendar, date, and time controls

Flyouts
Context menu
See Menu flyout and Popup menu.
Flyout
Displays a message that requires user interaction. (Unlike a dialog, a flyout does not create a separate window, and
does not block other user interaction.)

<Flyout>
<StackPanel>
<TextBlock Text="All items will be removed. Do you want to continue?"/>
<Button Click="DeleteConfirmation_Click" Content="Yes, empty my cart"/>
</StackPanel>
</Flyout>

Reference: Flyout
Design and how-to: Context menus and dialogs
Menu flyout
Temporarily displays a list of commands or options related to what the user is currently doing.
<MenuFlyout>
<MenuFlyoutItem Text="Reset" Click="Reset_Click"/>
<MenuFlyoutSeparator/>
<ToggleMenuFlyoutItem Text="Shuffle"
IsChecked="{Binding IsShuffleEnabled, Mode=TwoWay}"/>
<ToggleMenuFlyoutItem Text="Repeat"
IsChecked="{Binding IsRepeatEnabled, Mode=TwoWay}"/>
</MenuFlyout>

Reference: MenuFlyout, MenuFlyoutItem, MenuFlyoutSeparator, ToggleMenuFlyoutItem


Design and how-to: Context menus and dialogs
Sample code: XAML Context Menu sample
Popup menu
A custom menu that presents commands that you specify.
Reference: PopupMenu
Design and how-to: Context menus and dialogs
Tooltip
A pop-up window that displays information for an element.

<Button Content="Button" Click="Button_Click"


ToolTipService.ToolTip="Click to perform action" />

Reference: ToolTip, ToolTipService


Design and how-to: Guidelines for tooltips

Images
Image
A control that presents an image.
<Image Source="Assets/Logo.png" />

Reference: Image
Design and how-to: Image and ImageBrush
Sample code: XAML images sample

Graphics and ink


InkCanvas
A control that receives and displays ink strokes.

<InkCanvas/>

Reference: InkCanvas
Shapes
Various retained mode graphical objects that can be presented like ellipses, rectangles, lines, Bezier paths, etc.

<Ellipse/>
<Path/>
<Rectangle/>

Reference: Shapes
How to: Drawing shapes
Sample code: XAML vector-based drawing sample

Layout controls
Border
A container control that draws a border, background, or both, around another object.
<Border BorderBrush="Blue" BorderThickness="4"
Height="108" Width="64"
Padding="8" CornerRadius="4">
<Canvas>
<Rectangle Fill="Orange"/>
<Rectangle Fill="Green" Margin="0,44"/>
</Canvas>
</Border>

Reference: Border
Canvas
A layout panel that supports the absolute positioning of child elements relative to the top left corner of the canvas.

<Canvas Width="120" Height="120">


<Rectangle Fill="Red"/>
<Rectangle Fill="Blue" Canvas.Left="20" Canvas.Top="20"/>
<Rectangle Fill="Green" Canvas.Left="40" Canvas.Top="40"/>
<Rectangle Fill="Orange" Canvas.Left="60" Canvas.Top="60"/>
</Canvas>

Reference: Canvas
Grid
A layout panel that supports the arranging of child elements in rows and columns.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Rectangle Fill="Red"/>
<Rectangle Fill="Blue" Grid.Row="1"/>
<Rectangle Fill="Green" Grid.Column="1"/>
<Rectangle Fill="Orange" Grid.Row="1" Grid.Column="1"/>
</Grid>

Reference: Grid
Panning scroll viewer
See Scroll viewer.
RelativePanel
A panel that lets you position and align child objects in relation to each other or the parent panel.

<RelativePanel>
<TextBox x:Name="textBox1" RelativePanel.AlignLeftWithPanel="True"/>
<Button Content="Submit" RelativePanel.Below="textBox1"/>
</RelativePanel>

Reference: RelativePanel
Scroll bar
See scroll viewer. (ScrollBar is an element of ScrollViewer. You don't typically use it as a stand-alone control.)
Reference: ScrollBar
Scroll viewer
A container control that lets the user pan and zoom its content.

<ScrollViewer ZoomMode="Enabled" MaxZoomFactor="10"


HorizontalScrollMode="Enabled"
HorizontalScrollBarVisibility="Visible"
Height="200" Width="200">
<Image Source="Assets/Logo.png" Height="400" Width="400"/>
</ScrollViewer>

Reference: ScrollViewer
Design and how-to: Scroll and panning controls guide
Sample code: XAML scrolling, panning and zooming sample
Stack panel
A layout panel that arranges child elements into a single line that can be oriented horizontally or vertically.

<StackPanel>
<Rectangle Fill="Red"/>
<Rectangle Fill="Blue"/>
<Rectangle Fill="Green"/>
<Rectangle Fill="Orange"/>
</StackPanel>

Reference: StackPanel
VariableSizedWrapGrid
A layout panel that supports the arranging of child elements in rows and columns. Each child element can span
multiple rows and columns.

<VariableSizedWrapGrid MaximumRowsOrColumns="3" ItemHeight="44" ItemWidth="44">


<Rectangle Fill="Red"/>
<Rectangle Fill="Blue" Height="80"
VariableSizedWrapGrid.RowSpan="2"/>
<Rectangle Fill="Green" Width="80"
VariableSizedWrapGrid.ColumnSpan="2"/>
<Rectangle Fill="Orange" Height="80" Width="80"
VariableSizedWrapGrid.RowSpan="2"
VariableSizedWrapGrid.ColumnSpan="2"/>
</VariableSizedWrapGrid>

Reference: VariableSizedWrapGrid
Viewbox
A container control that scales its content to a specified size.
<Viewbox MaxWidth="25" MaxHeight="25">
<Image Source="Assets/Logo.png"/>
</Viewbox>
<Viewbox MaxWidth="75" MaxHeight="75">
<Image Source="Assets/Logo.png"/>
</Viewbox>
<Viewbox MaxWidth="150" MaxHeight="150">
<Image Source="Assets/Logo.png"/>
</Viewbox>

Reference: Viewbox
Zooming scroll viewer
See Scroll viewer.

Media controls
Audio
See Media element.
Media element
A control that plays audio and video content.

<MediaElement x:Name="myMediaElement"/>

Reference: MediaElement
Design and how-to: Media element control guide
MediaTransportControls
A control that provides playback controls for a MediaElement.

<MediaTransportControls MediaElement="myMediaElement"/>

Reference: MediaTransportControls
Design and how-to: Media element control guide
Sample code: Media Transport Controls sample
Video
See Media element.
Navigation
Hub
A container control that lets the user view and navigate to different sections of content.

<Hub>
<HubSection>
<!--- hub section content -->
</HubSection>
<HubSection>
<!--- hub section content -->
</HubSection>
</Hub>

Reference: Hub
Design and how-to: Hub control guide
Sample code:XAML Hub control sample
Pivot
A full-screen container and navigation model that also provides a quick way to move between different pivots
(views or filters), typically in the same set of data.
The Pivot control can be styled to have a "tab" layout.
Reference: Pivot
Design and how-to: Tabs and pivot control guide
Sample code: Pivot sample
Semantic zoom
A container control that lets the user zoom between two views of a collection of items.

<SemanticZoom>
<ZoomedInView>
<GridView></GridView>
</ZoomedInView>
<ZoomedOutView>
<GridView></GridView>
</ZoomedOutView>
</SemanticZoom>

Reference: SemanticZoom
Design and how-to: Semantic zoom control guide
Sample code: XAML GridView grouping and SemanticZoom sample
SplitView
A container control with two views; one view for the main content and another view that is typically used for a
navigation menu.
<SplitView>
<SplitView.Pane>
<!-- Menu content -->
</SplitView.Pane>
<SplitView.Content>
<!-- Main content -->
</SplitView.Content>
</SplitView>

Reference: SplitView
Design and how-to: Split view control guide
Web view
A container control that hosts web content.

<WebView x:Name="webView1" Source="http://dev.windows.com"


Height="400" Width="800"/>

Reference: WebView
Design and how-to: Guidelines for Web views
Sample code: XAML WebView control sample

Progress controls
Progress bar
A control that indicates progress by displaying a bar.

A progress bar that shows a specific value.


<ProgressBar x:Name="progressBar1" Value="50" Width="100"/>

A progress bar that shows indeterminate progress.

<ProgressBar x:Name="indeterminateProgressBar1" IsIndeterminate="True" Width="100"/>

Reference: ProgressBar
Design and how-to: Progress controls guide
Progress ring
A control that indicates indeterminate progress by displaying a ring.

<ProgressRing x:Name="progressRing1" IsActive="True"/>

Reference: ProgressRing
Design and how-to: Progress controls guide

Text controls
Auto suggest box
A text input box that provides suggested text as the user types.

Reference: AutoSuggestBox
Design and how-to: Text controls, Auto suggest box control guide
Sample code: AutoSuggestBox migration sample
Multi-line text box
See Text box.
Password box
A control for entering passwords.
<PasswordBox x:Name="passwordBox1"
PasswordChanged="PasswordBox_PasswordChanged" />

Reference: PasswordBox
Design and how-to: Text controls, Password box control guide
Sample code: XAML text display sample, XAML text editing sample
Rich edit box
A control that lets a user edit rich text documents with content like formatted text, hyperlinks, and images.

<RichEditBox />

Reference: RichEditBox
Design and how-to: Text controls, Rich edit box control guide
Sample code: XAML text sample
Search box
See Auto suggest box.
Single-line text box
See Text box.
Static text/paragraph
See Text block.
Text block
A control that displays text.

<TextBlock x:Name="textBlock1" Text="I am a TextBlock"/>

Reference: TextBlock, RichTextBlock


Design and how-to: Text controls, Text block control guide, Rich text block control guide
Sample code: XAML text sample
Text box
A single-line or multi-line plain text field.
<TextBox x:Name="textBox1" Text="I am a TextBox"
TextChanged="TextBox_TextChanged"/>

Reference: TextBox
Design and how-to: Text controls, Text box control guide
Sample code: XAML text sample

Selection controls
Check box
A control that a user can select or clear.

<CheckBox x:Name="checkbox1" Content="CheckBox"


Checked="CheckBox_Checked"/>

Reference: CheckBox
Design and how-to: Check box control guide
Combo box
A drop-down list of items a user can select from.
<ComboBox x:Name="comboBox1" Width="100"
SelectionChanged="ComboBox_SelectionChanged">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</ComboBox>

Reference: ComboBox
Design and how-to: Lists
List box
A control that presents an inline list of items that the user can select from.

<ListBox x:Name="listBox1" Width="100"


SelectionChanged="ListBox_SelectionChanged">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</ListBox>

Reference: ListBox
Design and how-to: Lists
Radio button
A control that allows a user to select a single option from a group of options. When radio buttons are grouped
together, they are mutually exclusive.

<RadioButton x:Name="radioButton1" Content="RadioButton 1" GroupName="Group1"


Checked="RadioButton_Checked"/>
<RadioButton x:Name="radioButton2" Content="RadioButton 2" GroupName="Group1"
Checked="RadioButton_Checked" IsChecked="True"/>
<RadioButton x:Name="radioButton3" Content="RadioButton 3" GroupName="Group1"
Checked="RadioButton_Checked"/>

Reference: RadioButton
Design and how-to: Radio button control guide
Slider
A control that lets the user select from a range of values by moving a Thumb control along a track.

<Slider x:Name="slider1" Width="100" ValueChanged="Slider_ValueChanged" />

Reference: Slider
Design and how-to: Slider control guide
Toggle button
A button that can be toggled between 2 states.

<ToggleButton x:Name="toggleButton1" Content="Button"


Checked="ToggleButton_Checked"/>

Reference: ToggleButton
Design and how-to: Toggle control guide
Toggle switch
A switch that can be toggled between 2 states.

<ToggleSwitch x:Name="toggleSwitch1" Header="ToggleSwitch"


OnContent="On" OffContent="Off"
Toggled="ToggleSwitch_Toggled"/>

Reference: ToggleSwitch
Design and how-to: Toggle control guide
Command bar
5/23/2017 13 min to read Edit Online

Command bars (also called "app bars") provide users with easy access to your app's most common tasks, and
can be used to show commands or options that are specific to the user's context, such as a photo selection or
drawing mode. They can also be used for navigation among app pages or between app sections. Command bars
can be used with any navigation pattern.

Important APIs: CommandBar class, AppBarButton class, AppBarToggleButton class, AppBarSeparator class

Is this the right control?


The CommandBar control is a general-purpose, flexible, light-weight control that can display both complex
content, such as images or text blocks, as well as simple commands such as AppBarButton, AppBarToggleButton,
and AppBarSeparator controls.
XAML provides both the AppBar control and the CommandBar control. You should use the AppBar only when
you are upgrading a Universal Windows 8 app that uses the AppBar, and need to minimize changes. For new
apps in Windows 10, we recommend using the CommandBar control instead. This document assumes you are
using the CommandBar control.

Examples
An expanded command bar in the Microsoft Photos app.

A command bar in the Outlook Calendar on Windows Phone.


Anatomy
By default, the command bar shows a row of icon buttons and an optional "see more" button, which is
represented by an ellipsis []. Here's the command bar created by the example code shown later. It's shown in
its closed compact state.

The command bar can also be shown in a closed minimal state that looks like this. See the Open and closed
states section for more info.

Here's the same command bar in its open state. The labels identify the main parts of the control.

The command bar is divided into 4 main areas:


The "see more" [] button is shown on the right of the bar. Pressing the "see more" [] button has 2
effects: it reveals the labels on the primary command buttons, and it opens the overflow menu if any
secondary commands are present. In the newest SDK, the button will not be visible when no secondary
commands and no hidden labels are present. OverflowButtonVisibility property allows apps to change this
default auto-hide behavior.
The content area is aligned to the left side of the bar. It is shown if the Content property is populated.
The primary command area is aligned to the right side of the bar, next to the "see more" [] button. It is
shown if the PrimaryCommands property is populated.
The overflow menu is shown only when the command bar is open and the SecondaryCommands property is
populated. The new dynamic overflow behavior will automatically move primary commands into the
SecondaryCommands area when space is limited.
The layout is reversed when the FlowDirection is RightToLeft.

Create a command bar


This example creates the command bar shown previously.

<CommandBar>
<AppBarToggleButton Icon="Shuffle" Label="Shuffle" Click="AppBarButton_Click" />
<AppBarToggleButton Icon="RepeatAll" Label="Repeat" Click="AppBarButton_Click"/>
<AppBarSeparator/>
<AppBarButton Icon="Back" Label="Back" Click="AppBarButton_Click"/>
<AppBarButton Icon="Stop" Label="Stop" Click="AppBarButton_Click"/>
<AppBarButton Icon="Play" Label="Play" Click="AppBarButton_Click"/>
<AppBarButton Icon="Forward" Label="Forward" Click="AppBarButton_Click"/>

<CommandBar.SecondaryCommands>
<AppBarButton Icon="Like" Label="Like" Click="AppBarButton_Click"/>
<AppBarButton Icon="Dislike" Label="Dislike" Click="AppBarButton_Click"/>
</CommandBar.SecondaryCommands>

<CommandBar.Content>
<TextBlock Text="Now playing..." Margin="12,14"/>
</CommandBar.Content>
</CommandBar>

Commands and content


The CommandBar control has 3 properties you can use to add commands and content: PrimaryCommands,
SecondaryCommands, and Content.
Primary actions and overflow
By default, items you add to the command bar are added to the PrimaryCommands collection. These
commands are shown to the left of the "see more" [] button, in what we call the action space. Place the most
important commands, the ones that you want to remain visible in the bar, in the action space. On the smallest
screens (320 epx width), a maximum of 4 items will fit in the command bar's action space.
You can add commands to the SecondaryCommands collection, and these items are shown in the overflow
area. Place less important commands within the overflow area.
The default overflow area is styled to be distinct from the bar. You can adjust the styling by setting the
CommandBarOverflowPresenterStyle property to a Style that targets the CommandBarOverflowPresenter.
You can programmatically move commands between the PrimaryCommands and SecondaryCommands as
needed.
App bar buttons
Both the PrimaryCommands and SecondaryCommands can be populated only with AppBarButton,
AppBarToggleButton, and AppBarSeparator command elements. These controls are optimized for use in a
command bar, and their appearance changes depending on whether the control is used in the action space or
overflow area.
The app bar button controls are characterized by an icon and associated label. They have two sizes; normal and
compact. By default, the text label is shown. When the IsCompact property is set to true, the text label is hidden.
When used in a CommandBar control, the command bar overwrites the button's IsCompact property
automatically as the command bar is opened and closed.
To position app bar button labels to the right of their icons, apps can use CommandBar's new
DefaultLabelPosition property.

<CommandBar DefaultLabelPosition="Right">
<AppBarToggleButton Icon="Shuffle" Label="Shuffle"/>
<AppBarToggleButton Icon="RepeatAll" Label="Repeat"/>
</CommandBar>

Here is what the code snippet above looks like when drawn by an app.

Individual app bar buttons cannot move their label position, this must be done on the command bar as a whole.
App bar buttons can specify that their labels never show by setting the new LabelPosition property to
Collapsed. We recommend limiting the use of this setting to universally recognizable iconography such as '+'.
When you place an app bar button in the overflow menu (SecondaryCommands), it's shown as text only. The
LabelPosition of app bar buttons in the overflow will be ignored. Here's the same app bar toggle button shown
in the action space as a primary command (top), and in the overflow area as a secondary command (bottom).

If there is a command that would appear consistently across pages, it's best to keep that command in a
consistent location.
We recommended placing Accept, Yes, and OK commands to the left of Reject, No, and Cancel. Consistency
gives users the confidence to move around the system and helps them transfer their knowledge of app
navigation from app to app.
Button labels
We recommend keeping app bar button labels short, preferably a single word. Longer labels positioned bellow
an app bar button's icon will wrap to multiple lines thus increasing the overall height of the opened command
bar. You can include a soft-hyphen character (0x00AD) in the text for a label to hint at the character boundary
where a word break should occur. In XAML, you express this using an escape sequence, like this:

<AppBarButton Icon="Back" Label="Areally&#x00AD;longlabel"/>

When the label wraps at the hinted location, it looks like this.
Other content
You can add any XAML elements to the content area by setting the Content property. If you want to add more
than one element, you need to place them in a panel container and make the panel the single child of the
Content property.
When there are both primary commands and content, the primary commands take precedence and may cause
the content to be clipped.
When the ClosedDisplayMode is Compact, the content can be clipped if it is larger than the compact size of the
command bar. You should handle the Opening and Closed events to show or hide parts of the UI in the content
area so that they aren't clipped. See the Open and closed states section for more info.

Open and closed states


The command bar can be open or closed. A user can switch between these states by pressing the "see more"
[] button. You can switch between them programmatically by setting the IsOpen property. When open, the
primary command buttons are shown with text labels and the overflow menu is open if secondary commands
are present, as shown previously.
You can use the Opening, Opened, Closing, and Closed events to respond to the command bar being opened or
closed.
The Opening and Closing events occur before the transition animation begins.
The Opened and Closed events occur after the transition completes.
In this example, the Opening and Closing events are used to change the opacity of the command bar. When the
command bar is closed, it's semi-transparent so the app background shows through. When the command bar is
opened, the command bar is made opaque so the user can focus on the commands.

<CommandBar Opening="CommandBar_Opening"
Closing="CommandBar_Closing">
<AppBarButton Icon="Accept" Label="Accept"/>
<AppBarButton Icon="Edit" Label="Edit"/>
<AppBarButton Icon="Save" Label="Save"/>
<AppBarButton Icon="Cancel" Label="Cancel"/>
</CommandBar>

private void CommandBar_Opening(object sender, object e)


{
CommandBar cb = sender as CommandBar;
if (cb != null) cb.Background.Opacity = 1.0;
}

private void CommandBar_Closing(object sender, object e)


{
CommandBar cb = sender as CommandBar;
if (cb != null) cb.Background.Opacity = 0.5;
}

ClosedDisplayMode
You can control how the command bar is shown in its closed state by setting the ClosedDisplayMode property.
There are 3 closed display modes to choose from:
Compact: The default mode. Shows content, primary command icons without labels, and the "see more"
[] button.
Minimal: Shows only a thin bar that acts as the "see more" [] button. The user can press anywhere on the
bar to open it.
Hidden: The command bar is not shown when it's closed. This can be useful for showing contextual
commands with an inline command bar. In this case, you must open the command bar programmatically by
setting the IsOpen property or changing the ClosedDisplayMode to Minimal o