Chapter 25. Implementing the user interface for a Windows Store app

After completing the chapter, you will be able to:

Microsoft Windows Store apps are based on a new paradigm for applications that is arguably the biggest change in Windows client application development since the advent of the Microsoft .NET Framework just after the turn of the millennium. The continuously connected, touch-driven interface of Windows 8.1 together with the use of Windows contracts for interacting with other apps, the support for embedded sensors, and an updated app security and lifecycle model changes the way that users and apps work together. Using Microsoft Visual Studio 2013, developers can easily design and implement apps that can take advantage of the features of the Windows 8.1 platform.

The purpose of this chapter is to provide a brief description of this new paradigm and help you to get started using Visual Studio 2013 to build apps that operate in this environment. In this chapter, you will learn about some of the new features and tools included with Visual Studio 2013 for building Windows Store apps, and you will start to build an app that conforms to the Windows 8.1 look and feel. You will concentrate on learning how to implement a user interface (UI) that scales and adapts to different device resolutions and form factors, and how to apply styling to give the app a distinctive look and feel.

Note

There is not enough space in a book such as this to provide a comprehensive treatise on building Windows Store apps. Rather, these final chapters concentrate on the basic principles of building an interactive app that uses the Windows 8.1 UI. For detailed information on writing Windows Store apps, visit the “Developing Windows Store apps” page on the Microsoft website at http://msdn.microsoft.com/library/windows/apps/xaml/BR229566.

What is a Windows Store app?

Windows Store apps are graphical apps that have a distinctive look and feel, based on a few simple principles that you will learn about in this chapter and in Chapter 26 and Chapter 27. They are highly interactive, placing the user at the center of their operations. Microsoft has invested a significant amount of time (and money) in studies that examined how users like to work with apps and the most effective ways of displaying data and interacting with that data. The designers at Microsoft have applied this knowledge to develop the model that Windows Store apps should follow.

When a Windows Store app runs, it typically occupies the full screen, although Windows Store apps can operate in different display modes that you will learn about in this chapter. They are chromeless, meaning they do not have borders, drop-down menus, pop-up windows, or many of the other user interface features that can serve as a distraction to users. Instead, you design a Windows Store app to be clean and focused on helping the user to perform a specific set of tasks. Additionally, Microsoft has performed investigations into areas such as readability, and the company has documented guidelines illustrating the standardized use of fonts, weights, spacing, and positioning for text.

Note

You can find lots of information about the design features of Windows Store apps online on the Microsoft website. Specifically, the webpage “UX Patterns,” available at http://msdn.microsoft.com/library/windows/apps/hh770552.aspx, provides guidance on planning the features that a Windows Store app should implement and how to design the app to provide the optimal user experience.

Many modern handheld and tablet devices make it possible for users to interact with apps by using touch, and you should design your Windows Store apps based on this style of user experience (UX). Windows 8.1 includes an extensive collection of touch-based controls that also work with the mouse and keyboard if the user does not have a touch-sensitive device. You don’t need to separate the touch and mouse features in your apps; simply design for touch and users can still operate by using the mouse and keyboard if they prefer or if they are running on a device that does not support this style of interaction.

Subtle, fluid, and discrete animations are also an important aspect of the entire UX. The way in which the graphical user interface (GUI) responds to gestures to provide feedback to the user can greatly enhance the professional feel of your apps. The Windows Store app templates included with Visual Studio 2013 include an animation library that you can use in your apps to standardize this feedback and blend in seamlessly with the operating system and software that Microsoft provides.

Note

The term gesture refers to the manual touch-oriented operations that a user can perform. For example, a user can tap an item with a finger, and this gesture typically responds in the same way that you would expect a mouse-click to behave. However, gestures can be far more expressive than the simple operations that can be captured by using a mouse. For example, the “rotate” gesture involves the user placing two fingers on the screen and “drawing” the arc of a circle with them; in a typical Windows 8.1 app, this gesture should cause the UI to rotate the selected object in the direction indicated by the movement of the fingers. Other gestures include “pinch” to zoom in on an item to display more detail, “press and hold” to reveal more information about an item (similar to performing a right-mouse click), and “slide” to select and drag an item across the screen.

The Windows 8.1 user interface employs a number of its own specific gestures for interacting with the operating system. For example, you can “swipe” the currently running app to the bottom of the screen to terminate it, or you can swipe from the left or right edge of the display to view the Windows system icons.

A diagram illustrating the different user gestures implemented by Windows 8.1

Windows 8.1 is intended to run on a wide range of devices, from desktop computers and laptops through to tablet computers and small handheld devices and smartphones. An important concept in building Windows Store apps is that you need to construct your software so that it adapts to the environment in which it is running, scaling automatically to the screen size and orientation of the device. This approach opens up your software to an increasingly broad market. Additionally, many modern devices can also detect their orientation and the speed at which the user changes this orientation through the use of in-built sensors and accelerometers. Windows Store apps can adapt their layout as the user tilts or rotates a device, making it possible for the user to work in a mode that is most comfortable for that individual. You should also understand that mobility is a key requirement for many modern apps, and with Windows Store apps, users can roam; their data can migrate through the cloud to whatever device they happen to be running your app on at a particular moment.

Windows Store apps can also support a number of features that facilitate interactions with other apps as well as the Windows 8.1 operating system. These features are based on a standardized mechanism known as a contract. A contract defines a Windows 8.1 interface through which an app can implement or consume an operating system–defined feature, such as the ability to share data or support search requests. Using contracts, Windows Store apps can communicate with one another without introducing any app-specific dependencies. You will learn more about Windows 8.1 contracts in Chapter 26.

The lifetime of Windows Store app is somewhat different from that of a traditional desktop app. At any given point in time, Windows 8.1 just runs the app that occupies the area of focus on the screen, and if you switch to a different app, that app becomes the focus and moves to the foreground, and the original app is suspended. Windows 8.1 might actually decide to close a suspended app if it determines that it needs to release system resources such as memory. When the app next runs, it should be able to resume from where it left off. This means that you need to be prepared to manage app state information in your code, save it to hard disk, and restore it at the appropriate juncture.

Note

You can find more information about how to manage the lifecycle of a Windows Store app on the Microsoft website. Look for the page “How to suspend an app” at http://msdn.microsoft.com/library/windows/apps/xaml/hh465115.aspx, and the page “How to resume an app” at http://msdn.microsoft.com/library/windows/apps/xaml/hh465110.aspx.

When you build a new Windows Store app, you can package it by using the tools provided with Visual Studio 2013 and upload it to the Windows Store. Other users can then connect to the store, download your app, and install it. You can charge a fee for your apps, or you can make them available at no cost. This distribution and deployment mechanism depends on your apps being trustworthy and conforming to security policies specified by Microsoft. When you upload an app to the Windows Store, it undergoes a number of checks to verify that it does not contain malicious code and that it conforms to the security requirements of a Windows Store app. These security constraints dictate how your app accesses resources on the computer on which it is installed. For example, by default a Windows Store app cannot write directly to the file system or listen for incoming requests from the network (two of the behaviors commonly exhibited by viruses and other malware). However, if your app needs to perform operations such as these, you can specify them as capabilities in the app manifest by using the manifest editor in Visual Studio 2013. To open the manifest editor, in Solution Explorer, double-click the Package.appxmanifest file.

A screenshot of the manifest editor showing the resource capabilities of a Windows Store app.

Note

You can find more information about the capabilities that Windows Store apps support on the “App capability declarations” page on the Microsoft website at http://msdn.microsoft.com/library/windows/apps/hh464936.aspx.

This information is recorded in the metadata of your app and signals Microsoft to perform additional tests to verify the way in which your app uses these features. There are also limitations on how these operations work, which are designed to protect the computers on which your app is installed. For example, you can indicate that your app requires access to the files in the Documents folder, but you cannot read or write files located elsewhere on the host computer.

Enough theory—let’s get started building a Windows Store app.

Using the Blank App template to build a Windows Store app

The simplest way to build a Windows Store app is to use the Windows Store app templates included with Visual Studio 2013 on Windows 8.1. Visual Studio 2013 provides three primary templates for this purpose: Blank App, Grid App, and Split App. Each of these templates enables you to quickly create apps that conform to Windows 8.1 user interface guidelines based on the model recommended by Microsoft. In addition, they generate a considerable amount of code, and it helps to understand how this code is structured so that you can adapt it to your own apps and data requirements. The Windows 8.1 versions of the apps used in earlier chapters have made use of the Blank App template, and this is a good place to start.

In the following exercises, you will design and implement the user interface for a simple app for a fictitious company called Adventure Works. This company manufactures and supplies bicycles and associated paraphernalia. The app will enable a user to enter and modify the details of Adventure Works’s customers.

Create the Adventure Works Customers app
  1. Start Visual Studio 2013 if it is not already running.

  2. On the File menu, point to New, and then click Project.

  3. In the New Project dialog box, in the left pane, expand Templates, expand Visual C#, and then click Windows Store.

  4. In the middle pane, click the Blank App (XAML) icon.

  5. In the Name field, type Customers.

  6. In the Location field, type Microsoft PressVisual CSharp Step By StepChapter 25 in your Documents folder.

  7. Click OK.

    The new app is created, and the App.xaml.cs file is displayed in the Code and Text Editor window. You can ignore this file for the time being.

  8. In Solution Explorer, double-click MainPage.xaml.

    The Design View window appears and displays a blank page. You can drag controls from the Toolbox to add the various controls required by the app, as is demonstrated in Chapter 1. However, for the purposes of this exercise, it is more instructive to concentrate on the XAML markup that defines the layout for the form. If you examine this markup, it should look like this:

    <Page
        x:Class="Customers.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Customers"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        </Grid>
    </Page>

    The form starts with the XAML <Page> tag and finishes with a closing </Page> tag. Everything between these tags defines the content of the page.

    The attributes of the <Page> tag contain a number of declarations of the form xmlns:id = “…”. These are XAML namespace declarations, and they operate in a similar manner to C# using directives inasmuch as they bring items into scope. Many of the controls and other items that you can add to a page are defined in these XAML namespaces, and you can ignore most of these declarations. However, there is one rather curious-looking declaration to which you should pay attention:

    xmlns:local="using:Customers"

    This declaration brings the items in the C# Customers namespace into scope, with which you can reference classes and other types in this namespace in your XAML code by prefixing them with local. The Customers namespace is the namespace generated for the code in your app.

  9. In Solution Explorer, expand MainPage.xaml, and then double-click MainPage.xaml.cs to display it in the Code and Text Editor window.

  10. Remember from the exercises earlier in this book that this is the C# file that contains the app logic and event handlers for the form. It looks like this (the using directives at the top of the file have been omitted to save space):

    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
    namespace Customers
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
        }
    }

    This file defines the types in the Customers namespace. The page is implemented by a class called MainPage, and it inherits from the Page class. The Page class implements the default functionality of a XAML page for a Windows Store app, so all you have to do is write your own code that defines the logic specific to your app in the MainPage class.

  11. Return to t unhe MainPage.xaml file in the Design View window. If you look at the XAML markup for the page, you should notice that the <Page> tag includes the following attribute:

    x:Class="Customers.MainPage"

    This attribute connects the XAML markup that defines the layout of the page to the MainPage class that provides the logic behind the page.

That’s the basic plumbing of a simple Windows Store app. Of course, what makes a graphical app valuable is the way in which it presents information to a user. This is not always as simple as it sounds. Designing an attractive and easy-to-use graphical interface requires specialist skills that not all developers have (I know, because I lack them myself). However, many graphic artists who do have these skills are not programmers, so although they might be able to design a wonderful user interface, they might not be able to implement the logic required to make it useful. Fortunately, Visual Studio 2013 makes it possible you to separate out the user interface design from the business logic so that a graphic artist and a developer can cooperate to build a really cool-looking app that also works well. All a developer has to do is to concentrate on the basic layout of the app and then let a graphic artist provide the styling.

Implementing a scalable user interface

The key to laying out the user interface for a Windows Store app is to understand how to make it scale and adapt to the different form factors available for the devices on which users might be running the app. In the following exercises, you will investigate how to achieve this scaling.

Lay out the page for the Customers app
  1. In Visual Studio, review the XAML markup for the MainPage page.

    The page contains a single Grid control:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    </Grid>

    Note

    Don’t worry about the way in which the Background property is specified for the Grid control. This is an example of using a style, and you will learn about using styles later in this chapter.

    Understanding how the Grid control works is fundamental to being able to build scalable and flexible user interfaces. The Page element can only contain a single item, and if you want, you can replace the Grid control with a Button, as shown in the example that follows:

    Note

    Don’t type the following code. It is shown for illustrative purposes only.

    <Page
        ...
        <Button Content="Click Me"/>
    </Page>

    However, the resulting app is probably not very useful—a form that contains a button and that displays nothing else is unlikely to win an award for the world’s greatest app. If you attempt to add a second control, such as a TextBox, to the page, your code will not compile and the errors shown in the following image will occur:

    A screenshot of the XAML pane and error window showing the XAML markup for an app. The page contains a Button control and a TextBox control, and the error window displays three error messages caused by attempting to add two controls to a page.

    The purpose of the Grid control is to facilitate adding multiple items to a page. The Grid control is an example of a container control; it can contain a number of other controls, and you can specify the position of these other controls within the grid. Other container controls are also available. For example, the StackPanel control automatically places the controls it contains in a vertical arrangement, with each control positioned directly below its immediate predecessor.

    In this app, you will use a Grid to hold the controls necessary for a user to be able to enter and view data for a customer.

  2. Add a TextBlock control to the page, either by dragging it from the Toolbox or by typing the text <TextBlock /> directly into the XAML pane on the blank line after the opening <Grid> tag, like this:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock />
    </Grid>

    Tip

    You can type the code for a control directly into the XAML window for a page; you do not have to drag controls from the Toolbox.

  3. This TextBlock provides the title for the page. Set the properties of the TextBlock control by using the values in the following table:

    Property

    Value

    HorizontalAlignment

    Left

    Margin

    400,90,0,0

    TextWrapping

    Wrap

    Text

    Adventure Works Customers

    VerticalAlignment

    Top

    FontSize

    50

    You can set these properties either by using the Properties window or by typing the equivalent XAML markup into the XAML window, as shown here in bold:

    <TextBlock HorizontalAlignment="Left" Margin="400,90,0,0" TextWrapping="Wrap"
    Text="Adventure Works Customers" VerticalAlignment="Top" FontSize="50"/>

    The resulting text should appear in the Design View window, like this:

    A screenshot of the Design View window showing the TextBlock control displaying the text Adventure Works Customers.

    Notice that when you drag a control from the Toolbox to a form, connectors appear that specify the distance of two of the sides of the control from the edge of the container control in which it is placed. In the preceding example, for the TextBlock control these connectors are labeled with the values 400 (from the left edge of the grid) and 90 (from the top edge of the grid). At run time, if the Grid control is resized, the TextBlock will move to retain these distances, and in this case it might cause the distance of the TextBlock in pixels from the right and bottom edges of the Grid to change. You can specify the edge or edges to which a control is anchored by setting the HorizontalAlignment and VerticalAlignment properties, and the Margin property specifies the distance from the anchored edges. Again, in this example, the HorizontalAlignment property of the TextBlock is set to Left and the VerticalAlignment property is set to Top, which is why the control is anchored to the left and top edges of the grid. The Margin property contains four values that specify the distance of the left, top, right, and bottom sides (in that order) of the control from the corresponding edge of the container. If one side of a control is not anchored to an edge of the container, you can set the corresponding value in the Margin property to 0.

  4. Add four more TextBlock controls to the page. These TextBlock controls are labels that help the user to identify the data that is displayed on the page. Use the values in the following table to set the properties of these controls:

    Control

    Property

    Value

    First Label

    HorizontalAlignment

    Left

    Margin

    330,190,0,0

    TextWrapping

    Wrap

    Text

    ID

    VerticalAlignment

    Top

    FontSize

    20

    Second Label

    HorizontalAlignment

    Left

    Margin

    460,190,0,0

    TextWrapping

    Wrap

    Text

    Title

    VerticalAlignment

    Top

    FontSize

    20

    Third Label

    HorizontalAlignment

    Left

    Margin

    620,190,0,0

    TextWrapping

    Wrap

    Text

    First Name

    VerticalAlignment

    Top

    FontSize

    20

    Fourth Label

    HorizontalAlignment

    Left

    Margin

    975,190,0,0

    TextWrapping

    Wrap

    Text

    Last Name

    VerticalAlignment

    Top

     

    FontSize

    20

    As before, you can either drag the controls from the Toolbox and use the Properties window to set their properties or you can type the following XAML markup into the XAML pane, after the existing TextBlock control and before the closing </Grid> tag:

    <TextBlock HorizontalAlignment="Left" Margin="330,190,0,0" TextWrapping="Wrap"
    Text="ID" VerticalAlignment="Top" FontSize="20"/>
    <TextBlock HorizontalAlignment="Left" Margin="460,190,0,0" TextWrapping="Wrap"
    Text="Title" VerticalAlignment="Top" FontSize="20"/>
    <TextBlock HorizontalAlignment="Left" Margin="620,190,0,0" TextWrapping="Wrap"
    Text="First Name" VerticalAlignment="Top" FontSize="20"/>
    <TextBlock HorizontalAlignment="Left" Margin="975,190,0,0" TextWrapping="Wrap"
    Text="Last Name" VerticalAlignment="Top" FontSize="20"/>
  5. Add three TextBox controls below the TextBlock controls that display the text ID, First Name, and Last Name. Use the following table to set the values of these controls. Notice that the Text property should be set to the empty string, “”. Also notice that the id TextBox control is marked as read-only. This is because customer IDs will be generated automatically in the code that you add later:

    Control

    Property

    Value

    First TextBox

    x:Name

    id

     

    HorizontalAlignment

    Left

     

    Margin

    300,240,0,0

     

    TextWrapping

    Wrap

     

    Text

     
     

    VerticalAlignment

    Top

     

    FontSize

    20

     

    IsReadOnly

    True

    Second TextBox

    x:Name

    firstName

    HorizontalAlignment

    Left

    Margin

    550,240,0,0

    TextWrapping

    Wrap

    Text

     

    VerticalAlignment

    Top

    FontSize

    20

    Third TextBox

    x:Name

    lastName

    HorizontalAlignment

    Left

    Margin

    875,240,0,0

    TextWrapping

    Wrap

     

    Text

     
     

    VerticalAlignment

    Top

     

    FontSize

    20

     

    The following code shows the equivalent XAML markup for these controls:

    <TextBox x:Name="id" HorizontalAlignment="Left" Margin="300,240,0,0" TextWrapping="Wrap"
    Text="" VerticalAlignment="Top" FontSize="20" IsReadOnly="True"/>
    <TextBox x:Name="firstName" HorizontalAlignment="Left" Margin="550,240,0,0"
    TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300" FontSize="20"/>
    <TextBox x:Name="lastName" HorizontalAlignment="Left" Margin="875,240,0,0"
    TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="300" FontSize="20"/>

    The Name property is not required for a control, but it is useful if you want to refer to the control in the C# code for the app. Notice that the Name property is prefixed with x:. This is a reference to the XML namespace http://schemas.microsoft.com/winfx/2006/xaml specified in the Page attributes at the top of the XAML markup. This namespace defines the Name property for all controls.

    Note

    It is not necessary to understand why the Name property is defined in this way, but for more information, you can read the article “x:Name Directive” at http://msdn.microsoft.com/library/ms752290.aspx.

    The Width property specifies the width of the control, and the TextWrapping property indicates what happens if the user attempts to enter information into the control that exceeds this width. In this case, all the TextBox controls will wrap the text onto another line of the same width (the control will expand vertically). The alternative value, NoWrap, causes the text to scroll horizontally as the user enters it.

  6. Add a ComboBox control to the form and place it below the Title TextBlock control, between the id and firstName TextBox controls. Set the properties of this control as follows:

    Property

    Value

    x:Name

    title

    HorizontalAlignment

    Left

    Margin

    420,240,0,0

    VerticalAlignment

    Top

    Width

    100

    FontSize

    20

    The equivalent XAML markup for this control is as follows:

    <ComboBox x:Name="title" HorizontalAlignment="Left" Margin="420,240,0,0"
    VerticalAlignment="Top" Width="100" FontSize="20"/>

    You use a ComboBox control to display a list of values from which the user can select.

  7. In the Design View window, click the title ComboBox, and in the Properties window expand the Common property category if it is not already expanded. Then, click the ellipsis button that appears alongside the Items property.

    The Object Collection Editor window opens.

  8. In the list toward the lower left of the window, select ComboBoxItem, and then click Add. In the right pane displaying the properties for the item, expand the Common section if it is not already expanded, and then type Mr in the Content property.

    A screenshot of the Object Collection Editor. A ComboBox item has been added, with the text Mr.
  9. Click OK.

    The Object Collection Editor closes. If you examine the XAML markup for the title ComboBox, it should now look like this:

    <ComboBox x:Name="title" HorizontalAlignment="Left" Margin="420,240,0,0"
    VerticalAlignment="Top" Width="100" FontSize="20"/>
        <ComboBoxItem Content="Mr"/>
    </ComboBox>

    There are two things to notice here. The first is that the ComboBox markup has been split into an opening <ComboBox> tag and a closing </ComboBox> tag. The second is that, between these tags, Visual Studio has added a ComboBoxItem element with the Content property set to Mr. This item will be displayed in a drop-down list when the app runs.

  10. Add the values Mrs, Ms, and Miss to the title ComboBox. You can either use the Object Collection Editor or type the XAML markup by hand. The resulting markup should look like this:

    <ComboBox x:Name="title" HorizontalAlignment="Left" Margin="420,240,0,0"
    VerticalAlignment="Top" Width="75" FontSize="20"/>
        <ComboBoxItem Content="Mr"/>
        <ComboBoxItem Content="Mrs"/>
        <ComboBoxItem Content="Ms"/>
        <ComboBoxItem Content="Miss"/>
    </ComboBox>

    Note

    A ComboBox control can display simple elements such as a set of ComboBoxItem controls that display text, but it can also contain more complex elements such as buttons, check boxes, and radio buttons. If you are adding simple ComboBoxItem controls, it is probably easier to type the XAML markup by hand, but if you are adding more complex controls, the Object Collection Editor can prove very useful. However, you should avoid trying to be too clever in a combo box; the best apps are those that provide the most intuitive UIs, and embedding complex controls in a combo box can be confusing to a user.

  11. Add two more TextBox controls and two more TextBlock controls to the form. With the TextBox controls, the user will be able to enter an email address and telephone number for the customer, and the TextBlock controls provide the labels for the text boxes. Use the values in the following table to set the properties of the controls.

    Control

    Property

    Value

    First TextBlock

    HorizontalAlignment

    Left

    Margin

    300,390,0,0

    TextWrapping

    Wrap

    Text

    Email

    VerticalAlignment

    Top

    FontSize

    20

    First TextBox

    x:Name

    email

    HorizontalAlignment

    Left

    Margin

    450,390,0,0

    TextWrapping

    Wrap

    Text

    Leave Empty

    VerticalAlignment

    Top

    Width

    400

    FontSize

    20

    Second TextBlock

    HorizontalAlignment

    Left

    Margin

    300,540,0,0

    TextWrapping

    Wrap

    Text

    Phone

    VerticalAlignment

    Top

    FontSize

    20

    Second TextBox

    x:Name

    phone

    HorizontalAlignment

    Left

    Margin

    450,540,0,0

    TextWrapping

    Wrap

    Text

    Leave Empty

    VerticalAlignment

    Top

    Width

    200

     

    FontSize

    20

    The XAML markup for these controls should look like this:

    <TextBlock HorizontalAlignment="Left" Margin="300,390,0,0" TextWrapping="Wrap"
    Text="Email" VerticalAlignment="Top" FontSize="20"/>
    <TextBox x:Name="email" HorizontalAlignment="Left" Margin="450,390,0,0"
    TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="400" FontSize="20"/>
    <TextBlock HorizontalAlignment="Left" Margin="300,540,0,0" TextWrapping="Wrap"
    Text="Phone" VerticalAlignment="Top" FontSize="20"/>
    <TextBox x:Name="phone" HorizontalAlignment="Left" Margin="450,540,0,0"
    TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="200" FontSize="20"/>

    The completed form in the Design View window should look like this:

    A screenshot of the Design View window showing the completed Customers form.
  12. On the Debug menu, click Start Debugging to build and run the app.

    The app starts and displays the form. You can enter data into the form and select a title from the combo box, but you cannot do much else yet.

  13. While the app is running, click in the upper-left corner of the screen and drag the image of Visual Studio running on the desktop.

    The Customers app adjusts itself and occupies half of the screen. Depending on the resolution of your screen, the title will wrap around and the Last Name field will fall off the right edge, as illustrated here:

    A screenshot of the Customers app occupying half of the screen. The right side of the app has been cut off.
  14. Resize the window displaying the Customer app to its minimum width. This time, much of the form disappears (it is displayed in an area that is only 500 pixels wide). Some of the TextBlock content wraps, but the form is clearly not usable in this view.

    You can also resize the view to make it bigger, occupying approximately two-thirds of the screen. Again, depending on the resolution available, some of the text might wrap and some of the controls might not be visible on the screen.

    Note

    The default minimum width of an app (500 pixels) is designed to reflect the size of a typical tablet device when it is held in the portrait orientation. You should remember that not all users will be running your app on a desktop computer, and so you must ensure that it presents a functional user interface at this width. You can also configure an app to support a minimum width of 320 pixels. This is the width of many Windows Phone devices. To change the default minimum width, edit the Minimum Width setting in the Application UI page of the Package.appxmanifest file in the manifest editor in Visual Studio.

  15. Return to Visual Studio, and on the Debug menu, click Stop Debugging.

That was a salutary lesson in being careful about how you lay out an app. Although the app looked fine when it ran full-screen, as soon as you resized the window to a narrower view it became less useful (or even completely useless). Additionally, the app assumes that the user will be viewing the screen on a device in the landscape orientation. If the user is running the app on a tablet that supports different orientations, and the user rotates the device to switch to portrait mode, it will look like this:

A screenshot of the Customers app running on a device rotated to the portrait orientation. The right side of the app has been truncated, and the title text has wrapped around, overwriting the upper controls on the form.

The issue is that the layout technique shown so far does not scale and adapt to different form factors and orientations. Fortunately, you can use the properties of the Grid control and another feature called the Visual State Manager to solve these problems.

Implementing a tabular layout by using a Grid control

You can use the Grid control to implement a tabular layout. A Grid contains rows and columns, and you can specify in which rows and columns other controls should be placed. The beauty of the Grid control is that you can specify the sizes of the rows and columns that it contains as relative values; as the grid shrinks or grows to adapt itself to the different form factors and orientations to which users might switch, the rows and columns can shrink and grow in proportion to the grid. The intersection of a row and a column in a grid defines a cell, and if you position controls in cells, they will move as the rows and columns shrink and grow. Therefore, the key to implementing a scalable UI is to break it down into a collection of cells and place related elements in the same cell. A cell can contain another grid, giving you the ability to fine-tune the exact positioning of each element.

If you consider the Customers app, you can see that the UI breaks down into two main areas: a heading containing the title and the body containing the customers’ details. Allowing for some spacing between these areas, and a margin at the bottom of the form, you can assign relative sizes to each of these areas, as shown in the following diagram:

A diagram of the Customers user interface showing the relative sizes of the heading, body, spacing, and bottom margin.

The diagram shows only rough approximations, but the row for the heading is twice as high as the row for the spacer below it. The row for the body is ten times as high as the spacer, and the bottom margin is twice the height of the spacer.

To hold the elements in each area, you can define a grid with four rows and place the appropriate items in each row. However, the body of the form can be described by another, more complex grid, as shown in the following diagram:

A diagram of the body of the Customers user interface, showing the relative sizes and spacing of each of the elements.

Again, the heights of each of the rows are specified in relative terms, as are the widths of the columns. Also, you can clearly see that the TextBox elements for the Email and Phone information do not quite fit into this grid pattern. If you were being pedantic, you might choose to define further grids inside the body of the form to make these items fit. However, you should keep in mind the purpose of this grid, which is to define the relative positioning and spacing of elements. Therefore, it is acceptable for an element to extend beyond the boundaries of a cell in the grid arrangement.

In the next exercise, you will modify the layout of the Customers app to use this grid format to position the controls.

Modify the layout to scale to different form factors and orientations
  1. In the XAML pane for the Customers app, add another Grid inside the existing Grid element. Give this new Grid a margin of 40 pixels from the left edge of the parent Grid and 54 pixels from the top, as shown in bold in the following code:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid Margin="40,54,0,0">
        </Grid>
        <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap"
    Text="Adventure Works Customers" ... />
        ...
    </Grid>

    You could define the rows and columns as part of the existing Grid, but to maintain a consistent look and feel with other Windows Store apps, you should leave some blank space to the left and at the top of a page. These margins make it possible for Windows 8.1 to display its various icons and toolbars, such as the icons showing the apps that are currently running and the Start menu, without overwriting data on the screen. The following image shows an example:

    A screenshot of the Customers app running, with the left margin showing icons for running apps and the Start screen.
  2. Add the following <Grid.RowDefinitions> section shown in bold to the new Grid element.

    <Grid Margin="40,54,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="10*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>
    </Grid>

    The <Grid.RowDefinitions> section defines the rows for the grid. In this example, you have defined four rows. You can specify the size of a row as an absolute value specified in pixels, or you can use the * operator to indicate that the sizes are relative and that Windows should calculate the row sizes itself when the app runs, depending on the form factor and resolution of the screen. The values used in this example correspond to the relative row sizes for the header, body, spacer, and bottom margin of the Customers form shown in the earlier diagram.

  3. Move the TextBlock control that contains the text “Adventure Works Customers” into the Grid, after the closing </Grid.RowDefinitions> tag.

  4. Add a Grid.Row attribute to the TextBlock control and set the value to 0.

    This indicates that the TextBlock should be positioned within the first row of the Grid (Grid controls number rows and columns starting at zero).

    Note

    The Grid.Row attribute is an example of an attached property. An attached property is a property that a control receives from the container control in which it is placed. Outside of a grid, a TextBlock does not have a Row property (it would be meaningless), but when positioned within a grid, the Row property is attached to the TextBlock, and the TextBlock control can assign it a value. The Grid control then uses this value to determine where to display the TextBlock control.

    Attached properties are easy to spot because they have the form ContainerType.PropertyName.

  5. Remove the Margin property, and set the HorizontalAlignment and VerticalAlignment properties to Center.

    This will cause the TextBlock to appear centered in the row.

    The XAML markup for the Grid and TextBlock controls should look like this (the changes to the TextBlock are highlighted in bold):

    <Grid Margin="40,54,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="10*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Adventure Works Customers" VerticalAlignment="Center" FontSize="50"/>
        ...
    </Grid>
  6. After the TextBlock control, add another nested Grid control. This Grid will be used to lay out the controls in the body of the form and should appear in the third row of the outer Grid (the row of size 10*), so set the Grid.Row property to 2, as shown in bold in the following code:

    <Grid Margin="40,54,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="10*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" HorizontalAlignment="Center" .../>
        <Grid Grid.Row="2">
        </Grid>
        ...
    </Grid>
  7. Add the following <Grid.RowDefinition> and <Grid.ColumnDefinition> sections to the new Grid control:

    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="4*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
    </Grid>

    These row and column definitions specify the height and width of each of the rows and columns shown in the earlier diagram that depicted the structure of the body of the form. There is a small space of 20 pixels between each of the columns that will hold controls.

  8. Move the TextBlock controls that display the ID, Title, Last Name, and First Name labels inside the nested Grid control, immediately after the closing <Grid.ColumnDefinitions> tag.

  9. Set the Grid.Row property for each TextBlock control to 0 (these labels will appear in the first row of the grid). Set the Grid.Column property for the ID label to 1, the Grid.Column property for the Title label to 3, the Grid.Column property for the First Name label to 5, and the Grid.Column property for the Last Name label to 7.

  10. Remove the Margin property from each of the TextBlock controls, and set the HorizontalAlignment and VerticalAlignment properties to Center.

  11. The XAML markup for these controls should look like this (the changes are highlighted in bold):

    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            ...
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="ID" VerticalAlignment="Center" FontSize="20"/>
        <TextBlock Grid.Row="0" Grid.Column="3" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Title" VerticalAlignment="Center" FontSize="20"/>
        <TextBlock Grid.Row="0" Grid.Column="5" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="First Name" VerticalAlignment="Center" FontSize="20"/>
        <TextBlock Grid.Row="0" Grid.Column="7" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Last Name" VerticalAlignment="Center" FontSize="20"/>
    </Grid>
  12. Move the id, firstName and lastName TextBox controls and the title ComboBox control inside the nested Grid control, immediately after the Last Name TextBlock control.

    Place these controls in row 1 of the Grid control. Put the id control in column 1, the title control in column 3, the firstName control in column 5, and the lastName control in column 7.

    Remove the Margin of each of these controls, and set the VerticalAlignment property to Center. Remove the Width property, and set the HorizontalAlignment property to Stretch.

    This causes the control to occupy the entire cell when it is displayed, and the control shrinks or grows as the size of the cell changes.

    The completed XAML markup for these controls should look like this, with changes highlighted in bold:

    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            ...
        </Grid.ColumnDefinitions>
        ...
        <TextBlock Grid.Row="0" Grid.Column="7" ... Text="Last Name" .../>
        <TextBox Grid.Row="1" Grid.Column="1" x:Name="id" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20" IsReadOnly="True"/>
        <TextBox Grid.Row="1" Grid.Column="5" x:Name="firstName"
    HorizontalAlignment="Stretch" TextWrapping="Wrap" Text=""
    VerticalAlignment="Center"
    FontSize="20"/>
        <TextBox Grid.Row="1" Grid.Column="7" x:Name="lastName" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20"/>
        <ComboBox Grid.Row="1" Grid.Column="3" x:Name="title" HorizontalAlignment="Stretch"
    VerticalAlignment="Center" FontSize="20">
            <ComboBoxItem Content="Mr"/>
            <ComboBoxItem Content="Mrs"/>
            <ComboBoxItem Content="Ms"/>
            <ComboBoxItem Content="Miss"/>
        </ComboBox>
    </Grid>
  13. Move the TextBlock control for the Email label and the email TextBox control to the nested Grid control, immediately after the closing tag of the title ComboBox control.

    Place these controls in row 3 of the Grid control. Put the Email label in column 1 and the email TextBox control in column 3. Additionally, set the Grid.ColumnSpan property for the email TextBox control to 3; this way, the column can spread to the value specified by its Width property across three columns, as shown in the earlier diagram.

    Set the HorizontalAlignment property of the Email label control to Center, but leave the HorizontalAlignment property of the email TextBox set to Left; this control should remain left-justified against the first column that it spans rather than being centered across them all.

    Set the VerticalAlignment property of the Email label and the email TextBox control to Center.

    Remove the Margin property for both of these controls.

    The following XAML markup shows the completed definitions of these controls:

    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            ...
        </Grid.ColumnDefinitions>
        ...
        <ComboBox Grid.Row="1" Grid.Column="3" x:Name="title" HorizontalAlignment="Stretch"
    VerticalAlignment="Center" FontSize="20">
            ...
        </ComboBox>
        <TextBlock Grid.Row="3" Grid.Column="1" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Email" VerticalAlignment="Center" FontSize="20"/>
        <TextBox Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="3" x:Name="email"
    HorizontalAlignment="Left" TextWrapping="Wrap" Text="" VerticalAlignment="Center"
    Width="400" FontSize="20"/>
    </Grid>
  14. Move the TextBlock control for the Phone label and phone TextBox control to the nested Grid control, immediately after the email TextBox control.

    Place these controls in row 5 of the Grid control. Put the Phone label in column 1 and the phone TextBox control in column 3. Set the Grid.ColumnSpan property for the phone TextBox control to 3.

    Set the HorizontalAlignment property of the Phone label control to Center and leave the HorizontalAlignment property of the phone TextBox set to Left.

    Set the VerticalAlignment property of both controls to Center and remove the Margin property.

    The following XAML markup shows the completed definitions of these controls:

    <Grid Grid.Row="2">
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            ...
        </Grid.ColumnDefinitions>
        ...
        <TextBox ..." x:Name="email" .../>
        <TextBlock Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Phone" VerticalAlignment="Center" FontSize="20"/>
        <TextBox Grid.Row="5" Grid.Column="3" Grid.ColumnSpan="3" x:Name="phone"
    HorizontalAlignment="Left" TextWrapping="Wrap" Text="" VerticalAlignment="Center"
    Width="200" FontSize="20"/>
    </Grid>
  15. On the Visual Studio toolbar, in the Debug Target list, select Simulator.

    You will run the app in the Simulator so that you can see how the layout adapts in different resolutions and form factors.

  16. On the Debug menu, click Start Debugging.

    The Simulator starts and the Customers app runs. Click Change Resolution and configure the Simulator to display the app using a screen resolution of 1366 × 768. Also, ensure that the Simulator is displayed in landscape orientation (click Rotate Clockwise if it is running in portrait orientation). Verify that the controls are evenly spaced in this orientation.

  17. Click the Rotate Clockwise button to rotate the Simulator to portrait orientation.

    The Customers app should adjust the layout of the user interface, and the controls should still be evenly spaced and usable:

    A screenshot of the Simulator running the Customers app in portrait orientation.
  18. Click Rotate Counterclockwise to put the Simulator back to landscape orientation, and then click Change Resolution and switch the resolution of the Simulator to 2560 × 1400.

    Notice that the controls remain evenly spaced on the form, although the labels might be quite difficult to read unless you actually have a 27-inch screen.

  19. Click Change Resolution again and switch the resolution to 1024 × 768.

    Again, notice how the spacing and size of the controls is adjusted to maintain the even balance of the user interface:

    A screenshot of the Simulator with the resolution set to 1024 by 768.
  20. Click Change Resolution again and switch the resolution back to 1366 × 768.

  21. Click the top edge of the form and drag it so that the form is displayed in the left half of the screen, and then drag the bar in the middle of the screen to reduce the size of the view to its minimum width (500 pixels).

    All of the controls remain visible, but the text for the Phone label wraps, making it difficult to read, and the controls are not particularly easy to use:

    A screenshot of the Customers app running in the minimum width view in the Simulator. All of the controls are visible but not very usable. Some of the text has wrapped and is difficult to read.
  22. In the Simulator, display the charms (press Windows+C), click Settings, click Power, and then click Disconnect.

    The Simulator closes and you return to Visual Studio.

  23. On the Visual Studio toolbar, in the Debug Target list, select Local Machine.

Adapting the layout by using the Visual State Manager

The user interface for the Customers app scales for different resolutions and form factors, but it still does not work well if you reduce the width of the view. Additionally, it probably would not look too good on a smartphone, which has an even narrower width. If you think about it, in these cases the problem is not so much a matter of scaling the controls as actually laying them out in a different way. For example, it would make better sense if the Customers form looked like this in a narrow view:

A diagram showing the proposed layout of the Customers form in a narrow view. The TextBox controls are arranged in columnar format.

You can achieve this effect by using the Visual State Manager. All Windows Store apps implement a Visual State Manager that tracks the visual state of an app. It can detect when the app switches between different views. You can catch these visual state transitions and use them to animate the user interface—to move controls around or to display and hide controls, for example. This is what you will do in the next exercises. The first step is to define a layout for the customers’ data that should appear in a narrow view.

Define a layout for the narrow view
  1. In the XAML pane for the Customers app, add the x:Name and Visibility properties shown in bold in the following code that defines the tabular layout of the various controls to the Grid control:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid x:Name="customersTabularView" Margin="40,54,0,0" Visibility="Collapsed">
            ...
        </Grid>
    </Grid>

    You will reference this Grid control in other XAML markup later in this set of exercises, hence the requirement to give it a name. The Visibility property specifies whether the control is displayed (Visible), or hidden (Collapsed). The default value is Visible, but for the time being you will hide this Grid while you define another for displaying the data in a columnar format.

  2. After the closing </Grid> tag for the customersTabularView Grid control, add another Grid control. Set the x:Name property to customersColumnarView, set the Margin property to 20,10,20,10, and set the Visibility property to Visible.

    Tip

    You can expand and contract elements in the XAML pane of the Design View window and make the structure easier to read by clicking the + and – signs that appear down the left edge of the XAML markup.

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid x:Name="customersTabularView" Margin="40,54,0,0" Visibility="Collapsed">
            ...
        </Grid>
        <Grid x:Name="customersColumnarView" Margin="10,20,10,20" Visibility="Visible">
        </Grid>
    </Grid>
  3. In the customersColumnarView Grid control add the following row definitions:

    <Grid x:Name="customersColumnarView" Margin="10,20,10,20" Visibility="Visible">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="10*"/>
        </Grid.RowDefinitions>
    </Grid>

    You will use the top row to display the title and the second, much larger row to display the controls into which the user enters data.

  4. After the row definitions, add the following TextBlock control. This control displays a truncated title, Customers, in the first row of the Grid control. Set the FontSize to 30.

    <Grid x:Name="customersColumnarView" Margin="10,20,10,20" Visibility="Visible">
        <Grid.RowDefinitions>
            ...
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Customers" VerticalAlignment="Center" FontSize="30"/>
    </Grid>
  5. Add another Grid control to row 1 of the customersColumnarView Grid control, immediately after the TextBlock control that contains the Customers title. This Grid control will display the labels and data-entry controls in two columns, so add the row and columns definitions shown in the following code example to this Grid.

    <TextBlock Grid.Row="0" ... />
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
    </Grid>

    Notice that if all the rows or columns in a set have the same height or width, you do not need to specify their size.

  6. Copy the XAML markup for the ID, Title, First Name, and Last Name TextBlock controls from the customersTabularView Grid control to the new Grid control, immediately after the row definitions that you just added. Put the ID control in row 0, the Title control in row 1, the First Name control in row 2, and the Last Name control in row 3. Place all controls in column 0.

    <Grid.RowDefinitions>
        ...
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="ID" VerticalAlignment="Center" FontSize="20"/>
    <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Title" VerticalAlignment="Center" FontSize="20"/>
    <TextBlock Grid.Row="2" Grid.Column="0" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="First Name" VerticalAlignment="Center" FontSize="20"/>
    <TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Last Name" VerticalAlignment="Center" FontSize="20"/>
  7. Copy the XAML markup for the id, title, firstName, and lastName TextBox and ComboBox controls from the customersTabularView Grid control to the new Grid control, immediately after the TextBox controls. Put the id control in row 0, the title control in row 1, the firstName control in row 2, and the lastName control in row 3. Place all four controls in column 1. Also, change the names of all the controls by prefixing them with the letter c (for column). This final change is necessary to avoid clashing with the names of the existing controls in the customersTabularView Grid control.

    <TextBlock Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center"
    TextWrapping="Wrap" Text="Last Name" VerticalAlignment="Center" FontSize="20"/>
    <TextBox Grid.Row="0" Grid.Column="1" x:Name="cId" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20" IsReadOnly="True"/>
    <TextBox Grid.Row="2" Grid.Column="1" x:Name="cFirstName" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20"/>
    TextBox Grid.Row="3" Grid.Column="1" x:Name="cLastName" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20"/>
    <ComboBox Grid.Row="1" Grid.Column="1" x:Name="cTitle" HorizontalAlignment="Stretch"
    VerticalAlignment="Center" FontSize="20">
            <ComboBoxItem Content="Mr"/>
            <ComboBoxItem Content="Mrs"/>
            <ComboBoxItem Content="Ms"/>
            <ComboBoxItem Content="Miss"/>
    </ComboBox>
  8. Copy the TextBlock and TextBox controls for the email address and telephone number from the customersTabularView Grid control to the new Grid control, after the cTitle ComboBox control. Place the TextBlock controls in column 0 and the TextBox controls in column 1, in rows 4 and 5. Change the name of the email TextBox control to cEmail and the name of the phone TextBox control to cPhone. Remove the Width properties of the cEmail and cPhone controls, and set their HorizontalAlignment properties to Stretch.

    <ComboBox ...>
        ...
    </ComboBox>
    <TextBlock Grid.Row="4" Grid.Column="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Email" VerticalAlignment="Center" FontSize="20"/>
    <TextBox Grid.Row="4" Grid.Column="1" x:Name="cEmail" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20"/>
    <TextBlock Grid.Row="5" Grid.Column="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Phone" VerticalAlignment="Center" FontSize="20"/>
    <TextBox Grid.Row="5" Grid.Column="1" x:Name="cPhone" HorizontalAlignment="Stretch"
    TextWrapping="Wrap" Text="" VerticalAlignment="Center" FontSize="20"/>

    The Design View window should display the columnar layout like this:

    A screenshot of the Design View window showing the columnar layout for the Customers form.
  9. Return to the XAML markup for the customersTabularView Grid control and set the Visibility property to Visible.

    <Grid x:Name="customersTabularView" Margin="40,54,0,0" Visibility="Visible">
  10. In the XAML markup for the customersColumnarView Grid control, set the Visibility property to Collapsed.

    <Grid x:Name="customersColumnarView" Margin="20,10,20,10" Visibility="Collapsed">

    The Design View window should display the original tabular layout of the Customers form. This is the default view that will be used by the app.

You have now defined the layout that will appear in the narrow view. You might be concerned that in essence all you have done is duplicated many of the controls and laid them out in a different manner. If you run the form and switch between views, how will data in one view transfer to the other? For example, if you enter the details for a customer when the app is running full screen, and then you switch to the narrow view, the newly displayed controls will not contain the same data that you just entered. Windows Store apps address this problem by using data binding. This is a technique by which you can associate the same piece of data to multiple controls, and as the data changes, all controls display the updated information. You will see how this works in Chapter 26. For the time being, you need to consider how to use the Visual State Manager to switch between layouts when the view changes.

Every Windows Store app has a Visual State Manager. Its purpose is to respond to changes in visual state and update the layout of the user interface. To indicate a change in visual state, you can use the GoToState method of the VisualStateManager object. You can specify the changes that the Visual State Manager makes to the layout by implementing a series of visual state transitions in the XAML markup of your app. This is what you will do in the next exercise.

Use the Visual State Manager to modify the layout
  1. In the XAML pane for the Customers app, after the closing </Grid> tag for the customersColumnarView Grid control, add the following markup:

    <Grid x:Name="customersColumnarView" Margin="10,20,10,20" Visibility="Visible">
        ...
    </Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="TabularLayout"/>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    You define the visual state transitions by implementing one or more visual state groups. Each visual state group specifies the transitions that should occur when the Visual State Manager switches to the specified visual state. In this case, the default actions will occur when the Visual State Manager switches to the TabularLayout state (this state will indicate that the app is running in a wide window; you will define this state shortly). You have already experienced these default actions—the controls adjust their widths and positions relative to each other, according to the definitions of the various rows and columns in the Grid controls that contain them.

  2. Add the following visual state transition shown in bold to the visual state group:

    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="TabularLayout"/>
              <VisualState x:Name="ColumnarLayout">
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=
    "customersTabularView" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                    </ObjectAnimationUsingKeyFrames>
                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=
    "customersColumnarView" Storyboard.TargetProperty="Visibility">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    This transition will occur when the app switches to ColumnarLayout state, when the user resizes the app to display it in a narrow window (again, you will define this state in a later step in this exercise).

    A transition is described in terms of an animation storyboard. Animation in Windows Store apps is a big subject in its own right; unfortunately, there is not space to discuss how animations work in this chapter, but the important point to glean from this code is that this transition contains two animations: the first changes the Visibility property of the customersTabularView Grid control to Collapsed, and the second changes the Visibility property of the customersColumnarView Grid control to Visible.

    Note

    For more information about using animations in Windows Store apps, visit the “Quickstart: Animating your UI” page on the Microsoft website at http://msdn.microsoft.com/library/windows/apps/xaml/hh452703.aspx.

  3. In Solution Explorer, expand MainPage.xaml, and then double-click MainPage.xaml.cs to display the code for the MainPage form in the Code and Text Editor window.

  4. Add the following method to the MainPage class:

    void WindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
    {
        if (e.Size.Width <= 750)
        {
            VisualStateManager.GoToState(this, "ColumnarLayout", false);
        }
        else
        {
            VisualStateManager.GoToState(this, "TabularLayout", false);
        }
    }

    This is an event handler that will run when the app window changes size. The WindowsSizeChangedEventArgs parameter contains the Size property which indicates the new size of the window. The Width property specifies the width of the window. The code in this event handler queries the Width property, and calls the static GoToState method of the VisualStateManager class, specifying the state to which the Visual State Manager should transition the window. The GoToState method triggers a transition on the object specified by the first argument (in this case, the Customers form), using the visual state name specified by the second argument. In this case, if the width of the window is less than 750 pixels, the app switches to the ColumnarLayout state, otherwise it moves to the TabularLayout state. Note that state names are simply string values. You can ignore the Boolean third argument.

    Note

    The form moves to the columnar layout when the width drops to 750 pixels rather than the 500 pixels that is the default minimum width of a window. This is because at widths below 750 pixels, the controls and labels on the Customers form start to wrap and become difficult to use.

  5. In the MainPage constructor, add the following statement shown in bold:

    public MainPage()
    {
        this.InitializeComponent();
        Window.Current.SizeChanged += WindowSizeChanged;
    }

    This code subscribes to the SizeChanged event for the current window; the WindowSizeChanged method that you defined in the previous step runs when this event occurs.

  6. On the Debug menu, click Start Debugging.

    The app starts and displays the Customer form full screen. The data displays using the tabular layout.

    Note

    If you are using a display with a resolution of less than 1366 × 768, start the app running in the Simulator as described earlier. Configure the Simulator with a resolution of 1366 × 768.

  7. Drag the top edge of the window displaying the Customer app to show it in a narrow view.

    This time, the data is displayed in the columnar layout:

    A diagram showing the Customers form running in the Simulator in a narrow view.
  8. Resize the window displaying the Customer app to display it running full screen.

    The Customer form reverts to the tabular layout.

  9. Return to Visual Studio and stop debugging.

Applying styles to a UI

Now that you have the mechanics of the basic layout of the app resolved, the next step is to apply some styling to make the UI look more attractive. The controls in a Windows Store app have a varied range of properties that you can use to change features such as the font, color, size, and other attributes of an element. You can set these properties individually for each control, but this approach can become cumbersome and repetitive if you need to apply the same styling to a number of controls. Also, the best apps apply a consistent styling across the UI, and it is difficult to maintain this consistency if you have to repeatedly set the same properties and values as you add or change controls. The more times you have to do the same thing, the greater the chances are that you will get it wrong at least once!

With Windows Store apps, you can define reusable styles. You can implement them as app-wide resources by creating a resource dictionary, and then they are available to all controls in all pages in an app. You can also define local resources that apply to only a single page in the XAML markup for that page. In the following exercise, you will define some simple styles for the Customers app and apply these styles to the controls on the Customers form.

Define styles for the Customers form
  1. In Solution Explorer, right-click the Customers project, point to Add, and then click New Item.

  2. In the Add New Item – Customers dialog box, click Resource Dictionary. In the Name box, type AppStyles.xaml, and then click Add.

    The AppStyles.xaml file appears in the Code and Text Editor window. A resource dictionary is a XAML file that contains resources that the app can use. The AppStyles.xaml file looks like this:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Customers">
    </ResourceDictionary>

    Styles are one example of a resource, but you can also add other items. In fact, the first resource that you will add is not actually a style but an ImageBrush that will be used to paint the background of the outermost Grid control on the Customers form.

  3. In Solution Explorer, right-click the Customers project, point to Add, and then click New Folder. Change the name of the new folder to Images.

  4. Right-click the Images folder, point to Add, and then click Existing Item.

  5. In the Add Existing Item – Customers dialog box, browse to the Microsoft PressVisual CSharp Step By StepChapter 25Resources folder in your Documents folder, click wood.jpg, and then click Add.

    The wood.jpg file is added to the Images folder in the Customers project. This file contains an image of a tasteful wooden background that you will add to the Customers form.

  6. In the Code and Text Editor window displaying the AppStyles.xaml file, add the following XAML markup shown in bold:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Customers">
        <ImageBrush x:Key="WoodBrush" ImageSource="Images/wood.jpg"/>
    </ResourceDictionary>

    This markup creates an ImageBrush resource called WoodBrush that is based on the wood.jpg file. You can use this image brush to set the background of a control, and it will display the image in the wood.jpg file.

  7. Underneath the ImageBrush resource, add the following style shown in bold to the AppStyles.xaml file:

    <ResourceDictionary
        ...>
        <ImageBrush x:Key="WoodBrush" ImageSource="Images/wood.jpg"/>
        <Style x:Key="GridStyle" TargetType="Grid">
            <Setter Property="Background" Value="{StaticResource WoodBrush}"/>
        </Style>
    </ResourceDictionary>

    This markup shows how to define a style. A Style element should have a name (so it can be referenced elsewhere in the app), and it should specify the type of control to which the style can be applied. You are going to use this style with the Grid control.

    The body of a style consists of one or more Setter elements. A Setter element specifies the property to set and the value to which the property should be set. In this example, the Background property is set to the WoodBrush ImageBrush resource. The syntax is a little curious, though. In a value, you can either reference one of the appropriate system-defined values for the property (such as “Red” if you want to set the background to a solid red color) or specify a resource that you have defined. To reference a resource, you use the StaticResource keyword and then place the entire expression in curly braces.

  8. Before you can use this style, you must update the global resource dictionary for the app in the App.xaml file and add a reference to the AppStyles.xaml file. In Solution Explorer, double-click App.xaml to display it in the Code and Text Editor window. The App.xaml file looks like this:

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

    Currently the App.xaml file only defines the app object and brings a few namespaces into scope; the global resource dictionary is empty.

  9. Add the code shown here in bold to the App.xaml file:

    <Application
        x:Class="Customers.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Customers">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="AppStyles.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>

    This markup adds the resources defined in the AppStyles.xaml file to the list of resources available in the global resource dictionary. These resources are now available for use throughout the app.

  10. Switch to the MainPage.xaml file displaying the UI for the Customers form. In the XAML pane, find the outermost Grid control:

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

    In the XAML markup for this control, replace the Background property with a Style property that references the GridStyle style, as shown in bold in the following code:

    <Grid Style="{StaticResource GridStyle}">

    The background of the Grid control in the Design View window should switch and display a wooden panel, like this:

    A screenshot of the Design View window showing the Customers form. The background of the form displays a wooden panel.

    Note

    Ideally, you should ensure that any background image that you apply to a page or control maintains its aesthetics as the device form factor and orientation changes. An image that looks cool on a 30-inch monitor might appear distorted and squashed on a Windows Phone device. It might be necessary to provide alternative backgrounds for different views and orientations and use the Visual State Manager to modify the Background property of a control to switch between them as the visual state changes.

  11. Return to AppStyles.xaml in the Code and Text Editor window and add the following FontStyle style after the GridStyle style:

    <Style x:Key="GridStyle" TargetType="Grid">
        ...
    </Style>
    <Style x:Key="FontStyle" TargetType="TextBlock">
        <Setter Property="FontFamily" Value="Buxton Sketch"/>
    </Style>

    This style applies to TextBlock elements and changes the font to Buxton Sketch. This font resembles a handwriting style.

    At this stage, it would be possible to reference the FontStyle style in every TextBlock control that required this font, but this approach would not provide any advantage over simply setting the FontFamily directly in the markup for each control. The real power of styles occurs when you combine multiple properties together, as you will see in the next few steps.

  12. Add the HeaderStyle style shown here to the AppStyles.xaml file:

    <Style x:Key="FontStyle" TargetType="TextBlock">
        ...
    </Style>
    <Style x:Key="HeaderStyle" TargetType="TextBlock" BasedOn="{StaticResource FontStyle}">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="TextWrapping" Value="Wrap"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Foreground" Value="SteelBlue"/>
    </Style>

    This is a composite style that sets the HorizontalAlignment, TextWrapping, VerticalAlignment, and Foreground properties of a TextBlock. Additionally, the HeaderStyle style references the FontStyle style by using the BasedOn property. The BasedOn property provides a simple form of inheritance for styles.

    You will use this style to format the labels that appear at the top of the customersTabularGrid and customersColumnarGrid controls. However, these headings have different font sizes (the heading for the tabular layout is bigger than that of the columnar layout), so you will create two more styles that extend the HeaderStyle style.

  13. Add the following styles to the AppStyles.xaml file:

    <Style x:Key="HeaderStyle" TargetType="TextBlock" BasedOn="{StaticResource FontStyle}">
        ...
    </Style>
    <Style x:Key="TabularHeaderStyle" TargetType="TextBlock"
    BasedOn="{StaticResource HeaderStyle}">
        <Setter Property="FontSize" Value="70"/>
    </Style>
    <Style x:Key="ColumnarHeaderStyle" TargetType="TextBlock"
    BasedOn="{StaticResource HeaderStyle}">
        <Setter Property="FontSize" Value="50"/>
    </Style>

    Note that the font sizes for these styles are slightly bigger than the font sizes currently used by the headings in the Grid controls. This is because the Buxton Sketch font is smaller than the default font.

  14. Switch back to the MainPage.xaml file and find the XAML markup for the TextBlock control for the Adventure Works Customers label in the customersTabularView Grid control:

    <TextBlock Grid.Row="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Adventure Works Customers" VerticalAlignment="Center" FontSize="50"/>
  15. Change the properties of this control to reference the TabularHeaderStyle style, as shown in bold in the following code:

    <TextBlock Grid.Row="0" Style="{StaticResource TabularHeaderStyle}"
    Text="Adventure Works Customers"/>

    The heading displayed in the Design View window should change color, size, and font and look like this:

    A screenshot of the Grid heading in the Design View window, showing the changes to the color, size, and font of the heading.
  16. Find the XAML markup for the TextBlock control for the Customers label in the customersColumnarView Grid control:

    <TextBlock Grid.Row="0" HorizontalAlignment="Center" TextWrapping="Wrap"
    Text="Customers" VerticalAlignment="Center" FontSize="30"/>

    Modify the markup of this control to reference the ColumnarHeaderStyle style, as shown here in bold:

    <TextBlock Grid.Row="0" Style="{StaticResource ColumnarHeaderStyle}"
    Text="Customers"/>

    Be aware that you won’t see this change in the Design View window, because the customersColumnarView Grid control is collapsed by default. However, you will see the effects of this change when you run the app later in this exercise.

  17. Return to the AppStyles.xaml file in the Code and Text Editor window. Modify the HeaderStyle style with the additional property Setter elements shown in bold in the following example:

    <Style x:Key="HeaderStyle" TargetType="TextBlock" BasedOn="{StaticResource FontStyle}">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="TextWrapping" Value="Wrap"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Foreground" Value="SteelBlue"/>
        <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <CompositeTransform Rotation="-5"/>
            </Setter.Value>
        </Setter>
    </Style>

    These elements rotate the text displayed in the header about its midpoint by an angle of 5 degrees by using a transformation.

    Note

    This example shows a simple transformation. Using the RenderTransform property, you can perform a variety of other transformations to an item, and you can combine multiple transformations together. For example, you can translate (move) an item on the x and y-axes, skew the item (make it lean), and scale an element. For more information, see http://msdn.microsoft.com/library/system.windows.uielement.rendertransform.aspx.

    You should also notice that the value of the RenderTransform property is itself another property/value pair (the property is Rotation, and the value is –5). In cases such as this, you specify the value by using the <Setter.Value> tag.

  18. Switch to the MainPage.xaml file. In the Design View window, the title should now be displayed at a jaunty angle:

    A screenshot of the Grid heading in the Design View window. The heading is angled up to the right at 5 degrees.
  19. In the AppStyles.xaml file, add the following style:

    <Style x:Key="LabelStyle" TargetType="TextBlock" BasedOn="{StaticResource FontStyle}">
        <Setter Property="FontSize" Value="30"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="TextWrapping" Value="Wrap"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Foreground" Value="AntiqueWhite"/>
    </Style>

    You will apply this style to the TextBlock elements that provide the labels for the various TextBox and ComboBox controls that the user employs to enter customer information. The style references the same font style as the headings but sets the other properties to values more appropriate for the labels.

  20. Go back to the MainPage.xaml file. In the XAML pane, modify the markup for the TextBlock controls for each of the labels in the customersTabularView and customersColumnarView Grid controls; remove the HorizontalAlignment,TextWrapping, VerticalAlignment, and FontSize properties; and reference the LabelStyle style, as shown here in bold:

    <Grid x:Name="customersTabularView" Margin="40,54,0,0" Visibility="Visible">
        ...
        <Grid Grid.Row="2">
            ...
            <TextBlock Grid.Row="0" Grid.Column="1" Style="{StaticResource LabelStyle}"
    Text="ID"/>
            <TextBlock Grid.Row="0" Grid.Column="3" Style="{StaticResource LabelStyle}"
    Text="Title"/>
            <TextBlock Grid.Row="0" Grid.Column="5" Style="{StaticResource LabelStyle}"
    Text="First Name"/>
            <TextBlock Grid.Row="0" Grid.Column="7" Style="{StaticResource LabelStyle}"
    Text="Last Name"/>
            ...
            <TextBlock Grid.Row="3" Grid.Column="1" Style="{StaticResource LabelStyle}"
    Text="Email"/>
            ...
            <TextBlock Grid.Row="5" Grid.Column="1" Style="{StaticResource LabelStyle}"
    Text="Phone"/>
            ...
        </Grid>
    </Grid>
    <Grid x:Name="customersColumnarView" Margin="20,10,20,10" Visibility="Collapsed">
        ...
        <Grid Grid.Row="1">
            ...
            <TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="ID"/>
            <TextBlock Grid.Row="1" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="Title"/>
            <TextBlock Grid.Row="2" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="First Name"/>
            <TextBlock Grid.Row="3" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="Last Name"/>
            ...
            <TextBlock Grid.Row="4" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="Email"/>
            ...
            <TextBlock Grid.Row="5" Grid.Column="0" Style="{StaticResource LabelStyle}"
    Text="Phone"/>
            ...
        </Grid>
    </Grid>

    The labels on the form should change to the Buxton Sketch font and display in white, in a font size of 30 points:

    A screenshot of the Design View window showing the Customers form. The labels are now all displayed in the Buxton Sketch font.
  21. On the Debug menu, click Start Debugging to build and run the app.

    Note

    Use the Simulator if you are running on a display with a resolution less than 1366 × 768.

    The Customers form should appear and be styled in the same way that it appears in the Design View window in Visual Studio. Notice that if you enter any text into the various fields on the form, they use the default font and styling for the TextBox controls.

    Note

    Although the Buxton Sketch font is good for labels and titles, it is not recommended as a font for data entry fields, because some of the characters can be difficult to distinguish from one another. For example, the lowercase letter l is very similar to the digit 1, and the uppercase letter O is almost indistinguishable from the digit 0. For this reason, it makes sense to stick with the default font for the TextBox controls.

  22. Click the top edge of the form and drag it so that the form is displayed in the left half of the screen and verify that the styling has been applied to the controls in the customersColumnarView grid. The form should look like this:

    A screenshot of the Customers form occupying the left half of the screen. The form uses the styles defined in the Customers app.
  23. Return to Visual Studio and stop debugging.

You can see that by using styles you can easily implement a number of really cool effects. In addition, careful use of styles makes your code much more maintainable than setting properties on individual controls. For example, if you want to switch the font used by the labels and headings in the Customers app, you need to make only a single change to the FontStyle style. In general, you should use styles wherever possible; besides assisting maintainability, use of styles helps to keep the XAML markup for your forms clean and uncluttered, and the XAML for a form only needs to specify the controls and layout, rather than how the controls should appear on the form.

Note

You can also use Microsoft Blend for Visual Studio 2013 to define complex styles that you can integrate into an app. Professional graphics artists can use Blend to develop custom styles and provide these styles in the form of XAML markup to developers building apps. All the developer has to do is add Style tags to the user interface elements to reference the appropriate styles.

Summary

In this chapter, you learned how to use the Grid control to implement a user interface that can scale to different device form factors and orientations. You also learned how to use the Visual State Manager to adapt the layout of controls when the user changes the size of the window displaying the app. Finally, you learned how to create custom styles and apply them to the controls on a form. Now that you have defined the user interface, the next challenge is to add functionality to the app, enabling the user to display and update data, which is what you will do in the final chapter.

  • If you want to continue to the next chapter, keep Visual Studio 2013 running, and turn to Chapter 26.

  • If you want to exit Visual Studio 2013 now, on the File menu, click Exit. If you see a Save dialog box, click Yes and save the project.

Quick reference

To

Do this

Create a new Windows Store app

Use one of the Windows Store templates in Visual Studio 2013, such as the Blank App template.

Implement a user interface that scales to different device form factors and orientations

Use a Grid control. Divide the Grid control into rows and columns, and place controls in these rows and columns rather than specifying an absolute location relative to the edges of the Grid.

Implement a user interface that can adapt to different display widths

Create different layouts for each view that display the controls in an appropriate manner. Use the Visual State Manager to select the layout to display when the visual state changes.

Create custom styles

Add a resource dictionary to the app. Define styles in this dictionary by using the <Style> element, and specify the properties that each style changes. For example:

<Style x:Key="GridStyle" TargetType="Grid">
    <Setter Property="Background"
Value="{StaticResource WoodBrush}"/>
</Style>

Apply a custom style to a control

Set the Style property of the control and reference the style by name. For example:

<Grid Style="{StaticResource GridStyle}">
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.37.191