Chapter 2. Silverlight User Interface Development

Since all client applications require some sort of end-user experience, user interface development is the first topic I will dive into after the introduction provided in Chapter 1. Also, for client-application development, it is usually the first aspect of the application that developers start to experiment with in learning a new technology.

The user interface is usually the hallmark of a great application proposal or application prototype. It helps communicate what an application will look like, as well as what it will actually do. How an application looks and feels is just as important as what the application actually does. It is understandable, as users expect more from client-applications, especially non-Web-based client applications such as mobile applications.

First up is an overview of the Windows Phone 7 application design and design resources. The Windows Phone 7 product team is incredibly passionate about the user interface they created for Windows Phone 7. In an effort to help jumpstart great user experience (UX) design and development for Windows Phone 7 developers, the Windows Phone 7 design team created some great resources and guidance, which I cover in this chapter.

After covering design, the chapter dives into developing UX in Visual Studio 2010, with a quick background on the underlying architecture of the Silverlight programming model and the. NET Framework for Silverlight. This book is not an introductory one, but this section provides hopefully enough background to fill in the major blanks as well as help understand the important namespaces and classes if you are new to Silverlight development.

The markup language for Windows Phone UX is Xml Application Markup Language (XAML). XAML development started out in Visual Studio 2005 with a basic design surface for Windows Presentation Foundation. Expression Blend was created to provide a design tool to make it easier for designers to work in XAML, but in a visual way. Both Visual Studio 2010 and Expression Blend XAML tooling has improved greatly, with unique support for phone development with Silverlight. I cover the built-in controls and capabilities using Visual Studio 2010 as the backdrop.

After covering Visual Studio 2010, UX development with Expression Blend 4 is next. As a developer, you need to learn Expression Blend 4 – it is definitely not just a tool for designers, and you will find some tasks are much easier to do in Expression Blend, such as data binding and sample data. The section covers laying out controls in Blend, sample data, data binding, the Silverlight Toolkit for Windows Phone 7, and animations in Expression Blend as well.

Designing for Windows Phone 7

This section covers design-oriented content that a developer will find very useful. I phrase it that way because this book in general is not geared toward designers; however, just as end-users were no longer satisfied with character-based UI when graphical UI came into vogue, today's end-users expect even more from client-based mobile applications when compared to the rich UX available via the desktop. Developers are an integral part to the design/development cycle, which is why it is strongly encouraged that developers embrace design concepts as much as possible to help create better UX beyond designer mock-ups.

Design Approach

The design team at Microsoft refers to the "design language" of Windows Phone 7, codenamed "Metro," when describing the approach they took when designing the Windows Phone 7 UI. The Metro codename is inspired by the graphics found in transportation systems worldwide, which rely on big, bold, beautiful graphics and text to communicate to the "end-user" or traveler where they need to go. It is inspired by other sources as well, such as Zune, video games, product packaging, and the like, which focus on these key principles:

  • Light and simple: Focus on primary tasks, achieving a lot with very little (little user effort and few phone resources, steps, and so on). Use whitespace to its full advantage.

  • Typography: Focus on beautiful, not just legible, with sensitivity to font weight, balance, and scale to communicate a sense of hierarchy for the content.

  • Motion: Responsive and alive UI. Transition between UI is just as important as the design of the UI. Create an animation system, not just transitions.

  • Content, not chrome: Reduce visuals that are not content. Navigate via content itself.

  • Honest: Design for the form factor, keeping things simple and direct. Be authentic. Content makes the UI beautiful.

Probably the most important design approach not to take is to simply port an iPhone or Android application to Windows Phone 7 without modifying the user interface to match the platform. The application will look odd and out of place if it does not at least use the default templates for the built-in controls and font styles for text. In the next section I cover the great design resources available to help you build an authentic Windows Phone 7 user interface, whether you are creating a new application or porting an existing one.

Design Resources

The Windows Phone 7 documentation includes several designer-oriented resources to help generate a beautiful user experience. If you are new to Windows Phone 7 design or development, you will want to review these resources.

Windows Phone Design System – Codename Metro

The Windows Phone Design System – Codename Metro is available here:

http://go.microsoft.com/fwlink/?LinkID=189338

This document describes what the product team calls its design language: seven areas of differentiation, and "red threads," or guiding principles. The user experience of Windows Phone 7 is partly inspired by the image of the simple and effective communication style provided by metropolitan public transportation system signage as shown in Figure 2-1.

Metropolitan signage as inspiration

Figure 2.1. Metropolitan signage as inspiration

The product team describes Metro as

"...our code name for our design language. We call it metro because it it's modern and clean. It's fast and in motion. It's about content and typography. And it's entirely authentic."

There are key points to take notice of in this description. "Modern and clean" means an application should provide just what is needed to get the task done, whether that task is to provide a movie, the news, or a weather forecast.

"Fast and in motion" means anything other than snappy performance is unsatisfactory. While this may seem obvious, the key here is that a user's perception is what's important. No doubt some tasks take time, so the key is to provide animation and indicators that help shape the user's perception that the application is responsive.

"Content and typography" means that the focus of the application is on the content, not application chrome. Navigate via the content with touch instead of a scroll bar is one example. Typography is incredibly important, so much so that the design team created a special font type for Windows Phone 7 called Segoe WP that looks great onscreen and is pleasing to the eye. Finally, "authentic" means that the application does not try to do more than what it is.

UI Design and Interaction Guide for Windows Phone 7

Here is a link to the UI Design and Interaction Guide for Windows Phone 7:

http://go.microsoft.com/fwlink/?LinkID=183218

It cannot be overstated: this document is a must-read for both designers and developers. It covers all of the user experience customizations, input methods, and controls to help developers and designers understand how to build a great looking Windows Phone 7 user interface.

Reviewing this document will help you combine Metro with your company's brand in the best way, resulting in an authentic user experience that is true to your brand and Windows Phone 7. Figure 2-2 is a page from the document with annotations.

UI Design and Interaction Guide format

Figure 2.2. UI Design and Interaction Guide format

The UI Design and Interaction Guide for Windows Phone 7 v2.0.pdf document prints out in a large format and is best viewed on a large monitor. Each section provides a topic item, such as "Application settings" (as shown in Figure 2-2). It displays an image and textual context for the topic item, along with guidance for designers and developers with do's and don'ts. As far as I am concerned, this document is required reading for anyone who designs or develops a Silverlight-based Windows Phone 7 application.

Application Icons

Windows Phone 7 design resources includes a zip of icons to use directly in your application or as a model for custom application icons you build. The application icons come in .png and XAML vector format. The .png format comes in both a light and dark variant to support the light and dark themes in Windows Phone 7. Figure 2-3 shows the included icons, as well as other sample icons. The image is taken from the Windows Phone Design System – Codename Metro.pdf document.

Collage of application icons for Windows Phone 7

Figure 2.3. Collage of application icons for Windows Phone 7

The icons are included with the Windows Phone 7 design resources, as well as installed by the Windows Phone Developer Tools, at C:Program Files (x86)Microsoft SDKsWindows Phonev7.0Icons on an x64 Windows machine. The icons come in black and white to match the built-in application themes available in Windows Phone 7.

The most common place to use the icons is for the Application bar if included in your application; however, they be incorporated into the main UI as well.

Design Templates for Windows Phone 7

The design templates for Windows Phone 7.zip file includes 28 Adobe Photoshop files that designers can use to create pixel-perfect UX. Share this download with your Windows Phone 7 designer friends and they will be forever grateful. It takes the guesswork out of how to size the design. It will also save rework for developers, as the templates will be ready to go when imported – more on this in the next section.

One little gem you will not want to ignore is the Design Templates for Windows Phone 7.pdf document that is included in the template download zip located here:

http://go.microsoft.com/fwlink/?LinkId=196225

This document details how to use the templates, which is especially important for controls that are not shipped as part of the Windows Phone Developer Tools. A great time to use this document is when you need to build UI, like a notification, where there isn't an existing control. The guidance is provided to help designers and developers match both visually and in interaction the built-in version of the control that appears in Windows Phone OS 7.0.

Tip

Many additional controls are shipped in the Silverlight Toolkit for Windows Phone, which is available for download at CodePlex: http://silverilght.codeplex.com.

This section concludes the overview of the design resources for Windows Phone 7. Please do checkout these resources as it will save you rework later. The next section covers the mechanics of how designers and developers can work together to build a Silverlight for Windows Phone 7 user interface.

Designer and Developer Mechanics

As with most client application development, Windows Phone 7 applications begin as comprehensive artwork, or "comps" for short, that can start out as a rough sketch wireframe that is refined into a full user interface mock-up handed over to developers for development. Quite often the actual development results in a far less stunning UI when compared to original comps. This is a result of a mismatch of the output from the design process, usually a vector drawing flattened into an image format and the input of the development process, which is a development language.

Starting with Windows Presentation Foundation, XAML was introduced as a language to describe UX that is both user- and tool-consumable, meaning a developer can author XAML directly or tools vendors can build applications that allow a designer and developer to visually create UX that generates the appropriate XAML. Silverlight was introduced after XAML as a lightweight version of WPF that fits into a small (approximately 5 MB) cross-platform, cross-browser desktop plug-in. Initially Silverlight included a subset of the most commonly used features of WPF. Since its introduction, Silverlight has steadily added additional capabilities to match more closely the full capabilities available in WPF. Examples include more support for triggers, Commanding, and COM interop, making offline desktop Silverlight a capable alternative to WPF for many desktop application scenarios.

Silverlight for Windows Phone 7 is based on Silverlight 3 with some Silverlight 4 features pulled forward, putting XAML-based development front and center in mobile application development. Also, since Silverlight for Windows Phone 7 does not run in a browser, some features, like browser-interoperability available in Silverlight for the desktop, are removed from Silverlight for Windows Phone. Fundamentally, however, they share core capabilities.

The reason XAML is so important and useful is that the output of visual design tools can be directly consumed by developers, since the output of the visual design is human-readable XAML. Designers can use Expression Design to create rich visual designs for application control templates as well as general application UX. Expression Design supports exporting XAML.

While Expression Design is a great tool, the world of designers is dominated by the Adobe toolset. What may not be well-known by many designers is that Expression Blend 4 has excellent import capabilities to pull in the vector output from the Adobe toolset directly into Expression Blend as XAML. The Expression Blend 4 import capabilities are shown in Figure 2-4.

Expression Blend 4 file menu import capabilities

Figure 2.4. Expression Blend 4 file menu import capabilities

The menu offers import capabilities for three Adobe file formats: .fxg, .psd (Photoshop), and .ai (Illustrator). The .fxg file is the new file interchange format introduced in Adobe Creative Suite 5 that provides a common interchange format for the Adobe toolset. The format is very similar to .svg format. The other two file formats are the native format of Adobe's well known Photoshop and Illustrator tools. Figure 2-5 shows one of the Windows Phone 7 design templates opened in Photoshop.

Windows Phone 7 design template in Photoshop

Figure 2.5. Windows Phone 7 design template in Photoshop

Let's say the example in Figure 2-5 is part of a real application that you are building. In Expression Blend, you can import the background using the File

Windows Phone 7 design template in Photoshop
Import a layer from a sample Photoshop file

Figure 2.6. Import a layer from a sample Photoshop file

When you click OK in the dialog shown in Figure 2-6, a Canvas object is added to the currently opened XAML file and the image assets are brought into the project in a new folder named with the same name as the imported asset but with the suffix _images appended. At the bottom on the right of Figure 2-6 there's an option to generate a "Compatibility image" instead of attempting to import the vector components of the image as XAML. What this option does is take the selected layers and "flatten" it to a .png image. This is a handy option when you just need a flattened image instead of the layers, which in many cases has better performance than having to calculate vector-based layout.

This section provided an overview of how designers and developers can work in their preferred tools while allowing for the smoothest work stream possible with Expression Blend 4 as the bridge between a pure designer and developer.

The technical designer or developer who works in Expression Blend will also build out the interaction model for the user experience using the built-in animation capabilities, which I cover later in this chapter. Before I jump into Expression Blend 4, I next cover Visual Studio 2010 with an introduction to the .NET Framework for Silverlight and an overview of the available controls.

User Interface Development in Visual Studio 2010

I highlighted in the introduction to this chapter the much improved design surface available in Visual Studio 2010 as compared to Silverlight support in previous editions of Visual Studio. I also gave you a whirl-wind tour of the improved tooling, so I will not cover it in this section. Be sure to refer to Chapter 1 for a refresher if needed.

Visual Studio 2010 Windows Phone Developer Tools include several additional controls and project templates to help developers get started building their mobile application. Figure 2-7 shows the available templates.

Visual Studio 2010 File New Project – Silverlight for Windows Phone dialog

Figure 2.7. Visual Studio 2010 File

Visual Studio 2010 File New Project – Silverlight for Windows Phone dialog
New Project – Silverlight for Windows Phone dialog

The first three application templates existed in the beta tools. The last two templates, Windows Phone Panorama Application and Windows Phone Pivot Application, were added to the final release and hint to the fact that the shipped tools include Panorama and Pivot controls that match the built-in Windows Phone 7 application experience. I cover the Panorama and Pivot controls later on in this chapter, since they define unique application UI navigation architectures.

The first thing you will notice when reviewing a Silverlight for Windows Phone application is that the control templates follow the Windows Phone 7 theme style, defaulting to the dark theme. The other available theme is the light theme.

Note

The built-in controls will automatically adjust to application theme changes by the user; however, the developer may need to adjust the rest of the UI such as images, backgrounds, and so on, if the end-user changes the phone theme to light or vice versa.

We create the BuiltInControls project by selecting File

Visual Studio 2010 File New Project – Silverlight for Windows Phone dialog
Initial project file layout in the Solution Explorer tool window

Figure 2.8. Initial project file layout in the Solution Explorer tool window

A typical Windows Phone 7 project consists of an App.xaml and App.xaml.cs file that represents the non-visual Application object that is the root of the project and application structure. MainPage.xaml with the MainPage.xaml.cs code-behind file is the default initial UI for the application. There are three graphic files associated with the project structure:

  • Background.png : This is a 173 × 173-pixel image that represents the application's "tile" when pinned to the Start screen. The user has to pin your tile. Applications cannot pin themselves.

  • ApplicationIcon.png: This is a 62 × 62–pixel image that is the icon in the application list when installed on a device.

  • SplashScreenImage.jpg: This is a 480 × 800-pixel image displayed when an application first launches. Developers do not have to do anything to show the image or hide the image. The framework handles it.

Tip

From the certification requirements applications must show UI within 5 seconds and be functional within 20 seconds after launch. The splash screen image is displayed until the UI is shown.

The next section covers the Windows Phone manifest file in more detail.

WMAppManifest.xml File

A file unique to the Windows phone 7 Visual Studio project templates is the WMAppManifest.xml file under the properties folder. Listing 2-1 shows the default WMAppManifest.xml file for the BuiltInControls project.

Example 2.1. WMAppManifest.xml Configuration File

<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment"
WMAppManifest.xml Configuration File
AppPlatformVersion="7.0"> <App xmlns="" ProductID="{1ea898d1-33a3-4064-a3e2–ad6cc6a5a38a}" Title="BuiltInControls"
WMAppManifest.xml Configuration File
RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="BuiltInControls
WMAppManifest.xml Configuration File
author" Description="Sample description" Publisher="BuiltInControls"> <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath> <Capabilities> <Capability Name="ID_CAP_GAMERSERVICES"/> <Capability Name="ID_CAP_IDENTITY_DEVICE"/> <Capability Name="ID_CAP_IDENTITY_USER"/> <Capability Name="ID_CAP_LOCATION"/> <Capability Name="ID_CAP_MEDIALIB"/> <Capability Name="ID_CAP_MICROPHONE"/> <Capability Name="ID_CAP_NETWORKING"/> <Capability Name="ID_CAP_PHONEDIALER"/> <Capability Name="ID_CAP_PUSH_NOTIFICATION"/> <Capability Name="ID_CAP_SENSORS"/> <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/> </Capabilities> <Tasks> <DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/> </Tasks> <Tokens> <PrimaryToken TokenID="BuiltInControlsToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background.png
WMAppManifest.xml Configuration File
</BackgroundImageURI> <Count>0</Count> <Title></Title> </TemplateType5>
</PrimaryToken>
    </Tokens>
  </App>
</Deployment>

When you configure project settings by right-clicking the BuiltInControls project node in the Solution Explorer and select Properties, the values are updated in AssemblyInfo.cs just like for every other .NET Framework project, but it also updates values in WMAppManifest.xml. The WMAppManifest.xml is rewritten when you submit your application to marketplace based on capabilities detection and based on the metadata provided to marketplace when submitting the application.

You can carefully edit the WMAppManifest.xml during development to help identify certification requirements. As an example, if you do not believe your application needs location information, you can remove ID_CAP_LOCATION from the Capabilities XML element. When you run your application, you will discover errors indicating that your application needs that capability. Using location means that certain certification requirements need to be met such as asking for permission as well as having a setting to disable location. Capabilities are an important part of certification.

Note

You can use the Capabilities Detection Tool available for download as of this writing in the January 2011 Tools update located here: www.microsoft.com/downloads/en/details.aspx?FamilyID=49B9D0C5-6597-4313-912A-F0CCA9C7D277.

Continuing to explore WMAppManifest.xml, the App element contains several key pieces of information. You should not change the ProductID once the application is published in Marketplace. If you change the ProductID when submitting an update, Marketplace will infer it to be a new product and not an update to an existing product. Existing users will never see the update in this case.

The Genre is configured based on user selection in the marketplace metadata. The default for Silverlight and XNA Framework is apps.normal. You can change it to Apps.Games to force the application to appear in the Games Hub on a device.

One item to be aware of is that if you rename MainPage.xaml, you should also update the DefaultTask element under the Tasks element to match the first UI Xaml page that should be displayed. If you do not, the application will fail to launch. For more information on the WMAppManifest.xml file, go to:

http://msdn.microsoft.com/en-us/library/ff769509(VS.92).aspx

Anatomy of a WP7 Application

As mentioned, App.xaml and App.xaml.cs are the code files for the application object that hosts the individual pages. Listings 2-2 and 2-3 contain a default App.xaml file and its code behind file.

Example 2.2. App.xaml File

<Application
    x:Class="BuiltInControls.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
    <!--Application Resources-->
    <Application.Resources>
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
        <!--Required object that handles lifetime events for the application-->
        <shell:PhoneApplicationService
            Launching="Application_Launching" Closing="Application_Closing"
            Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>
</Application>

Example 2.3. App.xaml.cs Code File

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace BuiltInControls
{
  public partial class App : Application
  {
    /// <summary>
    /// Provides easy access to the root frame of the Phone Application.
    /// </summary>
    /// <returns>The root frame of the Phone Application.</returns>
    public PhoneApplicationFrame RootFrame { get; private set; }

    /// <summary>
    /// Constructor for the Application object.
    /// </summary>
    public App()
    {
      // Global handler for uncaught exceptions.
      UnhandledException += Application_UnhandledException;

      // Show graphics profiling information while debugging.
      if (System.Diagnostics.Debugger.IsAttached)
      {
        // Display the current frame rate counters.
        Application.Current.Host.Settings.EnableFrameRateCounter = true;
// Show the areas of the app that are being redrawn in each frame.
        //Application.Current.Host.Settings.EnableRedrawRegions = true;

        // Enable non-production analysis visualization mode,
        // which shows areas of a page that are being GPU accelerated with a colored overlay.
        //Application.Current.Host.Settings.EnableCacheVisualization = true;
      }

      // Standard Silverlight initialization
      InitializeComponent();

      // Phone-specific initialization
      InitializePhoneApplication();
    }

    // Code to execute when the application is launching (eg, from Start)
    // This code will not execute when the application is reactivated
    private void Application_Launching(object sender, LaunchingEventArgs e)
    {
    }

    // Code to execute when the application is activated (brought to foreground)
    // This code will not execute when the application is first launched
    private void Application_Activated(object sender, ActivatedEventArgs e)
    {
    }

    // Code to execute when the application is deactivated (sent to background)
    // This code will not execute when the application is closing
    private void Application_Deactivated(object sender, DeactivatedEventArgs e)
    {
    }

    // Code to execute when the application is closing (eg, user hit Back)
    // This code will not execute when the application is deactivated
    private void Application_Closing(object sender, ClosingEventArgs e)
    {
    }

    // Code to execute if a navigation fails
    private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
    {
      if (System.Diagnostics.Debugger.IsAttached)
      {
        // A navigation has failed; break into the debugger
        System.Diagnostics.Debugger.Break();
      }
    }

    // Code to execute on Unhandled Exceptions
    private void Application_UnhandledException(object sender,
App.xaml.cs Code File
ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached)
{
        // An unhandled exception has occurred; break into the debugger
        System.Diagnostics.Debugger.Break();
      }
    }

    #region Phone application initialization

    // Avoid double-initialization
    private bool phoneApplicationInitialized = false;

    // Do not add any additional code to this method
    private void InitializePhoneApplication()
    {
      if (phoneApplicationInitialized)
        return;

      // Create the frame but don't set it as RootVisual yet; this allows the splash
      // screen to remain active until the application is ready to render.
      RootFrame = new PhoneApplicationFrame();
      RootFrame.Navigated += CompleteInitializePhoneApplication;

      // Handle navigation failures
      RootFrame.NavigationFailed += RootFrame_NavigationFailed;

      // Ensure we don't initialize again
      phoneApplicationInitialized = true;
    }

    // Do not add any additional code to this method
    private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
    {
      // Set the root visual to allow the application to render
      if (RootVisual != RootFrame)
        RootVisual = RootFrame;

      // Remove this handler since it is no longer needed
      RootFrame.Navigated -= CompleteInitializePhoneApplication;
    }

    #endregion
  }
}

Applications can locate application-wide resources such as data sources, styles, and templates in the Application.Resources element of App.xaml. The ApplicationLifetimeObjects element in App.xaml can contain references to classes that extend application services without having to subclass the Application class. The order of the services listed dictates the order that they are initialized and the order that lifetime event notifications are received. A class must implement the IApplicationService interface and optionally the IApplicationLifetimeAware interface in order to be an ApplicationLifetimeObject service.

The default extension that is configured in the ApplicationLifetimeObjects is the Microsoft.Phone.Shell.PhoneApplicationService extension that manages lifetime events such as Launching, Closing, Activated, and Deactivated for tombstoning, which I cover in Chapter 4. In the next section we create a Configuration Settings service that you can use to manage your application's configuration.

Configuration Settings Service

As part of user interface development, customizable settings are an important component to the user experience. In the sample source code is the ConfigSettingsDemo project that demonstrates how to create an application service for managing settings beyond the UI. The project contains an application lifetime service named ConfigurationSettingsService, which implements the IApplicationService interface. The project includes a Services folder containing the ConfigurationSettingsService.cs code file as shown in Listing 2-4.

Example 2.4. ConfigurationSettingsService.cs Code File

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Xml.Linq;
using ConfigSettingsDemo;

namespace ConfigSettingsDemo.Services
{
  public class ConfigurationSettingsService : IApplicationService
  {
    private string _configSettingsPath = @"Settings";
    private string _configSettingsFileName = " ConfigurationSettings.xml";

    //Event to allow the Application object know it is safe to
    //access the settings
    public event EventHandler ConfigurationSettingsLoaded;

    #region IApplicationService Members
    void IApplicationService.StartService(ApplicationServiceContext context)
    {
      LoadConfigSettings();
    }

    private void LoadConfigSettings()
    {
      //TODO - Load ConfigSettings from isolated storage

      //Check to see if the event has any handler's attached
      //Fire event if that is the case
      if (ConfigurationSettingsLoaded != null)
        ConfigurationSettingsLoaded(this, EventArgs.Empty);
    }

    private void SaveConfigSettings()
    {
      //TODO - Save ConfigSettings to isolated storage
    }
void IApplicationService.StopService()
    {
      SaveConfigSettings();
    }
    #endregion

    //Stores configuraiton settings in
    public Dictionary<string, string> ConfigSettings { get; set; }
  }
}

The sample doesn't implement the actual loading or saving of the data until I cover Isolated Storage later in Chapter 4; however, the service is fully wired up within the application. First we have to list the ConfigurationSettingsService in the App.xaml Application.ApplicationLifetimeObjects element. To do so, we have to make the class available in Xaml by adding an xml namespace:

xmlns:services="clr-namespace:ConfigSettingsDemo.Services"

The service can now be added to the ApplicationLifetimeObjects using the services namespace:

<services:ConfigurationSettingsService />

Adding that line of code completes the changes in App.xaml. In App.xaml.cs the ConfigSettingsDemo.Services is added via a using clause. The App() constructor is modified to get a reference to the ConfigurationSettingsService and to add an anonymous event handler that allows the configuration settings to load before launching the main user interface:

ConfigurationSettingsService service =
  App.Current.ApplicationLifetimeObjects[1]
  as ConfigurationSettingsService;

service.ConfigurationSettingsLoaded += new EventHandler((s, args) =>
{
  // Phone-specific initialization
  InitializePhoneApplication();
});

The splash screen will display until this event fires. As a test, modify ConfigurationSettingsService. LoadConfigSettings() and add this line of code:

System.Threading.Thread.Sleep(10000);

The splash screen will display for about 10 seconds. This demonstrates the effect of the anonymous event handler in allowing the configuration settings to fully load.

This completes our overview of how to create a lifetime service. I will now shift gears to a quick discussion of the events present in App.xaml.cs. The App.xaml.cs code-behind file contains the events and methods associated with the Application object. There are several important methods and events available to applications that we cover in the next few sections.

The Default App() Constructor

Besides wiring up the Application_UnhandledException event, the default constructor enables the Application.Current.Host.Settings.EnableFrameRateCounter if the debugger is attached as shown in code Listing 2-3. The frame rate counter is much more valuable on the device than in the emulator and it is something to monitor throughout development as features are added. Figure 2-9 shows the counters:

Frame rate counters

Figure 2.9. Frame rate counters

Table 2-1 explains the counters identified by letters in Figure 2-9.

Table 2.1. Frame Rate Counters

Letter

Counter

Description

A

Render Thread FPS

This is the frame rate for the render thread where animations, etc., run. Applications should try to push as much render processing as possible to the render thread from the UI thread.

B

UI Thread FPS

This is the frame rate for the UI thread where application runs. Application code execution directly affects this frame rate.

C

Texture Memory Usage

Indicates the video memory used for storing application textures.

D

Surface Counter

A count of the number of surfaces that are passed to the graphics chip.

E

Intermediate Texture Count

The number of intermediate textures created for compositing.

F

Screen Fill Rate

A metric representing the number of complete phone screens being painted each frame.

Jeff Willcox, a senior software development engineer on the Silverlight phone and devices team at Microsoft, provides some target framerates for good performance on his blog: www.jeff.wilcox.name/2010/07/counters/, but here is a summary:

  • Render Thread FPS: 60 fps is great performance. 30 fps or below will show a poor experience. Turns red below 30 fps.

  • UI Thread: This is the busiest thread. Applications must try to take as much work as possible off of the UI thread by leveraging the Render Thread or a background thread. Turns red below 15 fps.

  • Screen Fill Rate: Below 2.0 is ideal. Above 2.5 indicates overdraw.

The frame rate counters can be zero when there isn't an animation playing on the thread at the moment and then spike during an animation or transition. Applications can play a simple continually playing animation to always show a frame rate.

The best way to leverage the frame rate counters and the screen fill rate counter is to continuously monitor them when testing on an actual device. The best time to address frame rate issues is after making a change and it results in a drop in performance. Check out the Creating High Performing Silverlight Applications for Windows Phone Samples for more information on UX performance:

www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=3a8636bf-185f-
Frame Rate Counters
449a-a0ce-83502b9ec0ec

ApplicationUnhandledException Event

The Application_UnhandledException event is where you can log, report, and display an error message to a user when something unexpected happens in your application that causes an unhandled exception. Applications should customize this event to present a friendly message to the user. Many users welcome the ability to enter feedback regarding a failure so displaying a simple UI to collect information on what the user was doing at the time and recording to a local error log for review can help increase application quality.

In the Chapter 2 Solution's ConfigSettingsDemo project's App.xaml.cs, the Application_UnhandledException event handler is modified to show an error message to the user when an exception is encountered.

private void Application_UnhandledException(object sender,
ApplicationUnhandledException Event
ApplicationUnhandledExceptionEventArgs e) { MessageBox.Show( "Error! We logged the error. Click OK to turn on logging mode.", "Error Diagnostics", MessageBoxButton.OKCancel); //TODO – Add logging service //Log error to logging service here //Turn on logging mode for logging service if OK clicked by user //Use the Microsoft.Phone.Tasks.EmailComposeTask //to collect exception information and offer to the user //to send in the exeception info. //Set e.Handled to true if recoverable e.Handled = true; if (System.Diagnostics.Debugger.IsAttached) { // An unhandled exception has occurred; break into the debugger System.Diagnostics.Debugger.Break(); } }

You can intentionally cause an error to display the error message by clicking the DivideByZero button at the bottom of the main page. Run the application without the debugger connected by deploying the project and running the app manually in the emulator or on a device. You will notice that the error message displays and then the application exits.

The Application_UnhandledException event handler arguments include the familiar sender object and an instance of the ApplicationUnhandledExceptionEventArgs. The ApplicationUnhandledExceptionEventArgs class contains the following properties:

  • ExceptionObject property: A reference to the original exception that was thrown.

  • Handled property: Set to true to if the application can recover from the error.

In the previous code, uncomment the line e.Handled = true; and the application will continue to run after the error is thrown. This property gives the application a chance to recover without kicking the user completely out of the application, providing a much better experience.

The comments hint at creating a logging service and adding logging to the application with the implication that the user can choose to upload the logs. Such a logging service could implement IApplicationService, and therefore be available anywhere in the application via the Application. ApplicationLifetimeObjects collection along with the Configuration Service discussed above.

Consider that, in a consumer-oriented application, you may not have a direct relationship to your customer, so you simply cannot ask them what they saw just before the crash. One option is to prompt the user if they would like to send more info. If the user agrees, display the Microsoft.Phone.Tasks. EmailComposeTask to send the Exception object's Message and StackTrace values to the support email alias. I cover the EmailComposeTask in Chapter 4.

Part of the overall user experience is to build applications that can recover as well as give the user an opportunity to provide additional information. Most users will be happy to do so if they like your application and want to help make it better.

Anatomy of a PhoneApplicationPage

I covered the Application object and related PhoneApplicationFrame object that hosts the application. You can get access to the PhoneApplicationFrame with code like this:

PhoneApplicationFrame frame = App.Current.RootVisual as PhoneApplicationFrame;

Once the root PhoneApplicationFrame loads, the first UI displayed after the splash screen is a PhoneApplicationPage identified as the default task in WMAppManifest.xml, named MainPage.xaml with its corresponding code-behind file named MainPage.xaml.cs. The code-behind partial class inherits from PhoneApplicationPage.MainPage.xaml is linked to the code-behind via the Class attribute on the root PhoneApplicationPage root element.

The root element includes several namespace declarations to bring in common namespaces, like the phone namespace alias that pulls in the Microsoft.Phone.Controls namespace. I cover options related to PhoneApplicationPage in the next sections.

Orientation

The root element of the page declaration includes two attributes related to page layout, SupportedOrientations and Orientation. SupportedOrientations has three options:

  • Landscape

  • Portrait

  • PortraitOrLandscape

The Orientation attribute can be set to any of the SupportedOrientations permissible values. For the ConfigSettingsDemo project, SupportedOrientations is set to PortraitOrLandscape in order to test orientation changes. When SupportedOrientations is set to PortraitOrLandscape, the page automatically changes the display depending on how you hold the phone. We set SupportedOrientations to PortraitOrLandscape for the ConfigSettingsDemo project.

The page does not automatically change the layout of controls. So, if the page has more than 480 pixels of content when held in Portrait mode, the content will run off the screen when held in Landscape mode. An application has an opportunity to react to orientation changes by adjusting the layout content in the PhoneApplicationPage.OrientationChanged event. I cover how to handle orientation changes in detail in Chapter 5, but for this demo, I will use a simple switch statement to reposition the single UI element, the divideByZeroBtnButton object:

private void PhoneApplicationPage_OrientationChanged(object sender,
Orientation
OrientationChangedEventArgs e) { switch (e.Orientation) { case PageOrientation.Landscape: divideByZeroBtn.Margin = new Thickness(12, 200, 235, 0); break; case PageOrientation.LandscapeLeft: divideByZeroBtn.Margin = new Thickness(12, 200, 235, 0); break; case PageOrientation.LandscapeRight: divideByZeroBtn.Margin = new Thickness(12, 200, 235, 0); break; //default is Portrait default: divideByZeroBtn.Margin = new Thickness(12, 400, 235, 0); break; } }

SystemTray

The system tray is the bar across the top of the screen in Portrait mode that displays the connection signal strength, Wi-Fi, and current time. According to the UI Design and Interaction Guide for Windows Phone 7, the system tray or status bar is 32 pixels high in Portrait mode and 72 pixels width in Landscape mode. Developers can set it to not display by editing the XAML for the page to this value:

shell:SystemTray.IsVisible="False"

It is not recommended to hide the SystemTray, as users consider it to be valuable information. Letting the SystemTray display is helpful to the user who wants to see the current time without having to exit the application. Probably the most common reason to hide the system tray is for a XNA Game Studio game.

Application Bar

The Application Bar is located at bottom of the screen to provide menu icon buttons for actions and views related to the content presented on the page. You can put up to four icon buttons at any time. If you have additional actions, you can place them into the Application Bar Menu instead. The Application Bar Menu item text will run off the screen. The recommendation is between 14 and 20 characters.

By default, XAML for the Application Bar is available in a new page but commented it out. The default XAML is un-commented for the ConfigSettingsDemo project. Two of the Application Bar IconButton images that are installed by default in the C:Program Files (x86)Microsoft SDKsWindows Phonev7.0Icons folder are dropped into an Images folder for the project and set as the icon for two of the objects. Figure 2-10 shows the Application Bar after swiping up on the Application Bar to display the Application Bar menu items.

Expanded Application Bar

Figure 2.10. Expanded Application Bar

If you click the back button when the Application Bar is expanded, the Application Bar will close down. The application bar height is 72 pixels both in portrait and landscape mode and cannot be changed. The Application Bar can be displayed and hidden.

Developers should resist the temptation to use the Application Bar for navigation. Developers should not put a Home button into the Application Bar either, because it breaks the back stack. Users should navigate your application via the content and the hardware Back button.

Page Navigation

Most Windows Phone 7 applications will consist of more than one page. Silverlight for Windows Phone leverages the built-in navigation framework available as part of Silverlight. Pages navigation occurs within the hosting Application PhoneApplicationFrame object via the Page.NavigationService instance of the System.Windows.Navigation.NavigationService object.

In addition to the NavigationService, the page has two methods to override called OnNavigatedTo() and OnNavigatedFrom(). I cover these options in the next two sections.

NavigationService

The NavigationService has several properties and methods to aid in application navigation listed in Table 2-2.

Table 2.2. NavigationService Key Properties and Methods

Member

Description

CanGoBack

Indicates whether there is an entry in the back stack to navigate to backward in the stack.

CanGoForward

Indicates whether there is an entry in the forward navigation history to navigate to forward to in the navigation history.

GoBack

Navigate to the most recent page in the back stack. Throws an exception if there isn't an entry to navigate back to in the back stack.

GoForward

Navigate to the most recent page in the forward navigation history. Throws an exception if there isn't an entry to navigate forward to in the navigation history.

Navigate Method

Navigates to the page specified by the passed in Uri object.This Uri must be of type UriKind.Relative.

Navigated Event

Event fires when content that is being navigated to has been located and is available.

Navigating Event

Event fires when a new navigation is requested.

NavigationFailed Event

Event fires when a navigation request encounters an error.

NavigationStopped Event

Event fires when a navigation requested when an existing navigation event is in progress. It also occurs if the StopLoading method is called.

StopLoading Method

Stops asynchronous navigations that have not yet been processed.

The NavigationService provides full control over application flow but the most common member called is the Navigate method. In this chapter's solution PageNavigation project, MainPage contains a TextBlock that when clicked navigates to Page2.xaml:

private void NavToPage2_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  this.NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
}

When the project is run and the TextBlock with the Text "Navigate to Page 2" is clicked, the event fires and Page2.xaml is displayed. Developers can pass parameters to the navigation target using standard Query string parameters with the question mark and paramname=paramdata notation like this:

this.NavigationService.Navigate(
  new Uri(String.Format("/Page2.xaml?page2data={0}",textBox1.Text), UriKind.Relative));

Pass multiple parameters like this: Page2.xaml?ParamName1=ParamData1&ParamName2=ParamData2 and so on with an ampersand between parameter values. Generally parameters consist of keys or object IDs such that the page can look up the full object or object collection of data for rendering.

In Table 2-3, the events like Navigating and Navigated provide opportunities to display progress to the user as navigation events fire. To test this, add the below line of code to the constructor for Page2.xaml:

System.Threading.Thread.Sleep(5000);

The effect is that when the TextBlock is clicked, the UI appears frozen for about five seconds before the navigation occurs. To provide feedback to the user, a ProgressBar is added to the UI and IsIndeterminate is set to False and Visibility to Collapsed.

Note

IsIndeterminate should be set to false anytime the ProgressBar is not needed in order to conserve CPU resources. The Silverlight for Windows Phone toolkit includes a performance optimized PerformanceProgressBar control as well.

Navigation.Navigating and Navigation.Navigated are wired up to an event handler in the PhoneApplicationPage_Loaded event in MainPage.xaml.cs in the PageNavigation project. The Navigating event handler enables and makes visible the ProgressBar. The Navigated event handler hides the ProgressBar and sets IsIndeterminate to false. Here is the code from the PageNavigation project's MainPage.xaml.cs code file:

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
  NavigationService.Navigating += new navigation.NavigatingCancelEventHandler
NavigationService Key Properties and Methods
(NavigationService_Navigating); NavigationService.Navigated += new navigation.NavigatedEventHandler
NavigationService Key Properties and Methods
(NavigationService_Navigated); } void NavigationService_Navigating(object sender, navigation.NavigatingCancelEventArgs e) { progressBar1.Visibility = Visibility.Visible; progressBar1.IsIndeterminate = true; } void NavigationService_Navigated(object sender, navigation.NavigationEventArgs e) { progressBar1.Visibility = Visibility.Collapsed; progressBar1.IsIndeterminate = false; }

The performance of the ProgressBar is choppy because, by default, it runs on the UI thread, which is put to sleep in the Page2 constructor. I cover the PerformanceProgressBar in Chapter 5 when I go over the Silverlight for Windows Phone toolkit.

Tip

In Silverlight there are two threads that draw to the screen, the UI thread and the Render thread. Storyboard animations run on the Render thread. User code runs on the UI thread. Any animations that run on the UI thread can become choppy if the UI thread is very busy doing application work. Developers should strive to offload as much work as possible from the UI thread and keep an eye on the Render thread and UI thread frame rate counters to see how code changes affect render performance.

This sample so far shows how to use the NavigationService to navigate to a page, as well as hook into navigation related events. The next section covers the PhoneApplicationPage overrides available that allow additional hooks into the navigation system.

OnNavigated Overrides

There are two PhoneApplicationPage method overrides available to further plug into the navigation system:

  • OnNavigatedFrom: Event fires when navigating from the current page.

  • OnNavigatedTo: Event fires when navigating to the current page.

Both methods take a NavigationEventArgs object. This object includes two properties:

  • Uri: Uri of the target for navigation.

  • Content: The content of the target being navigated to.

The OnNavigatedFrom override is the method where you can take any final actions when the page has become inactive. The OnNavigatedTo override is called when the page becomes active in the navigation frame. Developers can access query parameters on OnNavigatedTo with code similar to the following from MainPage.xaml.cs in the PageNavigation project:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
  if (NavigationContext.QueryString.ContainsKey("page2data"))
    dataFromMainPageTextBlock.Text = NavigationContext.QueryString["page2data"];

  base.OnNavigatedTo(e);
}

In this code, we first check to make sure that the parameter is present and then retrieve the value. Otherwise, if you attempt to retrieve data for a non-existing key, it results in an error. We will explore navigation further in Chapters 5 and 6, but many of the examples leverage navigation so this section provides an overview. This completes the discussion on the navigating events.

Up to now, this chapter focused on overall design and then dove into project organization covering the Application object, PhoneApplicationFrame, PhoneApplicationPage, and an overview of the navigation framework. In the next section I step back a bit and provide an overview of the .NET Framework for Silverlight and programming XAML, to help prepare for more advanced topics such as data binding, control templates, and control customization.

.NET Framework for Silverlight

As I mentioned earlier, Silverlight for Windows Phone 7 is based on Silverlight 3 with some key features pulled forward from Silverlight 4, such as the WebBrowser control and offline DRM for Silverlight Smooth Streaming Support, which means you can play DRM'd content when in airplane mode. I cover DRM and SmoothStreaming in more detail in Chapter 6.

Since this chapter is focused on building application user experience in Silverlight, it provides a deeper look at the .NET Framework for Silverlight. Here is a summary of the major .NET Framework namespaces available in Silverlight for Windows Phone 7:

  • System

  • System.Collections

  • System.Collections.Generic

  • System.Diagnostics

  • System.Globalization

  • System.IO

  • System.Linq

  • System.Media

  • System.NET

  • System.Reflection

  • System.Runtime

  • System.Security

  • System.ServiceModel

  • System.Text

  • System.Threading

  • System.Windows

  • System.Windows.Controls

  • System.Windows.Input

  • System.Windows.Shapes

  • System.XML

If you are at all familiar with Silverlight and the .NET Framework in general, you can see that much of your existing skills will translate right over. If you are new to Silverlight, this book strives to help you get up to speed. However, consider reviewing an Introduction or Silverlight reference book for additional background information.

Tip

Check out Silverlight Recipes: A Problem-Solution Approach, Second Edition, co-authored by Jit Ghosh and me (Apress, 2010) for more on general Silverlight development.

For Windows Phone 7, Microsoft adds additional assemblies and namespaces related to phone specific functionality that I cover in this chapter and throughout this book:

  • Microsoft.Devices

  • Microsoft.Phone

  • Microsoft.Phone.Controls

  • Microsoft.Phone.Shell

These assemblies and namespaces identify a rich set of APIs available to developers in order to build powerful Silverlight for Windows Phone 7 mobile applications.

Next let's take a deeper look at Xml Application Markup Language (XAML) and how it relates to the .NET Framework for Silverlight.

XAML Overview

The .NET Framework 3.0 introduced XAML for Windows Presentation Foundation (WPF) and Windows Workflow Foundation (WF). WPF is of more interest to us since it is a desktop-based client development technology and has a lot in common with Silverlight. WPF was updated in .NET Framework 3.5, and available today in its latest incarnation in the .NET Framework 4.0.

Introduced in 2007, Silverlight is another client application technology that uses XAML to express UI. Recall from Chapter 1 that Silverlight is Microsoft's cross-browser, cross-platform browser plug-in that has rapidly evolved to have near parity with WPF in the latest version Silverlight 4.

With this rich heritage, there are a lot of great references available on Silverlight development, but it is important to provide fundamentals on the XAML language itself. As XAML is based on XML, it is hierarchical in nature, which lends itself to tooling because it is simple XML manipulation under the covers. Expression Blend 4 takes advantage of this by providing a GUI interface to XAML development that you will want to take advantage of when building animation storyboards and data binding.

Since this section is focused on XAML as a markup language, I explore the capabilities of XAML using Visual Studio 2010. We could just as easily explore XAML capabilities in Expression Blend 4. Expression Blend 4 includes syntax highlighting and IntelliSense as shown in Figure 2-11.

Expression Blend 4 syntax highlighting and IntelliSense

Figure 2.11. Expression Blend 4 syntax highlighting and IntelliSense

We will be looking at some C# code as well, so Visual Studio serves our purposes better in this section. But unlike with previous versions of Expression Blend, you don't have to leave Blend in order to hand-edit XAML with syntax Highlighting and IntelliSense support.

Importing a .NET Class into XAML

As you can see in Figure 2-11, the XAML markup for the XAMLBasics project includes several namespace imports using xmlns, including the xmlns:phone import that is used to declare the root element phone:PhoneApplicationPage. What may not be completely obvious at first glance is that PhoneApplicationPage is a class in the Microsoft.Phone.Controls namespace, contained in the Microsoft.Phone.dll assembly reference. Here is the xmlns import for the phone namespace:

xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

In the xmlns import above, you see the .NET namespace, Microsoft.Phone.Controls, and the assembly name, Microsoft.Phone. This corresponds to a using clause in .NET code:

using Microsoft.Phone.Controls

The point is that markup written in XAML corresponds to objects in C# code. For example, you can create a button in C# using the code Button btn = new Button(). In XAML, you create a button with this markup: <Button />. You can essentially consider XAML as a human editable serialization format for .NET Framework for Silverlight.

With this background in hand, you can deduce that making custom C# classes available within XAML is as simple as creating a xmlns namespace import, which is correct. One consideration is that for a .NET classes to be brought in to a XAML markup page, it must have a parameter-less constructor so that you can simply declare it as <foo /> in XAML without needing parameters in the constructor, which is not supported.

Programming XAML

With the appropriate namespaces in place, creating a user experience in XAML is simple XML editing with XML Elements and Attributes. Elements generally represent a class or object such as a Button declared as <Button />. To set properties on the Button, you can add XMLAttributes such as Height and Width : <Button Height="40" Width="100" />.

Some properties are of type System.Object or some other complex type, which could be difficult to set via an attribute depending on the value. The Button 's Content property is of type System.Object, which means that it can point to pretty much anything. For a Button 's Content property, it can be set as an attribute like so:

<Button Height="40" Width="100" Content="Hello Reader" />

For a not so simple type, The Button.Content property can be set using XML property element syntax:

<Button>
    <Button.Content>
        <MediaElement />
    </Button.Content>
</Button>

Remember that the Button.Content property is of type System.Object, so you could actually play a video as the "content" of a Button object via a MediaElement. With property element syntax, more complex objects such as a MediaElement playing a video named video1.wmv can be set as the value for the Content:

<Button>
    <Button.Content>
        <MediaElement Source="video1.wmv" />
    </Button.Content>
</Button>

Other properties can be set to an enumerated type such as a System.Windows.Media.Color value configured on a Brush type such as a SolidColorBrush object. In the example below, how does XAML know what do to with the text value "Blue" in this example?

<Button Background="Blue" />

Intuitively, the developer understands what this means, however, there is a little bit of magic to support this simplified syntax. In the XAML above, the text "Blue" is converted to a System.Windows.Media.Color value via a built in System.ComponentModel.TypeConverter for the Brush type. Without the type converter, the full property element syntax is required:

<Button>
  <Button.Background>
    <SolidColorBrush Color = "Blue" />
  </Button.Background>
</Button>

TypeConverter objects are intrinsic to straightforward XAML programming. Developers can create their own custom TypeConverter objects to simplify data binding between two XAML objects with two different types allowing the developer to avoid cluttering event handlers in the code-behind file for a XAML page.

The last XAML concept I will cover in this overview is markup extensions. Markup extensions are similar to type converters in that they allow for more straightforward XAML development. Markup extensions allow a string value to be converted into a configured object, which can greatly reduce the amount of XAML that must either be hand-written or generated by a tool.

In order to identify and parse a markup extension, since it is configured as attribute property text, a special syntax is required that uses curly braces: attribute="{ extension goes here}". The curly braces tell the XAML parser that a markup extension is inbound for parsing.

The two most common markup extensions are used for specifying a resource for an object property or attribute value and for configuring data binding for an object property or attribute value. Listing 2-5 shows the MainPage.xaml file for the XAMLBasics project where you can see Style attributes configured using the markup extension syntax:.

<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION"
   Style="{StaticResource PhoneTextNormalStyle}"/>

Example 2.5. XamlBasics MainPage.xaml File

<phone:PhoneApplicationPage
    x:Class="XAMLBasics.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
  <phone:PhoneApplicationPage.Resources>
    <Style x:Key="TestTextBlockStyle" TargetType="TextBlock">
      <Setter Property="Foreground" Value="#FFD49696"/>
      <Setter Property="FontSize" Value="16"/>
    </Style>
  </phone:PhoneApplicationPage.Resources>

  <!--LayoutRoot is the root grid where all page content is placed-->
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
      <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION"
                       Style="{StaticResource PhoneTextNormalStyle}"/>
      <TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0"
                       Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>


    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" >
      <TextBox Height="72" HorizontalAlignment="Left" Margin="12,66,0,0"
       Name="textBoxOriginal" Text="Original" VerticalAlignment="Top"
       Width="374" />
      <TextBlock Height="30" Margin="35,185,0,0" Name="textBlock1"
       Text="{Binding Text, ElementName=textBoxOriginal}"
       VerticalAlignment="Top" Width="374"
       Style="{StaticResource TestTextBlockStyle}" />
      <TextBox Height="72" HorizontalAlignment="Left" Margin="12,280,0,0"
        Text="{Binding Text, ElementName=textBoxOriginal, Mode=TwoWay}"
        VerticalAlignment="Top" Width="374" Name="textBox2" />
    </Grid>
  </Grid>
</phone:PhoneApplicationPage>

<Button Style="{StaticResource CustomButtonStyle}" />

The next question is where is CustomButtonStyle defined? It can be defined either in App.xaml or the current XAML page in the Resources collection like this:

<phone:PhoneApplicationPage.Resources>
    <Style x:Key="CustomButtonResource" TargetType="Button" >
        <Setter Property="Margin" Value="20,20,0,0" />
    </Style>
</phone:PhoneApplicationPage.Resources>

Figure 2-12 shows the UI in the emulator for the XamlBasics project.

XAML Basics UI

Figure 2.12. XAML Basics UI

The UI is pretty simple, but it helps me explain the concept of markup extensions for resources and data binding. The TextBlock has a style resource applied to it via a markup extension that makes the text very small and a reddish color. Here is the style resource wrapped in the PhoneApplicationPage.Resources element from Listing 2-1:

<phone:PhoneApplicationPage.Resources>
  <Style x:Key="TestTextBlockStyle" TargetType="TextBlock">
    <Setter Property="Foreground" Value="#FFD49696"/>
    <Setter Property="FontSize" Value="16"/>
  </Style>
</phone:PhoneApplicationPage.Resources>

The style is named TestTextBlockStyle via the x:Key attribute. The style is applied to the TextBock via the StaticResource markup extension as shown here:

<TextBlock Height="30" Margin="32,187,50,0" Name="textBlock1" ....
Style="{StaticResource TestTextBlockStyle}" />

This syntax applies to all types of resources, not just element styles. It allows for consistent UX by sharing resources across an application. Resources can be stored at the Page level or the Application level in App.xaml. Resources can also be stored in external files in Resource Dictionaries. I explore the StaticResource markup extension further when I cover Expression Blend later in this chapter, but for now this section provides solid background to help you understand how to program in XAML with resources.

Let's now move on to an overview of the data binding markup extension with Element Data binding. Element data binding allows one control's property to data bind to another control's property value. The stylized TextBlock and the TextBox below it in Figure 2-1 databind to the first TextBox via element data binding. Run the project and enter text in the first TextBox, notice the other two change values as you type.

Tip

If you would like to use your keyboard when typing in the emulator, click the "pause" button on your physical keyboard. This allows the emulator OS to capture the physical keyboard and can save a lot of time typing. Exit the element and click "pause" again to switch back to the soft key keyboard within the emulator.

Element Data binding is a powerful concept, but at its simplest level it saves the developer from writing simple event handlers that do nothing but copy values from one control to another. How this works is that when you type in the first TextBox on the screen shown in Figure 2-12, the reddish text TextBlock and the TextBox below it get the same value automatically via Element Data binding. Here is the XAML for the TextBlock that uses the Binding markup extension to element databind:

<TextBlock Height="30" Margin="32,187,50,0" Name="textBlock1"
  Text="{Binding Text, ElementName=textBoxOriginal}"
  VerticalAlignment="Top" Width="374"
  Style="{StaticResource TestTextBlockStyle}" />

The Binding markup extension first identifies the target property that the property is binding to, in this case TextBlock.Text is binding to TextBox.Text. The ElementName attribute value within the Binding markup extension specifies textBoxOriginal.Text as the target control/property that textBlock1.Text is databound to by default as one-way or read-only data binding.

The third control on the page in Figure 2-12, the TextBox, also databinds to the first TextBox as shown here:

<TextBox Height="72" HorizontalAlignment="Left" Margin="12,280,0,0"
  Text="{Binding Text, ElementName=textBoxOriginal, Mode=TwoWay}"
  VerticalAlignment="Top" Width="374" Name="textBox2" />

The Binding markup extension for the textBox2 TextBox looks very similar to the TextBlock's Binding, except that it also specifies Mode=TwoWay in the Binding markup extension. This means that if you type a value in the third TextBox named textBox2, the same value propagates back to the original TextBox named textBoxOriginal, which then updates the TextBlock's value via one-way Element data binding.

Data binding in XAML is an incredibly powerful construct that extends beyond Element data binding to object data binding via collections of data retrieved from a server via web service calls. I explore data binding further in a later section in this chapter on Expression Blend.

Combining TypeConverters with Element Data binding can provide a powerful XAML construct that avoids writing what would normally be a lot of boilerplate code. As an example, you could Element Databind a TextBlock to the Position property of a MediaElement that is playing either an audio or video segment. There is a type mismatch between the TextBlock.Text property's type of String and the MediaElement.Position property's type of TimeSpan. You can get around this by writing a simple event handler that manually converts from a TimeSpan value to a String value. A more elegant way to handle this is to create a simple ValueConverter that is applied as part of the Element Data binding markup extension. TypeConverter objects are used by the XAML parser at compile time; however, ValueConverter objects apply at runtime for converting values when data binding. I cover ValueConverters in detail in Chapter 6.

This section concludes the XAML overview. The next section dives into the class model available within Silverlight for Windows Phone and is the underlying objects behind the XAML markup.

Key Silverlight UI Base Classes

Silverlight for Windows Phone is similar to Silverlight for the desktop and traces its roots back to Windows Presentation Foundation. As such it has a similar control tree to support functionality endemic to XAML UIs such as data binding, styling, and animation to name a few.

As with all of.NET, the root base class is Object. Next in line from Object is DependencyObject, which you will find in Windows Presentation Foundation (WPF) and Silverlight. DependencyObject provides dependency property system services to derived classes. The D ependencyObject includes the concept of dependency properties to enable automatic data binding, animation, and styling. Dependency Properties support three major functions over standard .NET properties: Change notification, Property value inheritance, and value providers.

The UIElement class inherits from the DependencyObject class and serves as the base class for most objects that have visual appearance and that can process basic input. Example properties and events are Visibility, Opacity, Clip, GotFocus, KeyDown, and MouseLeftButtonDown, etc. Check out the MSDN documentation for a full list of properties and methods:

http://msdn.microsoft.com/en-us/library/system.windows.uielement(v=VS.95).aspx

The FrameworkElement class is the common base class for System.Windows.Shapes namespace classes like Shape, Ellipse, and Rectangle and System.Windows.Controls namespace classes like Control, Button, and TextBox. FrameworkElement implements layout, data binding, and the visual object tree functionality. Properties and events implemented in FrameworkElement include Margin, Padding, Height, Width, SizeChanged, and LayoutUpdated. The next section covers graphic primitives followed by an overview on controls.Check out the MSDN documentation for a full list of properties and methods:

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement(v=VS.95).aspx

Graphics Primitives

Silverlight for Windows Phone supports 2D graphics primitives such as rectangles, ellipses, lines, and paths. Generally these objects have been used in Silverlight to build up images, separate UI areas, as well as incorporated within controls. One of the key reasons to use XAML primitives is to take advantage of the infinite scaling capabilities of vector-based graphics.

On Windows Phone 7, UI design is all about the content, not UI "chrome" – so you won't see a heavy use of UI control chrome in most applications. Where graphics primitives can be useful on Windows Phone 7 is in game development when you need to draw game scenes for 2D game development.

For game development, vector graphics primitives or raster images can be used to draw the scene – so which one should you use? Vector-based graphics require a level of CPU processing to convert from a vector to raster format so that the GPU can render the scene. Therefore, wherever possible, it is recommended to use a raster format like .png files to avoid the additional format conversation, saving battery. Given the fixed screen size of a mobile device, little fidelity is lost by sing raster graphics.

I cover the graphics primitives in more detail with a sample application called GraphicsPrimitives in the Chapter 2 Solution. Figure 2-13 shows the UI.

Graphics Primitives UI

Figure 2.13. Graphics Primitives UI

Listing 2-6 shows the XAML markup for the GraphicsPrimitives project.

Example 2.6. GraphicsPrimitives MainPage.xaml File

<phone:PhoneApplicationPage
    x:Class="GraphicsPrimitives.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

  <!--LayoutRoot is the root grid where all page content is placed-->
  <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
</Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
      <TextBlock x:Name="ApplicationTitle" Text="Chapter 2"
        Style="{StaticResource PhoneTextNormalStyle}"/>
      <TextBlock x:Name="PageTitle" Text="graphics primitives"
         Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
      <Ellipse Height="146" HorizontalAlignment="Left" Margin="12,28,0,0"
         x:Name="ellipse" Stroke="White" StrokeThickness="3"
         VerticalAlignment="Top" Width="176" />
      <Rectangle x:Name="Rectangle" Fill="LightGray" HorizontalAlignment="Left"
         Margin="12,200,0,227" Stroke="White" Width="145"/>
<Image HorizontalAlignment="Left" Margin="21,213,0,0"
         x:Name="image1" VerticalAlignment="Top"
         Source="images/bookcover.jpg" Stretch="None" />
<Path x:Name="Line" Data="M245,28 L404,200" Fill="#FFF4F4F5"
         HorizontalAlignment="Right" Height="173" Margin="0,28,51,0"
         Stretch="Fill" UseLayoutRounding="False" VerticalAlignment="Top"
         Width="160" Stroke="White" StrokeThickness="5" />
      <Path Data="M406,307 L244,306 L239,187" Fill="White"
         HorizontalAlignment="Right" Margin="0,200,49.5,227" Width="161.5"
         Stretch="Fill" Stroke="White" UseLayoutRounding="False" Name="Pen" />
      <Path x:Name="pencil"   Height="55" Margin="24,0,19,93.143"
          Stretch="Fill" Stroke="White" UseLayoutRounding="False"
          VerticalAlignment="Bottom" Data="M31,396 C36.294918,415.62234 34.544609,412.77231
GraphicsPrimitives MainPage.xaml File
57,424 C67.599434,429.29971 74.964737,436.59296 87,439 C91.685699,439.93713 97.165527,439 102,439 C131.96695,439 133.0285,434.60718 158,419 C181.28416,404.44739 192.78926,421.84195 221,443 C236.51602,454.63702 255.19547,455.07272 274,430 C290.42596,408.09872 279.30313,393.7677
GraphicsPrimitives MainPage.xaml File
319,407 C334.2662,412.08875 343.0755,439.55231 359,441 C369.82889,441.98444 372.32379,433.58371
GraphicsPrimitives MainPage.xaml File
379,425 C383.57141,419.12247 397.35007,414.1167 406,417 C419.57794,421.52597 422,469.74692 422,412 C428.6496,413.32993 435.72543,412.92343 443,413"/> <Canvas Height="104" HorizontalAlignment="Left" Margin="6,495,0,0" Name="canvas1" VerticalAlignment="Top" Width="444"> <Ellipse Canvas.Left="75" Canvas.Top="24" Height="60" x:Name="ellipseCanvas1" StrokeThickness="1" Width="76" Stroke="White" /> <Ellipse Canvas.Left="290" Canvas.Top="24" Height="60" x:Name="ellipseCanvas2" StrokeThickness="1" Width="76" Stroke="White" /> </Canvas> </Grid> </Grid> </phone:PhoneApplicationPage>

The Ellipse and Rectangle controls are pretty straightforward except that, as a developer, you might be wondering what is setting the top and left values for the Ellipse and Rectangle objects at the top. How are they positioned?

<Ellipse Height="146" HorizontalAlignment="Left" Margin="12,28,0,0"
    x:Name="ellipse" Stroke="White" StrokeThickness="3"
    VerticalAlignment="Top" Width="176" />
<Rectangle x:Name="Rectangle" Fill="LightGray" HorizontalAlignment="Left"
    Margin="12,200,0,227" Stroke="White" Width="145"/>

Since I mentioned game development earlier, it is worth spending a little bit of time on the layout system. Silverlight includes a layout system as part of the rendering engine that places objects based on the Margin property for the Grid and StackPanel layout controls. The Margin property takes four values representing the distance from the Left, Top, Right, and Bottom sides of the containing control, in this case the ContentPanelGrid object. Notice that just the first two values are configured for the Ellipse. If the other values are not set, the Width and Height values determine sizing for the object.

For game development, it would be odd to draw game scenes using just Margin values to place game sprites or images. Silverlight includes another layout control, the Canvas object, which allows the developer to set Top and Left directly on the object. This may seem strange because graphics primitives and even controls do not include a Top or Left property. Check the Properties Tool window in Visual Studio 2010 for any object to confirm.

We added a Canvas at the bottom of the Grid and place two Ellipse objects in it. Here is the markup for the Ellipse objects.

<Canvas Height="104" HorizontalAlignment="Left" Margin="6,495,0,0" Name="canvas1"
        VerticalAlignment="Top" Width="444">
  <Ellipse Canvas.Left="75" Canvas.Top="24" Height="60"
      x:Name="ellipseCanvas1" StrokeThickness="1" Width="76" Stroke="White" />
  <Ellipse Canvas.Left="290" Canvas.Top="24" Height="60"
      x:Name="ellipseCanvas2" StrokeThickness="1" Width="76" Stroke="White" />
</Canvas>

The Ellipse objects are placed using Attached Property syntax, i.e., Canvas.Top and Canvas.Width properties. Attached properties are a special dependency property that allows the attached property to be configured on and apply to a contained object in the XAML tree. I cover attached properties in the next section, but they provide a powerful extensibility mechanism without having to create custom objects. Given that Silverlight objects tend to have many more properties then their Windows Forms counterparts already, attached properties allows controls to take advantage of additional properties without having to actually declare them in every object

The last item I'll cover here are the two <Path /> objects named Pen and Pencil. The controls have those named because that is the tool I used to draw them in Expression Blend. I cover Expression Blend later in this chapter. The Path objects include a Data property that is set to what looks like a code.

The Data property is set to a value that follows the syntax of the Path Mini-Language. The Path Mini-Language has a similar syntax as the Scalable Vector Graphics (SVG) markup Path object. Please refer to a SVG reference for more info on the syntax if interested. Otherwise, use Expression Blend to visually draw objects without worrying about the underlying Data value generated for the Path object.

The other object that is part of the GraphicsPrimitives project is the Image object. It takes an image file such as a .png as the value for its Source property. It can be configured to stretch and scale an image by setting the Stretch property to Fill or UniformttoFill. The Image object is the most common graphics primitive a developer will work with. I cover working with the Image object in detail in Chapter 6.

This wraps up the overview of the .NET Framework for Silverlight and XAML. Now let's dive into the details on controls.

Controls

Silverlight for Windows Phone 7 includes a rich set of controls that are already templated with the Metro theme" by default. Figure 2-14 shows a quick search of controls available on my laptop.

Avaialble controls on the author's laptop

Figure 2.14. Avaialble controls on the author's laptop

Some of the controls are "sub" controls that are generally associated with a primary control. As an example, the ListBoxItem control always sits within a ListBox control. The ZoomBox control is part of the Bing Maps Map control, etc. Still, as you can see, there are a rich set of controls available for Windows Phone 7 developers.

Note

I cover the additional controls available in the Silverlight for Windows Phone Toolkit in Chapter 5.

The Chapter 2 solution in the code download has a project named BuiltInControls to demonstrate a few of the controls that ship with the Windows Phone Developer Tools. One control in Figure 2-4 that may not be on your system is the SmoothStreamingMediaElement control. This control plays media like the built-in MediaElement, but it also supports IIS Smooth Streaming adaptive streaming technology, which allows you to chunk up a media stream to different sizes depending on available bandwidth conditions. Smooth Streaming is especially important on mobile devices where bandwidth can vary greatly by optimizing the user experience for available conditions. You can learn more about Smooth Streaming at IIS.net. I cover media playback in Chapter 6.

There's an additional control available as part of the Microsoft Advertising SDK for Windows Phone 7. You can download it here:

www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=b0f00afc-9709-4cc2–ba2c-57728db6cbd6

The download installs the control and API documentation here:

C:Program Files (x86)Microsoft Advertising SDK for Windows Phone 7

All that's needed is to add a reference to the control and a few lines of code to generate revenue from your free applications. I cover how to integrate advertising into your application in Chapter 6. Other controls shown in Figure 2-14 are pulled in by the Silverlight for Windows Phone 7 Toolkit, which is covered below in Chapter 5.

User Interface Development with Expression Blend 4

In this section we build on the introduction to Expression Blend 4 for Windows Phone provided in Chapter 1 by delving into key concepts such as the layout system, sample data, data binding, and control templates. I provide coverage of the Silverlight for Windows Phone 7 Toolkit and then return to an overview of the Panorama and Pivot controls.

Layout System

The Silverlight for Windows Phone 7 layout system is based on the desktop Silverlight layout system, so it behaves in a similar manner. The Silverlight layout system enables dynamic positioning of vector-based UI elements using device-independent units or pixels that default to 96 units per inch, regardless of display resolution.

For example, if you set a rectangle to be 96 units high and 96 units wide in Visual Studio 2010 or Expression Blend 4, the rectangle will be one-inch square by default, because the Windows Phone default is 96 dpi.

The Silverlight for Windows Phone layout system includes containers that manage the size and position of controls placed within the container. UI elements are placed into one of three primary containers that inherit from the Panel base class:

  • Canvas: Defines an area within which you can explicitly position child elements by coordinates relative to the Canvas area.

  • StackPanel: Arranges child elements into a single line that can be oriented horizontally or vertically.

  • Grid: Defines an area containing rows and columns where elements can be placed.

I cover the container controls over the next few sections, but first let's look at the layout system in more detail. This is a critically important topic when laying out UI. The layout system is a recursive operation that first sizes, then positions, and finally draws elements onscreen.

The layout system is a two-pass system that is applied starting at the top of the visual XAML tree and then works its way through the Children collection of each control. During the Measure pass, the desired size of each child element is determined. In the Arrange pass, each child element's size and position are finalized.

Two closely related properties with respect to layout are Margin and Padding. Whereas all FrameworkElements have the Margin property, only objects that inherit from Control and the BorderFrameworkElement have a Padding property. The difference is that Margin defines the extra space placed around the outside edges of the element, and Padding defines the extra spaced placed around the inside edges of the control.

You can use Margin and Padding to force mandatory separation between controls; it is applied by the layout system as the UI is resized, either programmatically or as the user resizes the browser.

Values for Margin and Padding can be specified using three notations: a unique value for each edge, such as "1,2,3,4"; two numbers, such as "3,5", which applies 3 for the left and right and 5 for the top and bottom; or a single value such as "4." If you set the property to a single value, that Margin or Padding will be applied to the left, top, right, and bottom edges of the control. If you set each edge explicitly to "1,2,3,4", the order applied is left, top, right, bottom.

Canvas

The Canvas object may feel most comfortable to developers who are not familiar with WPF or Silverlight and have built UIs in technologies similar to .NET Windows Forms. The Canvas container enables absolute positioning of UI elements – very similar to Windows Forms or other layout technologies.

StackPanel

The StackPanel arranges controls side-by-side, either vertically or horizontally, via the Orientation property, taking into account the configured Margin and Padding for each control nested within the StackPanel control.

Grid

The Grid control is similar to an HTML table in laying out controls. It supports multiple rows and columns in the RowDefinitions and ColumnDefinitions collections. By default, if a control is nested inside a Grid without any rows or columns defined, the control renders in the upperleft-hand corner, which represents row zero and column zero.

When you define columns and rows on a Grid, you can specify the Width in the ColumnDefinition object for a column and the Height in the RowDefinitions object for a row in pixels. You can also leave Width and Height set at their default value of Auto or specify Auto explicitly for each.

Leaving Width and Height set to Auto causes the Grid to size rows and columns equally as much as possible; however, the ultimate size is determined by the layout system, which takes into account the size of the content. For example, if a Grid has two rows defined with the default of Auto, but the content in the first row has a minimum size that is twice that of the content in the second row, the layout system causes the first row to be twice the width of the second.

The Grid supports a much more powerful method of sizing columns and rows: star sizing. When you specify a star (*) as the Width or Height of a column or row, the column or row receives a proportional amount of space relative to the other columns or rows, respectively. This XAML has the same effect as setting Width and Height to the default of Auto:

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

It gets interesting when you prepend an integer to * for Width or Height. For example, to give up to twice the amount of available space to the second column and second row, specify 2* for both the Width and Height, like this:

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

Note that I said "up to twice the amount." That is because the layout system takes into account the minimum size required for content. If the second column wants twice as much space as the first column, the content in the first column may prevent the second column from getting all the requested space, depending on the minimum width values configured on the content in the first column.

Layout Controls Sample and Blend Behaviors

The project LayoutControls in the Chapter 2 solution demonstrates how the Canvas, StackPanel, and Grid layout controls work. Since this section is focused on Expression Blend, I introduce a new concept called Behaviors to provide navigation without writing any C# code.

Behaviors Overview

WPF introduced the concept of Triggers, which allowed actions to happen such as starting an animation StoryBoard object by clicking a button without writing any C# code. Behaviors were introduced in Silverlight 3 and take the concept of Triggers even further while including full Expression Blend support with drag-and-drop support to apply behaviors.

Behaviors allow developers to add logic to a control visually in Blend. You can think of them as code-less events or actions meaning no C# code is needed to utilize a Behavior. To find behaviors in Expression Blend, click on the Assets tab and select Behaviors to filter to the list of items. Figure 2-15 shows a list of available behaviors.

Expression Blend built-in behaviors

Figure 2.15. Expression Blend built-in behaviors

Additional Silverlight behaviors can be found at the Expression Blend Gallery located here:

http://gallery.expression.microsoft.com/en-us/site/search

For the LayoutControls sample project, three TextBlock controls are put into the UI of MainPage. xaml with text of Canvas, StackPanel, and Grid, respectively. Three pages are added to the project named CanvasPage.xaml, StackPanelPage.xaml, and GridPage.xaml. Switch back to MainPage. xaml to drag-and-drop a NavigateToPageAction behavior onto the TextBlock with the text Canvas.Figure 2-16 shows the Properties window for the behavior. The EventName property indicates the event to kick off the action, in this case touching the label will navigate to the page configured for the TargetPage property.

NavigateToPageAction behavior configuration

Figure 2.16. NavigateToPageAction behavior configuration

Without writing any code, when the CanvasTextBlock is touched, the MouseLeftButtonDown event fires and the PhoneApplicationFrame will navigate to the TargetPage of CanvastPage.xaml. We do the same for the other two labels so that they navigate to the StackPanelPage.xaml and GridPage.xaml pages respectively. Here is a snippet of the XAML added to the Canvas textbox as a result of dragging-and-dropping the behavior:

<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Canvas"
NavigateToPageAction behavior configuration
VerticalAlignment="Top" Margin="12,43,0,0"> <Custom:Interaction.Triggers> <Custom:EventTrigger EventName="MouseLeftButtonDown"> <ic:NavigateToPageAction TargetPage="/CanvasPage.xaml"/> </Custom:EventTrigger> </Custom:Interaction.Triggers> </TextBlock>

Under the hood, behaviors are just XAML markup programmed visually with Expression Blend. The navigation actions do not include animations but this quick demo touches upon just the beginning of what Silverlight Behaviors can offer in terms of simplifying code with standardized behaviors and actions. Chapter 5 covers how to add animations to page transitions.

Layout Controls

Now that the navigation has been visually programmed with Behaviors, it is time to add the layout controls starting with the Canvas control to CanvasPage.xaml. By default the Canvas control is not listed in the Asset Bar. As covered in Chapter 1, click and hold the chevron at the bottom of the Asset Bar on the left to pop-out the search UI, or click and hold on the Grid icon in the Asset Bar and the UI to switch to Canvas is presented.

Double-click on Canvas to add it to the CanvasPage.xaml UI. Type Shift-V to go back to Selection mode and then right-click on the Canvas and select Auto-Size

Layout Controls

Move the Ellipse to about the middle of the ContentPanelGrid 's area. Notice that the Margin value did not change as what is normally the case when objects are placed within a Grid layout control. Because the Ellipse is within a Canvas layout control, objects are absolutely positioned using Canvas.Left and Canvas.Top attached properties instead of via Margin. Here is the XAML for the ellipse:

<Ellipse Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100" Canvas.Left="176"
Layout Controls
Canvas.Top="279"/>

The Canvas layout control operates differently with respect to the Silverlight Layout system. Controls are absolutely positioned within a Canvas, making it the ideal layout control for Silverlight-based game development. Developers can apply Margin to controls within a Canvas but the Margin is applied relative to the Canvas.Top and Canvas.Left properties, not to the bounds of the Canvas, which is different behavior compared to a Grid.

Grid Page

For GridPage.xaml, we don't add an additional Grid, because there is already a Grid control named ContentPanel by default when adding a new page to the project. Click and hold the Rectangle to switch to Ellipse, and double-click as before to add the Ellipse to the Grid. By default it is placed in Grid.Row = 0 and Grid.Column=0. Initially the ContentPanel does not have any additional Rows or Columns so let's add a couple visually to make a tic-tac-toe type grid layout as shown in Figure 2-17.

GridPage.xaml at desig time

Figure 2.17. GridPage.xaml at desig time

The Ellipse is placed in the center position in the Grid control resulting in this Xaml:

<Ellipse Fill="#FFF4F4F5" Stroke="Black" Grid.Column="1" Grid.Row="1" Width="100"
GridPage.xaml at desig time
Height="100"/>

We see two additional attached properties used to position the Ellipse within the Grid Control: Grid.Column and Grid.Row.

StackPanel Page

Double-click on StackPanel to add it to the StackPanelPage.xaml UI. Press Shift-V to go back to Selection mode, and then right-click on the StackPanel and select Auto-Size

StackPanel Page

The StackPanel control does not support absolute positioning like the Canvas. Developers can use Margin and Padding to adjust the display within the StackPanel. Remove two of the six Ellipses so that four are stacked. Multi-select the remaining four Ellipse controls and then set the Top and Bottom Margin values to 10. This results in the Ellipses separating from each other a bit but still within the behavior of the StackPanel.

Now set a Width on all four Ellipse controls of 100 pixels to remove the stretch. By default, we now have four circles stacked and spaced. Finally, add a 100 Left Margin to the second Ellipse and 100 Right Margin to the third Ellipse resulting in Figure 2-18.

StackPanel.xaml at design time

Figure 2.18. StackPanel.xaml at design time

Layout Tips

The layout controls provide an immense amount of flexibility within the layout system. Developers should use the controls to lay out UI as much as possible initially. As an example, use a Grid with Rows and Columns to separate UI first. For items that are lined up either horizontally or vertically, use a StackPanel. Adjust HorizontalAlignment and VerticalAlignment as needed.

Once the general layout is in place, Apply Margin and Padding as needed to space controls within containers. Resist the temptation to set Width and Height on every control initially. Width and Height override all other layout configurations and can result in odd layout behavior where controls appear to be cut off. Only set Width or Height when needed to ensure correct display of content.

With all that said, the Silverlight Layout System takes CPU cycles to determine positioning. In most cases following the above recommendations works fine and provides maximum flexibility with great performance. Only in cases when frame rates are dropping should a developer consider absolute positioning to reduce layout calculations and even then the gains may be marginal. In the next section, I shift gears over to another major topic in XAML development: data binding.

Data Binding

Support for data binding is engineered directly into XAML-based programming languages like WPF and Silverlight. This means most properties are of type DependencyProperty, which includes built-in support for change notifications and data binding. It would be nearly impossible to cover Silverlight user experience without also covering data binding. There are three main categories for data binding:

  • Element data binding

  • Object data binding

  • XML data binding

Silverlight for Windows Phone 7 includes full data binding support comparable to what is related in Silverlight 3. In order to create sample code, some demo live data is needed. The next section covers the DemoLiveData project available in the Chapter 2 solution.

Demo Live Data

In addition a separate project named DemoLiveData is available to provide an object collection and an xml data file to work with for the rest of this chapter. The project contains two simple classes, a Customer class and a Customers class to serve as the live data. Listings 2-7 and 2-8 show the Customer and Customers classes.

Example 2.7. Customer.cs Code File

namespace SampleData.LiveData
{
  public class Customer
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
  }
}

Example 2.8. Customers.cs Code File

using System.Collections.Generic;

namespace SampleData.LiveData
{
  public class Customers
  {
    private List<Customer> _customerList;

    public Customers()
    {
      _customerList = new List<Customer>()
      {
        new Customer(){FirstName="Rob",LastName="Cameron",PhoneNumber="555-555-5555",
                        Address="123 Main Street", City="Atlanta",State="GA", Zip="30042"},
        new Customer(){FirstName="Amanda",LastName="Cam",PhoneNumber="555-555-5555",
                        Address="123 Main Street", City="Philadephia",State="PA",
Customers.cs Code File
Zip="19111"}, new Customer(){FirstName="Anna",LastName="Ron",PhoneNumber="555-555-5555", Address="123 Main Street", City="New York",State="NY", Zip="10001"},
new Customer(){FirstName="John",LastName="Smith",PhoneNumber="555-555-5555",
                        Address="123 Main Street", City="Chicago",State="IL", Zip="20011"},
        new Customer(){FirstName="Jane",LastName="Doe",PhoneNumber="555-555-5555",
                        Address="123 Main Street", City="San Francisco",State="CA",
Customers.cs Code File
Zip="30333"}, new Customer(){FirstName="Daniel",LastName="Booth",PhoneNumber="555-555-5555", Address="123 Main Street", City="Dallas",State="TX", Zip="79999"}, new Customer(){FirstName="Arthur",LastName="Olson",PhoneNumber="555-555-5555", Address="123 Main Street", City="Seattle",State="WA", Zip="50000"}, new Customer(){FirstName="Janet",LastName="Rich",PhoneNumber="555-555-5555", Address="123 Main Street", City="Portland",State="OR", Zip="43334"}, new Customer(){FirstName="Janus",LastName="Poor",PhoneNumber="555-555-5555", Address="123 Main Street", City="Sacramento",State="CA", Zip="85755"}, new Customer(){FirstName="Alice",LastName="Mer",PhoneNumber="555-555-5555", Address="123 Main Street", City="Kansas City",State="KA", Zip="48488"} }; } public List<Customer> CustomerList { get { return _customerList; } } } }

To instantiate the data, simply create the Customers class and data bind to the CustomerList. The XML file named ApressBooks.xml lists details on about 20 books that have been published by Apress over the years. I won't list the full XML file, but here is a summary of the schema with one of the sample book data present:

<ApressBook>
   <ID>4</ID>
   <ISBN>1-4302-2435-5</ISBN>
   <Author>Jit Ghosh and Rob Cameron</Author>
   <Title>Silverlight Recipes: A Problem-Solution Approach, Second Edition</Title>
     <Description>Silverlight Recipes: A Problem-Solution Approach, Second Edition is your
Customers.cs Code File
practical companion to developing rich, interactive web applications with Microsoft's
Customers.cs Code File
latest technology. This book tackles common problems and scenarios that on-the-job
Customers.cs Code File
developers face every day by revealing code and detailed solutions. You'll quickly be able
Customers.cs Code File
to integrate real-world, functioning code into your applications—and save hours of coding
Customers.cs Code File
time.</Description> <DatePublished>2010-07-15T00:00:00</DatePublished> <NumPages>1056</NumPages> <Price>$49.99</Price> </ApressBook>

The next three sections cover the scenarios listed previously and demonstrated in the Chapter 2 solution. That includes a project named Data Binding, which includes a MainPage.xaml and a folder named pages that includes three pages to cover each topic that follows.

Element Data Binding

Element data binding is when a property on one control data binds to the value of a property on another control. To demonstrate this, we add a Rectangle and a Slider control to the page named ElementDataBindingPage.xaml with the Rectangle on the left and the Slider control oriented vertically.

The experience we want to create is that when the Slider is positioned, the Opacity on the Rectangle is modified. The Slider has a MinimumValue of zero and MaximumValue of one, with a default of one. The LargeChange property is changed to .1 and the SmallChange property is changed to .01 to keep the value consistent with what are valid values for the Opacity property.

What we want to do is data bind the Rectangle'sOpacity value to the Value property of the Slider. To do this, select the Rectangle object and click the small button to the right of the field in the Properties Window to bring up the menu shown in Figure 2-19 to select the Element Property Binding... menu item.

Expanded menu options for the Opacity property

Figure 2.19. Expanded menu options for the Opacity property

The menu shown in Figure 2-19 is mostly the same for any Property selected for a control. When Element Property Binding... is clicked, the Artboard switches to Element Property Binding mode, allowing the developer to select a control to then choose a property. Figure 2-20 shows the UI. Notice that it indicates that the Slider control will be given a name of slider. This is because the control must be named for Element Binding to work.

Element Binding mode with mouse over the slider

Figure 2.20. Element Binding mode with mouse over the slider

Once the Slider control is clicked, it is named slider and you can select the property to bind to as shown in Figure 2-21.

Element Binding – Create Binding dialog

Figure 2.21. Element Binding – Create Binding dialog

The Slider.Value property is the desired property so click OK to create the element binding. The XAMLor the Rectangle is updated to include element binding for the Opacity value as shown here:

<Rectangle Fill="#FF0000E0" Height="134" Margin="30,44,0,0" Stroke="Black"
Element Binding – Create Binding dialog
VerticalAlignment="Top" HorizontalAlignment="Left" Width="188" Opacity="{Binding Value, ElementName=slider}"/>

The Binding markup extension indicates that the Opacity property for the Rectangle should get its value from the UI element named "slider." Markup extensions are identified by the braces within the quotes as covered above in the XAML overview. Binding is a class in the .NET Framework for Silverlight that connects the property, in this case Opacity, to the data source, in this case the Value property on the Slider control.

Object Data Binding

Data binding to collection of objects is a very typical scenario. Silverlight for Windows Phone 7 has rich support for data binding to object collections, as is the case with Silverlight. We continue to customize the DataBinding project by adding a ListBox onto the ObjectDataBindingPage.xaml ContentPanel Grid. Add a reference to the DemoLiveData project to provide an object data source.

In Expression Blend, right-click on the ListBox and select the "Data bind ItemSource to Data..." menu item. Click the "+CLR Object" button in the Create Data Binding dialog shown in Figure 2-22.

Create Data Binding dialog

Figure 2.22. Create Data Binding dialog

This brings up the Create Object Data Source dialog shown in Figure 2-23, where we select SampleData.LiveData.Customers and click OK.

Create Object Data Source dialog

Figure 2.23. Create Object Data Source dialog

This returns us back to the Create Data Binding dialog with an object data source pointing to the custom object collection. Select the CustomerList Field to data bind it to the ItemSource as shown in Figure 2-24 and click OK.

Create Data Binding with Object data source

Figure 2.24. Create Data Binding with Object data source

Figure 2-25 shows the ListBox now data bound to the object data source.

Data-bound ListBox

Figure 2.25. Data-bound ListBox

In Figure 2-25, the data source is configured but it just displays the ToString() value for the Customer object, which defaults to the full type name. This is because an ItemTemplate is not configured on the ListBox. The ItemTemplate is used to layout the individual Customer records. Listing 2-9

Example 2.9. ObjectDataBindingPage.xaml Code File

<phone:PhoneApplicationPage
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:SampleData_LiveData="clr-namespace:SampleData.LiveData;assembly=DemoLiveData"
    x:Class="DataBinding.ObjectDataBindingPage"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    shell:SystemTray.IsVisible="True">
<phone:PhoneApplicationPage.Resources>
    <SampleData_LiveData:Customers x:Key="CustomersDataSource" d:IsDataSource="True"/>
  </phone:PhoneApplicationPage.Resources>

  <phone:PhoneApplicationPage.FontFamily>
    <StaticResource ResourceKey="PhoneFontFamilyNormal"/>
  </phone:PhoneApplicationPage.FontFamily>
  <phone:PhoneApplicationPage.FontSize>
    <StaticResource ResourceKey="PhoneFontSizeNormal"/>
  </phone:PhoneApplicationPage.FontSize>
  <phone:PhoneApplicationPage.Foreground>
    <StaticResource ResourceKey="PhoneForegroundBrush"/>
  </phone:PhoneApplicationPage.Foreground>

  <!--LayoutRoot is the root grid where all page content is placed-->
  <Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding
ObjectDataBindingPage.xaml Code File
Source={StaticResource CustomersDataSource}}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="Chapter 2 - DATA BINDING"
ObjectDataBindingPage.xaml Code File
Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="object data binding" Margin="9,-7,0,0"
ObjectDataBindingPage.xaml Code File
Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox Margin="12,0" ItemsSource="{Binding CustomerList}"/> </Grid> </Grid> </phone:PhoneApplicationPage>

The Expression Blend work results in the following XAML changes:

  • Added an xmlns namespace import to the SampleData.LiveData namespace at the top of the XAML page.

  • Added a CustomersDataSource resource to the PhoneApplicationPage.Resources section.

  • Set the DataContext attribute for the LayoutRoot Grid to the CustomersDataSource resource via a Binding markup extension.

  • Bind the ListBoxItemSource attribute to the CustomerList property of the Customers class.

It is important to note that by setting the DataContext on the LayoutRootGrid, it makes the data source collection, individual records, and fields available to nested XAML controls automatically. As an example, an ItemTemplate can be added to the ListBox that Binds TextBlock control Text properties to the FirstName and LastName properties of the Customer class just by specifying the data field name in the Binding marketup extension. I demonstrate how to do this visually next.

Right-click on the ListBox, select Edit Additional Templates, then Edit Generated Items, and finally click Create Empty. This puts the Artboard into template editing mode with an empty Grid. Drag two TextBlock controls next to each other with some spacing to fit the FirstName and LastName fields. Next click the more actions button next to the Text property in the Properties Window for the first TextBlock to bring up Figure 2-26.

Create data binding

Figure 2.26. Create data binding

Expression Blend understands that we are creating an ItemTemplate to display individual Customer records in the ListBox that is data bound to the CustomersList so the fields available for controls in the ItemTemplate are Customer class fields. We select FirstName for the left TextBlock and LastName for the second TextBlock. Adding the ItemTemplate results in the much more useful display of first name and last name for each record. Here is the resulting XAML:

<DataTemplate x:Key="CustomersListBoxDataTemplate">
  <Grid>
    <TextBlock Margin="0" TextWrapping="Wrap"
    Text="{Binding FirstName}"
    d:LayoutOverrides="Height" Width="75"/>
    <TextBlock Margin="0,0,-148,0" TextWrapping="Wrap"
    Text="{Binding LastName}"
    d:LayoutOverrides="Height" HorizontalAlignment="Right" Width="118"/>
  </Grid>
</DataTemplate>

XML Data Binding

The first step to data binding to XML is to obtain the XML file, which can be retrieved from a remote server or embedded as part of the application. For this demonstration, the XML file is retrieved from the application, because I don't cover remote server access until Chapter 4.

There are two ways to parse XML data in Silverlight: the XmlReader class and LINQ to XML, which is one of the new technologies that became available in .NET Framework 3.5 and later. The XmlReader class is a fast-forward–only, non-caching XML parser. For processing large XML files, XmlReader is better suited than LINQ to XML for performance reasons. LINQ to XML provides rich object-based XML processing using the common LINQ syntax.

The work in this section is focused on the XmlDataBindingPage.xaml page, which has two ListBox controls: a ListBox named XmlDataLinqListBox that is loaded via data binding with LINQ to XML and another ListBox named XmlDataReaderListBox that is loaded via XmlReader in Code.

The ApplicationBar control is enabled with two icon buttons, one to switch between the two ListBox controls by alternatively hiding and making visible the controls. The other icon button loads data into the XmlDataReaderListBoxListBox. We configure an icon for the icon button that loads the data via XmlReader by simply browsing the list of icons available as resources and configure the Refresh icon. The other icon was created by combining the default next and back icons into one. The second icon button switches between the two ListBox controls using the Visibility property.

Now that we have the sample project set up, the next two sections cover the code to load the XML data using both methods.

LINQ to XML

The Silverlight XmlReader works in a similar manner as the XmlReader in the full version of the .NET Framework. Visit this site for details on the differences between the .NET Framework and the .NET Framework for Silverlight versions of XmlReader:

http://msdn.microsoft.com/en-us/library/cc189053(VS.95).aspx

Silverlight for Windows Phone 7 is a rich subset of the full .NET Framework 3.5 and that it includes LINQ. There are many web sites, blogs, and books that cover LINQ, so I won't dive into all the details here.

Tip

A great resource on LINQ is Joseph C. Rattz Jr.'s Pro LINQ: Language Integrated Query in C# 2008 (Apress, 2007).

Since the XML file is embedded into the application, we use an XmlResolver. In this case the XmlXapResolver, which extracts XML from the xap, and then loads the XML data into an XDocument object.

We call XDocument.Load(XmlReader) to load the contents into an XDocument so that it can be queried using LINQ. The XDocument class, located in the System.Xml.Linq namespace, is the key object in LINQ to XML functionality.

The XmlReader class can be used to read XML data from the IsolatedStorage file system as well as from streams retrieved via the network just like in the full .NET Framework. A unique Silverlight for Windows Phone 7 ability that we take advantage of in this section is to use an XmlXapResolver to retrieve XML data embedded into the application's .xap file, which is the container for Silverlight applications. An XML resolver in .NET resolves, or evaluates, external XML resources. An XmlUrlResolver is used to resolve the Url location passed into XmlReader.Create. The XmlXapResolver looks for the name passed into XmlReader.Create within the .xap file for the application:

XmlReaderSettings XmlRdrSettings = new XmlReaderSettings();
XmlRdrSettings.XmlResolver = new XmlXapResolver();
XmlReader reader = XmlReader.Create("ApressBooks.xml",
XmlRdrSettings);

The resolver is configured for the XmlReaderSettings object that is passed into the Create method. For more information on the XmlReaderSettings class, refer to the MSDN documentation here:

http://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings(VS.95).aspx

The LINQ to XML code is encapsulated in the ApressBooks class that is part of the DemoLiveData project shown in Listing 2-10.

Example 2.10. APressBooks.cs Code File

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Collections;

namespace DemoLiveData
{
  public class ApressBooks
  {
    private List<ApressBook> _apressBookList;
    public List<ApressBook> ApressBookList
    {
      get
      {
        if (null == _apressBookList)
          RetrieveData();
        return _apressBookList;
      }
    }

    private void RetrieveData()
    {
      XmlReaderSettings XmlRdrSettings = new XmlReaderSettings();
      XmlRdrSettings.XmlResolver = new XmlXapResolver();
      XmlReader reader = XmlReader.Create("ApressBooks.xml", XmlRdrSettings);

      XDocument xDoc = XDocument.Load(reader);

      _apressBookList =
        (from b in xDoc.Descendants("ApressBook")
         select new ApressBook()
         {
           Author = b.Element("Author").Value,
           Title = b.Element("Title").Value,
           ISBN = b.Element("ISBN").Value,
Description = b.Element("Description").Value,
           PublishedDate = Convert.ToDateTime(b.Element("DatePublished").Value),
           NumberOfPages = b.Element("NumPages").Value,
           Price = b.Element("Price").Value,
           ID = b.Element("ID").Value
         }).ToList();
    }
  }
}

It is similar to the Customers class in the same project in that it just returns a list of objects to databind. The object type is ApressBook shown here:

using System;

namespace DemoLiveData
{
  public class ApressBook
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string Description { get; set; }
    public DateTime PublishedDate { get; set; }
    public string NumberOfPages { get; set; }
    public string Price { get; set; }
    public string ID { get; set; }
  }
}

The significant difference between the Customers class and the ApressBooks class is the LINQ to XML code that parses out an ApressBook object from the XML. Otherwise, the data binding process is the same within Expression Blend so we how all of the dialogs to data bind ApressBooks to the XmlDataLinqListBoxListBox control on the XmlDataBindingPage.xaml page. The next section covers reading the XML data and loading it directly into the Items collection of the ListBox control.

XmlReader

For this section, the XML records are added to the ListBox.Items collection for the XmlDataReaderListBox on the XmlDataBindingPage.xaml page without using an ItemTemplate. In Silverlight 4 XPath is supported so that you can create a Data Template that parses the bound XML object but for now we just bind the XML object as is without a template. Here is the code to load up the data:

private void XmlReaderIconButton_Click(object sender, EventArgs e)
{
  XmlReaderSettings XmlRdrSettings = new XmlReaderSettings();
  XmlRdrSettings.XmlResolver = new XmlXapResolver();
  XmlReader reader = XmlReader.Create("ApressBooks.xml", XmlRdrSettings);

  // Moves the reader to the root element.
  reader.MoveToContent();

  while (!reader.EOF)
{
    reader.ReadToFollowing("ApressBook");
    // Note that ReadInnerXml only returns the markup of the node's children
    // so the book's attributes are not returned.
    XmlDataReaderListBox.Items.Add(reader.ReadInnerXml());
  }
  reader.Close();
  reader.Dispose();
}

Figure 2-27 shows both methods in action.

Xml Data Binding UI

Figure 2.27. Xml Data Binding UI

In this section I covered the Silverlight for Windows Phone 7 data binding capabilities. When live data is not available, developers can take advantage of the sample data capabilities available in Expression Blend, which I cover in the next section.

Sample Data

It is difficult to build out a user experience without the content available in a usable format. Quite often, a project will have development and test services and classes to make data available within an application. Still, this means that you must have an Internet connection available, or have to VPNconfigured to access services. Being able to work with a local copy of the data is more convenient and probably quicker in terms of iterative development than connecting over and over to a data service. Expression Blend 4 includes a Data Panel on the right in the Blend UI as shown in Figure 2-28 where developers and designers can add or import sample data.

The Data Panel in Expression Blend 4

Figure 2.28. The Data Panel in Expression Blend 4

Table 2-3 identifies key aspects of the Data Panel with a couple of fake data sources configured to help explain the various capabilities.

Table 2.3. Expression Blend 4 Data Panel Features

Annotation

Description

A

Selected by default, list mode for the Data panel lets you drag the Customers collection shown in Figure 2-28 onto the Artboard and generates a ListBox data-bound to the Customers design-time datasource.

B

Details mode lets you drag a collection item like FirstName to the Artboard to create a control data-bound to that collection item. This action also configures the DataContext property of the parent container to the collection, in this example Customers.

C

This is a document-level datasource collection named Customers. In addition, a datasource named ProjectSampleDataSource is defined at the Project level.

D

Click this button to edit and further customize the collection. You can specify the type of value (String, Number, Boolean, or Image) as well as the format (for String, how many words; for Number, how many digits; and for Image, a folder location).

E

The "Create data source" button allows you to add a live or real datasource to the application to display at runtime.

F

The "Create sample data" button allows you to create a design-time datasource to help working with UI elements that display data in Expression Blend

G

You can define datasources at the document and project levels of an application.

H

Click the plus sign to add a simple property to a datasource collection, or click the down-arrow next to the plus sign to choose whether to add a simple property, a complex property, or a collection property to the design-time datasource.

I

Click the down-arrow for an individual property to edit the attributes for the property, such as its type and format, depending on the type of the property.

The Data Panel allows developers and designers to work with the design-time data in Expression Blend while also displaying the design-time data at runtime for testing and demonstration purposes. Developers can also add a live datasource to the UI that pulls data from a live datasource for display at runtime, by clicking item E in Figure 2-28.

As long as your schema is compatible between the design-time datasource and the live datasource, a developer can use both a design-time and a runtime data source in an application. The steps to use both are pretty straightforward. Start working with a design-time datasource to build an application. Next add a live datasource to the Data panel in Expression Blend. Drag items from the live datasource, and drop them onto the control displaying the corresponding sample data. This will bind the control to design-time data at design-time and runtime data at runtime.

Note

Clear the check box next to Enable When Running Application in the design-time datasource properties to allow the live datasource to display data at runtime.

As long as the data schemas match, the sample data displays on the Artboard in Expression Blend and the live data displays when the application executes. This is because the sample datasource bindings are not removed or overwritten when the run-time datasource is added. Once you create a sample data source, you can work with it just like with live data as demonstrated above in the section on Data Binding.

Control Styling

By default, Windows Phone 7 controls are styled to fit the Metro design language intrinsic to Windows Phone 7. You can apply the built-in styles to your application's user interface as well as create your own styles. Silverlight styles allow you to define a set of properties related to UI that can be reused throughout an application to create a standardized look and feel.

Expression Blend 4 can apply Metro text styles as shown in Figure 2-29 by right-clicking on the control and selecting Edit Style

Control Styling
Applying built-in Metro text styles

Figure 2.29. Applying built-in Metro text styles

After visually applying the style, the XAML is updated with a StaticResouce markup extension applied to the Style property.

<TextBlock Margin="12,273,31,270" TextWrapping="Wrap" Text="Apply a Built in Style"
   Style="{StaticResource PhoneTextExtraLargeStyle}"/>

You can create your own styles tailored to your brand or application theme but otherwise try to use the built-in Metro styles. To create a custom Text style right-click on a TextBlock and select Edit Style as before but this time select "Create Empty..." to bring up the dialog box shown in Figure 2-30.

Create Style Resource dialog

Figure 2.30. Create Style Resource dialog

The Name (Key) attribute is how you reference the resource when applying it as a style with this syntax Style="{StaticResource ResourceKeyNameHere}".

Resources can be defined at the application level in the <Application.Resources> element, at the page level in the <phone:PhoneApplicationPage.Resources> element, or in a separate Resource Dictionary by clicking the "New.." button. Clicking the "New..." button brings up the Resource Dictionary dialog shown in Figure 2-31.

Resource Dictionary New Item dialog

Figure 2.31. Resource Dictionary New Item dialog

Clicking OK to the dialog in Figure 2-31 enables the Resource Dictionary option and sets the name on the dropdownlist box in the dialog shown in Figure 2-30. Clicking OK to that dictionary adds an entry to the Application.Resources element in App.xaml.

<Application.Resources>
  <ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
      <ResourceDictionary Source="Chapter2ControlStylesResourceDictionary.xaml"/>
    </ResourceDictionary.MergedDictionaries>
  </ResourceDictionary>
</Application.Resources>

Resource dictionaries are a great way to segregate XAML markup to keep markup files from becoming unwieldy and achieve better project organization. Now that you understand how styles are referenced and stored, let's move on to creating a custom text style that we can apply to the TextBlock named CustomStyleTextBlock.

We continue visually editing the TextBlockStyle1 style now located in the Chapter2ControlStylesResourceDictionary.xaml resource dictionary. We set the Foreground color to Gold and the Opacity to 70%. Here is the resulting XAML markup:

<Style x:Key="TextBlockStyle1" TargetType="TextBlock">
        <Setter Property="Foreground" Value="Gold"/>
        <Setter Property="Opacity" Value="0.7"/>
</Style>

Tip

Implicit styles are introduced in Silverlight 4, but they are not supported in Silverlight for Windows Phone, which is based on Silverlight 3. Implicit styles are defined without an x:key so that the style is applied to all controls that match the TargetType without an explicit Style value configured.

A style consists of a TargetType and nested series of Setter property elements. The TargetType must be a control that inherits from the FrameworkElement base class. Each Setter consists of a Property name and a Value. These identify what control properties the settings apply to as well as what the value should be. For a complex property, the <Setter.Value></Setter.Value> syntax like this:

<Style x:Key="TextBlockStyle2" TargetType="TextBlock">
  <Setter Property="Foreground">
    <Setter.Value>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="Gold" Offset="0"/>
        <GradientStop Color="White" Offset="1"/>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
  <Setter Property="Opacity" Value="0.7"/>
</Style>

Another attribute available on the Style element is the BasedOn attribute, which allows a Style to inherit from another Style. The TextBlockStyle2 is modified to inherit from the built-in Metro style using this attribute setting on the Style element:

BasedOn="{StaticResource PhoneTextExtraLargeStyle}"

The last option I will cover is inline styles, where the Style is nested within the XAML markup for the control. Here is an example with a single property:

<TextBlock Height="57" HorizontalAlignment="Left" Margin="42,427,0,0"
Resource Dictionary New Item dialog
Name="InlineStyleTextBlock" Text="TextBlock" VerticalAlignment="Top" Width="162"> <TextBlock.Style> <Style TargetType="TextBlock" BasedOn="{StaticResource PhoneTextLargeStyle}"> <Setter Property="Foreground" Value="Orange" /> </Style> </TextBlock.Style> </TextBlock>

Any control that inherits from the FrameworkElement base class has a Style property that can be standardized across the application, though not all controls support visual editing of styles via menu items. To create a custom style for a Button, edit the XAML in the Chapter2ControlStyleResourceDictionary.xaml file to start a custom Style with a TargetType of Button and a name of ButtonStyle. Once the custom Style is manually created, you can visual edit styles using the Resources window as shown in Figure 2-32 with the ButtonStyle selected and ready to be edited visually.

Resources window

Figure 2.32. Resources window

Once the custom Button style is completed, you can apply it to an existing Button control by selecting the Button, finding the Style property in the Properties window, and clicking the button to apply a Local Resource named ButtonStyle. See Figure 2-33.

In Figure 2-33, the Properties Window is filtered by typing Style in the filter box at the top of the Properties Window.

Applying ButtonStyle via Properties window Style property

Figure 2.33. Applying ButtonStyle via Properties window Style property

The Style is already applied to the Button but the arrows highlight the small green button, which is usually black until the property is customized. Green around a property indicates that a resource is applied. Additional menu items light up such as Edit Resource... and Convert to New Resource... Here is the final XAMLfor the ButtonStyleStyle:

<Style x:Key="ButtonStyle" TargetType="Button" >
  <Setter Property="Foreground">
    <Setter.Value>
      <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="Gold" Offset="0"/>
        <GradientStop Color="White" Offset="1"/>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
  <Setter Property="Opacity" Value="0.7"/>
  <Setter Property="BorderBrush" Value="Red"/>
</Style>

This completes the overview on Control Styles and customization. The next section provides background on control templates.

Control Templates

In most "real" software development projects, custom controls are needed to customize data presentation, customize how a control appears, as well as how a control functions. In Silverlight, developers generally do not create custom controls. Instead, Silverlight developers modify existing controls vial control templates.

Right-click on the ListBox control on the ListBoxTemplatePage.xaml page and you will see two menu items related to Templates: Edit Template and Edit Additional Templates. I cover both menu items in the next two sections.

Edit Template Menu Item

This menu item enables direct modification of the control for maximum customization. There are two sub-menu items "Create Empty..." and "Edit a Copy..." to create a customized control. Selecting the "Create Empty..." menu item is essentially starting from scratch. The template contains a Grid to start create a new control UI.

Most customizations start with the "Edit a Copy..." menu item, which extracts the Control's internal visual tree, including visual states and animations, and makes it available for customization. This is very similar to inheriting from an existing control in other languages but much more powerful.

Edit Additional Templates

The Edit Additional Templates menu item can have one or more options depending on the control. For example, a ListBox control has the following options:

  • Edit Generated Items (ItemTemplate)

  • Edit Generated Item Container (ItemContainerStyle)

  • Edit Layout of Items (ItemsPanel)

The Generated Items ItemTemplate is the template applied to the data bound list of items. Without customization, the ListBox displays the .ToString() value for the data bound type. This is the most common – and necessary – customization for a ListBox control.

The ItemContaineStyle is also a customization applied to the data bound list of items. This style is applied to the container element generated for each item. For a ListBox, the generated container control is a ListBoxItem control. I don't cover ItemsContainerStyle in this section. I will discuss customizations in Chapter 5 when I cover the Visual State Manager.

The last additional template for the ListBox is the ItemsPanel template, which just has a "Create Empty..." option. This template customizes the container that all of the ListBoxItem controls exist in.

As mentioned, different types of controls can have different options for additional templates to edit. As another example, the progress bar does not have any additional templates to edit but the Button Control has a ContentTemplate that customizes content rendering for the Button control by applying a data template to the content.

I discuss editing the control template and additional templates in the next couple of sections to demonstrate these concepts with the ListBox, Button, and ProgressBar controls.

ListBox Customization

The ListBox control needs to data bind with a collection of data to be interesting. We create a sample data source at the Project level named ProductsSampleData that has 100 items.The sample data text, a url, and an image in order to make it interesting. Next up is working with the ItemTemplate in the first section.

Working with ItemTemplate

The first step we take is to drag the Products collection to the ListBox, which data binds the collection and creates an ItemTemplate automatically that can be used as a starting point as shown in Figure 2-34.

Generated ItemTemplate for Products sample data

Figure 2.34. Generated ItemTemplate for Products sample data

Here is the XAML markup for the ItemTemplate that we customize in Blend shortly:

<DataTemplate x:Key="ProductsItemTemplate">
  <StackPanel>
    <TextBlock Text="{Binding Description}"/>
    <TextBlock Text="{Binding Name}"/>
    <TextBlock Text="{Binding Price}"/>
    <Image Source="{Binding ProductImage}" HorizontalAlignment="Left" Height="64" Width="64"/>
    <TextBlock Text="{Binding Url}"/>
  </StackPanel>
</DataTemplate>

To edit the template, click the drop-down arrow next to (ListBox) at the top of the ArtBoard under where the filenames are displayed and select Edit Additional Templates

Generated ItemTemplate for Products sample data

The first modification is to add 40px bottom margin to the root StackPanel to create space between the items. Next the items are re-arranged to present a better display with the item name, price, image, and URL at the top. Do this by re-arranging the controls in the first item visually.

Note

Because it is a repeated template for each item, the ItemTemplate is dynamically applied to the items below the first item as the first item is visually edited.

To improve the display and better utilize space, multi-select the Name and Price fields, right-click, select Group Into, and pick a container control. Any one of the containers can be used to arrange the Name and Price fields, but choose the StackPanel with Orientation set to Horizontal in this case to flow the content across the screen. Grab the lower right-hand corner of the Image to increase the Image size. We next apply built-in styles to further refine the UI. Finally, set the DescriptionTextBox TextWrapping property to Wrap. Figure 2-35 shows the final modifications to the generated template shown in Figure 2-34.

Customized ItemTemplate for Products sample data

Figure 2.35. Customized ItemTemplate for Products sample data

This completes our overview on working with the ItemTemplate customization for the ListBox. Let's turn to the ItemsPanel customization next.

Custom ItemsPanel

By default, the ListBox uses a VirtualizedStackPanel as the ItemsPanel. The VirtualizedStackPanel enables much faster data refresh with very long lists, because only the visible elements are drawn. For a list that is tens of items or low hundreds of items, the VirtualizedStackPanel may not provide much benefit and can potentially impact scroll performance.

If scrolling is not smooth for your application, select the ListBox control and go to the breadcrumb menu up top of the ArtBoard near the filenames and click on ListBox, select Edit Additional Templates, Edit Layout of Items (ItemsPanel), and then "Create Empty..." to get started. The Create ItemsPanelTemplate Resource dialog box pops up. Provide a name and store the template in This Document to place the template in the Resources section. By default it creates this ItemsPanelTemplate with a StackPanel.

<ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
        <StackPanel/>
</ItemsPanelTemplate>

Because there is a few hundred items, you can experience the performance differences. Without the custom ItemsPanelTemplate modification, when you click Customize ListBox, the ListBoxTemplatePage.xaml page loads immediately, because the data is virtualized in the ListBox with the default VirtualizedStackPanel items container.

When you modify the ItemsPanelTemplate to be a StackPanel, the page takes noticeably longer to load –about four or five seconds. Scrolling appears smoother, but the load time may be unacceptable. This is because all of the items, a couple of hundred, must be created before rendering, i.e., the data is no longer virtualized.

As you can see, there are always trade-offs with performance recommendations to consider and test before final implementation.

Button Customization

In this section I cover some additional control customizations available to developers. Next we transform a standard rectangle Button to an ellipse Button via a custom control template.

Custom Control Template

To get started, drag a Button on the ArtBoard, right-click on the Button, and select Edit Template, then "Edit a Copy..." to go into control template editing mode. The ButtonBackground Layer is a Border. You may be tempted replace the Border with an Ellipse control, but that would make the necessary changes much more complex due to animation dependencies and the fact that the Border is actually a container control whereas the Ellipse is not.

Instead, make a simple modification by adjusting the CornerRadius property for the Border by setting it to 50. The Button now has rounded corners and can take on various elliptical shapes depending on the Height and Width properties. Figure 2-36 shows the Button in action.

Custom Button control template

Figure 2.36. Custom Button control template

There are much more complex modifications possible that involve editing the Visual States defined in the template. I cover modifying states in Chapter 5, when I discuss the Visual State Manager. For this section I will expose you to control customizations by modifying the internal visual tree via a control template.

Animation Fundamentals

Silverlight has powerful animation capabilities that allow the designer or developer to animate any property value of type Double, Color, or Point. Animation lets you vary a property between two values over a specified period of time, thus providing the illusion of motion or transformation.

In Silverlight for Windows Phone, the animation engine is left to interpret how to change the value over the specified period of time between the configured values for the property that is being animated. To apply an animation to a UI element, create a Storyboard, which I describe in the next section and then move on to key frame animations.

Creating an Animation Storyboard

In the Chapter 2 project BasicAnimations, we add a navy blue Rectangle control named NavyRect to animate using a Storyboard. To apply an animation to a UI element, create a Storyboard in XAML, and set TargetName and TargetProperty to specify the element and the property of the element to animate. Nest the animation within the Storyboard element in XAML in phone:PhoneApplicationPage.Resourcelike this:

<Storyboard x:Name="NavyRectMouseClick">
  <DoubleAnimation BeginTime="00:00:00.5" From="1" To="7"
   AutoReverse="True" Duration="00:00:00.5"
   Storyboard.TargetName="Rect1"
   Storyboard.TargetProperty="(Shape.StrokeThickness)"/>
</Storyboard>

The TargetName and TargetProperty attributes are attached properties for the Storyboard class. Storyboard objects are usually created as resources within either the Application.Resources or UserControl.Resources element, making it easy to interact with the Storyboard by referencing it by the x:Name value.

This XAML contains a DoubleAnimation object, which can animate a value of type Double between the values configured in the From and To properties. An additional property configured here is AutoReverse, which indicates whether the animation should automatically reverse itself and animate in the opposite direction starting at the To value and ending at the From value. BeginTime indicates how long after starting the Storyboard should the animation actually begin.Duration specifies how long the animation should take to animate between the From and To values for the property of type Double. Also, a Storyboard can contain more than one animation, allowing one Storyboard to animate multiple objects and properties.

The Storyboard class provides Begin, Pause, Stop, and Resume methods you can use to control the Storyboard programmatically. The following code starts the animation when you touch the Rectangle:

private void NavyRect_MouseEnter(object sender, MouseEventArgs e)
{
  NavyRectMouseClick.Begin();
}

The Loaded event is the only RoutedEvent supported in a Trigger for Silverlight. You can read more about RoutedEvents in the Silverlight documentation:

http://msdn.microsoft.com/en-us/library/system.windows.routedevent(VS.96).aspx

Triggers provide an elegant way of firing an animation. Silverlight for Windows Phone supports Triggers like WPF, where an animation is kicked off via XAML code only; but currently, the only supported event that can be associated with a trigger is the Loaded event. Here is an example from the BasicAnimations project:

<Rectangle.Triggers>
  <EventTrigger RoutedEvent="Rectangle.Loaded">
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation Storyboard.TargetName="NavyRect"
          BeginTime="00:00:00" From="0.0" To="1.0" Duration="0:0:0.5"
          Storyboard.TargetProperty="(UIElement.Opacity)" />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger>
</Rectangle.Triggers>

The Loaded event is very handy to have UI fade into view as the XAML loads. Run the sample to see the effect. You may wonder why the Storyboard is embedded in the Rectangle declaration and not configured as a Resource on the Page. The reason is that Silverlight does not support loading a value for Storyboard using the StaticResource markup extension within a Trigger.

In addition to the DoubleAnimation, developers can also create ColorAnimation and PointAnimation objects within a Storyboard object. To demonstrate this, add an Ellipse named GoldEllipse to the XAML:

<Ellipse Name="GoldEllipse" Stroke="Navy" Height="100" Fill="Gold" Width="100"
  Margin="30,162,0,0" HorizontalAlignment="Left" StrokeThickness="1"
  VerticalAlignment="Top" MouseEnter="GoldEllipse_MouseEnter"
  MouseLeave="GoldEllipse_MouseLeave" />

Here are several ColorAnimation examples that are started in the MouseEnter event and stopped in the MouseLeave event. Because there isn't a mouse pointer in Windows Phone, these events fire when your finger touches and then is moved off of the Ellipse.

<Storyboard x:Name="EllipseMouseEnter">
  <ColorAnimation BeginTime="00:00:00" Duration="00:00:00.3"
                  From="#FFC18125" To="#FF2DBD43"
                  Storyboard.TargetName="GoldEllipse"
                  Storyboard.TargetProperty=
                  "(Shape.Fill).(SolidColorBrush.Color)"/>
</Storyboard>
<Storyboard x:Name="EllipseMouseLeave">
  <ColorAnimation BeginTime="00:00:00" Duration="00:00:00.3" To="#FFFFD700"
                  Storyboard.TargetName="GoldEllipse"
                  Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"/>
</Storyboard>

To demonstrate PointAnimation, add a Path object with the shape defined by a PathGeometry:

<Path Name="OlivePath" Fill="Olive" Margin="46,380,75,6"
  MouseLeftButtonDown="OlivePath_MouseLeftButtonDown" >
  <Path.Data>
    <PathGeometry>
      <PathFigure>
        <ArcSegment x:Name="animatedArcSegment" Point="50,50" Size="50,150"
        RotationAngle="-20" IsLargeArc="False"
              SweepDirection="Clockwise"/>
      </PathFigure>
    </PathGeometry>
  </Path.Data>
</Path>

Here is the related PointAnimation that is invoked by touching the Path object via the MouseLeftButtonDown event:

<Storyboard x:Name="PathClick">
  <PointAnimation AutoReverse="True"
    Storyboard.TargetProperty="Point"
    Storyboard.TargetName="animatedArcSegment"
    Duration="0:0:2" To="200,200"/>
</Storyboard>

This section covered the basics of Storyboard animation. The next section introduces key frame animation with Expression Blend.

Creating Animations in Blend

Icovered the basics of animation in the previous section using Storyboard objects. In this section we will dive deeper into creating animations using keyframe objects to explore animating multiple controls and properties in the same Storyboard, configuring the interpolation type for the animation, as well as configuring easing in, easing out, i.e., acceleration for overall animation to provide fine-tuned animation control.

To create and manage animations, you work in the Objects and Timeline Tool Window as shown in Figure 2-37.

Animation management in the Objects and Timeline tool window

Figure 2.37. Animation management in the Objects and Timeline tool window

Clicking the "plus" sign to create a new Storyboard prompts for a name, name it RectStoryboard, and then click OK. With our new Storyboard, let's create an animation that re-positions and rotates the Rectangle vertically. Select just the Rectangle in the Storyboard editor as shown in Figure 2-38.

Storyboard editor

Figure 2.38. Storyboard editor

Clicking the record keyframe button (the small blue oval with the plus sign pointed to by the arrow) adds a keyframe for the selected or multiple selected objects on the Artboard. Recording a Storyboard is a matter of adding keyframes at different points of time, slide the yellow timeline marker to later on the timeline, reposition the object(s), and then click the add keyframe button again. Silverlight will interpret the animation behavior between keyframes. You simply have to position objects and record keyframes to create an animation.

Click the close animation button (the "x" button) to exit timeline recording mode. You don't want to accidentally record random editing as part of an animation.

Tip

You can always undo accidental modifications by clicking Edit

Storyboard editor

Open the Chapter 2 BasicAnimation project to explore the Storyboard editor and play the RectStoryboard animation. Clicking on one of the keyframe objects in the timeline brings up the visual keyframe editor as shown in Figure 2-39.

Individual Keyframe editor

Figure 2.39. Individual Keyframe editor

Select the second keyframe at one second and change the easing from the default straight line to a Cubic Out Easing Function to improve the animation's behavior towards the end of the animation. Select an "In" animation to affect the beginning of the animation. The EasingFunction options provide a quick and easy way to visually identify how the changes will affect the animation.

The other options available are KeySpline and Hold In. The Hold In easing modification holds the animation and then adjusts position very quickly at the end. The KeySpline easing modification allows for more fine grained control by adjusting the yellow control handles to modify the values as shown in Figure 2-40.

KeySpline easing customization

Figure 2.40. KeySpline easing customization

Add a TextBlock and then drop the ControlStoryboardAction behavior on to the TextBlock. Leave the EventName to MouseLeftButtonDown and the ControlStoryboardOption to Play. All that has to be changed is the name of the Storyboard. Change it to RectStoryboard, which means that when the TextBlock is clicked or touched on a device, the white Rectangle will animate. Listing 2-11 has the generated XAML from the work in Expression Blend.

Example 2.11. RectStoryboard Code Fragment

<Storyboard x:Name="RectStoryboard">
  <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform)
RectStoryboard Code Fragment
.(CompositeTransform.TranslateY)" Storyboard.TargetName="rectangle"> <EasingDoubleKeyFrame KeyTime="0" Value="0"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="198.876"> <EasingDoubleKeyFrame.EasingFunction> <CubicEase EasingMode="EaseOut"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform)
RectStoryboard Code Fragment
.(CompositeTransform.TranslateX)" Storyboard.TargetName="rectangle"> <EasingDoubleKeyFrame KeyTime="0" Value="0"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-35.955">
<EasingDoubleKeyFrame.EasingFunction>
                <CubicEase EasingMode="EaseOut"/>
        </EasingDoubleKeyFrame.EasingFunction>
    </EasingDoubleKeyFrame>
  </DoubleAnimationUsingKeyFrames>
  <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform)
RectStoryboard Code Fragment
.(CompositeTransform.Rotation)" Storyboard.TargetName="rectangle"> <EasingDoubleKeyFrame KeyTime="0" Value="0"/> <EasingDoubleKeyFrame KeyTime="0:0:1" Value="89.949"> <EasingDoubleKeyFrame.EasingFunction> <CubicEase EasingMode="EaseOut"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame> </DoubleAnimationUsingKeyFrames> </Storyboard>

As you can see in the generated XAML, The animation class is DoubleAnimationUsingKeyFrames. Just like DoubleAnimation, ColorAnimation, and PointAnimation objects, the keyframe animations work on certain types, including Color, Double, Point, and Object with the corresponding keyframe class of ColorAnimationUsingKeyFrames, DoubleAnimationUsingKeyFrames, PointAnimationUsingKeyFrames, and ObjectAnimationUsingKeyFrames.

Each of these classes includes a KeyFrames collection containing keyframe objects that correspond to the type being animated, with an additional wrinkle of the algorithm used to interpolate between keyframes.

The available animation interpolation options are linear, discrete, and splined. Linear interpolation animates at a constant rate for the duration of the segment and is the default. Discrete or Hold interpolation animates at discrete intervals without interpolation over time.

KeySpline interpolation is more similar to linear than discrete but provides the ability to accelerate or decelerate the animation within the duration of a segment. The spline interpolation method has an additional property called KeySpline that defines a Bezier curve to create more realistic effects. The KeySpline property defines a Bezier curve with two control points that go from (0,0) to (1,1). The first control point defines the curve factor of the first half of the curve, and the second control point defines the curve factor for the second half of the curve; the curve factor defines the rate of change or acceleration for the spline keyframe as shown in Figure 2-40.

This concludes my exploration of animations in Blend. I will build on this work throughout the text as needed to demonstrate more advanced concepts such as handling orientation changes in Chapter 5. The next section covers an example of how to create animation in code.

Creating Animations in Code

On Windows Phone 7, such as when you click a tile or other objects in the phone UI, there is a Tilt animation to give visual feedback that the action was registered. This link provides an overview of the Tile Effect sample in the Windows Phone 7 documentation.

http://msdn.microsoft.com/en-us/library/ff941094(v=VS.92).aspx

This link references a code sample that contains a file named TiltEffect.cs. This link describes how to use the TilfEffect code sample but I'll also cover the steps here:

http://msdn.microsoft.com/en-us/library/ff941108%28v=VS.92%29.aspx

We add TiltEffect.cs code file to the BasicAnimations project and change the namespace to BasicAnimations. We add the xmlns:tilt="clr-namespace:BasicAnimations" namespace to MainPage.xaml. We also add this line to the PhoneApplicationPage element to enable Tilt: tilt:TiltEffect.IsTiltEnabled="True".We also add a ListBox control with a few items to test the TiltEffect. Run the sample to see the TiltEffect in action. Note that it only applies to controls that inherit from ButonBase or ListBoxItem by default. Developers can add additional control types programmatically via code:

TiltEffect.TiltableItems.Add(typeof("AdditionalControl"))

Application Layout

Windows Phone 7 provides a differentiated user experience with unique interaction models. In Chapter 1 and at the beginning of Chapter 2, I discussed the Metro design language with examples provided by the "Hubs" like People, music+video, and so on. Hub experiences are based on a Panorama control. The built in Outlook application is based on a Pivot control. I cover both the Panorama and Pivot controls in the next two sections.

Panorama

The Panorama control allows Windows Phone 7 developers to build "Hub-like" experiences within their own applications. Generally an application will have one Panorama as the first screen in the application. It is not recommended to have multiple Panorama controls within an application.

Think of the as the magazine cover and table of contents of an application. From a design perspective, a Panorama control should not be jammed-packed with content. Rather an application's Panorama page should highlight top items, favorites, and a menu to navigate to the details of an application hosted on Pivot pages for detailed lists of items or regular pages for individual item details.

The control provides full design-time experience to switch between PanoramaItem panes and visually edit content. The built-in Panorama control matches the look and behavior of the built-in Windows Phone 7 experience, including the gesture-and-flick support.

A Panorama control includes automatic page animations so that transitioning between panes, with different layers moving at different speeds, providing a nice parallax effect. The layers consist of a Title layer at the top left-aligned on the PanoramaItem pane furthest to the left by default. The next layer is the header for the individual PanoramaItem panes.

A Panorama control consists of multiple panes or PanoramaItem objects that span beyond the phone screen horizontally. Generally a Panorama application spans between three and five PanoramaItem objects wide, though four is the recommended maximum. The number of PanoramaItem panes that perform well depends on the content weight in each Pane. Having four PanoramaItem controls richly packed with images and content may well bog down an application with performance issues. Keep an eye on the UI performance counters when working with the Panorama control especially.

Warning

Keep an eye on transitions, animations, and scrolling. If transitions and animations cut short or don't render, that's an indication of too much work on the UI thread. Poor scrolling performance is also an indicator. Reduce rendering complexity as well as offload work from the UI thread wherever possible in these situations.

In situations where performance is suffering, developers can hide individual PanoramaItems until content is visible. Dynamically loading and unloading PanoramaItems may help in some cases as well. Pay attention to the graphic performance counters covered previously to see the impact of changes as content is added.

PanoramaItem panes overlap onscreen such that 24 pixels of the pane to the right show on the current pane in view as shown in Figure 2-41. The content to the right of the line with arrows overlaid on to the screenshot is from the PanoramaItem item to the right, giving a hint to swipe right and reveal the content.

The "peek" on a PanoramaControl

Figure 2.41. The "peek" on a PanoramaControl

Notice the straight edges and grid like nature of content on the screen. It is perfectly OK for a PanoramaItem object to extend into two panes such as the "History" section of the music+video Hub on a Windows Phone 7 device. You can set the PanoramaItem control's Orientation property to Horizontal to flow into additional panes and achieve the same effect.

Note

Across Windows Phone 7 applications, whether Panorama or not, content should align on the left margin at 24px. In general, examine margin values and try to apply margin to the largest container possible in order to achieve alignment while reducing calculations.

A Panorama can have a background image. It is recommended to keep a Panorama background image less than 2,000 pixels wide and 800 pixels in height. If the image is not 800 pixels in height, the image will be stretched automatically without consideration to aspect ratio. The background image should span the entire width of the Panorama control or be a single-colored background. I demonstrate how to add a custom image as well as correct the Title layer positioning in the next section.

Correct Title Position

We start by creating a new project named PanoramaApp using the Windows Phone Panorama Application project template. This template is a fully functioning application that is based on the Panorama control leveraging sample data.

A 2272 wide × 1704 in height photo from a recent vacation is added to the project. We modify the photo to be 800 pixels in height, maintaining aspect ratio, in Paint.NET to prevent stretching the image when the project is debugged. In the emulator, the image fits nicely but the White text doesn't show very well against the image – it needs more contrast. Open the image in any editing too, such as Paint.NET and add a layer that is 30% Black over the entire of the image to provide more contrast with the White text while allowing the background image to show through when the project is run again in the emulator.

Notice though that, when you swipe over to the second pane, part of the text is clipped in the Title, as shown in Figure 2-42. The lower case 'l' and 'I' are clipped at the top.

Clipped Title text

Figure 2.42. Clipped Title text

To fix this, you can modify the control template in Expression Blend. Select the Panorama control, right-click, select Edit Template, Edit a Copy to create a Style resource. Click OK to the dialog box to go into Style editing mode. Select the TitleLayer in the Objects and Timeline Tool Window. Adjust the Top Margin to slide the title down a bit by changing the value from −76 to −68. When you run the application, this puts the top of the 'l' right against the top of the screen to fully display the text. Otherwise, the application behaves just as before.

Image as Title and Themes

Let's say you want to put your company name and logo as the title for a Panorama application. Once again, we can edit the Panorama control's template to create a custom Style to support this. First we add a new wrinkle to the sample code. The image for the Title in the Panorama will be an Apress logo. In the spirit of customizing the design to fit the logo, the Panorama background is changed to a solid color to a yellow similar to Apress' logo yellow.

In Expression Blend, the Device tab shown in Figure 2-43 can help you test out your application by changing the Orientation, Theme, and Accent color at design time. It also allows you to choose to preview the application in the emulator or device.

Device tab in Expression Blend

Figure 2.43. Device tab in Expression Blend

Switching the Theme from the default of Dark to Light changes the font from White to Black. The darker font of the Light theme looks much better; however, this is a setting that a user can change on a whim. By default Windows Phone 7 obey the theme settings automatically because of the default control styles applied to controls.

Applications can override the default theme by setting custom values for Foreground color and the like on individual controls but that can be error prone. A better way to do this is to redefine the built-in Metro styles to force the foreground color to Color.Black regardless of theme setting, making the change in effect for the entire application with just a few lines of code.

In the App Application objectconstructor, remove the pre-defined resource and then add back the resource with modifications. Here is example code to redefine the pre-defined styles:

this.Resources.Remove("PhoneForegroundColor");
this.Resources.Add("PhoneForegroundColor",  Colors.Black);

this.Resources.Remove("PhoneAccentColor");
this.Resources.Add("PhoneAccentColor",Color.FromArgb(200,200,200,200));

this.Resources.Remove("PhoneBackgroundColor");
this.Resources.Add("PhoneBackgroundColor ",  Colors.White);

Now that the resources are redefined to better fit the branding colors, we will now convert the title from a text title to an image. You can make this modification two different ways. The simplest method is to set Panorama.Title to an Image without editing the control template using code like this:

<controls:Panorama.Title>
  <Image Source="images/panorama_title.jpg" Height="80" Width="420" Margin="-20,80"/>
</controls:Panorama.Title>

The other way to modify the Title is to edit the Panorama's TitleTemplate by right-clicking on the Panorama, select Edit Additional Templates, and then Create Empty... to enter template editing mode in Expression Blend. This updates the Panorama's TitleTemplate to point to a resource:

<controls:Panorama  Background="#FFFFCC00"
TitleTemplate="{StaticResource PanoramaTitleDataTemplate}">

Here is the XAML for PanoramaTitleDataTemplate:

<DataTemplate x:Key="PanoramaTitleDataTemplate">
  <Grid>
    <Image HorizontalAlignment="Left" VerticalAlignment="Top"
       Source="images/panorama_title.jpg" Margin="-20,80,0,0"/>
  </Grid>
</DataTemplate>

Dynamic Background Image

A nice application customization is to make the Panorama.Background image dynamic. The Title property can be databound to a Brush type, which can be a png image or color Brush or it could simply be set when the page is Loaded or Activated via a background thread. If the Image is downloaded dynamically, you would not want to perform the download in the main UI thread. For the same reason, the background image could be configured on a Timer control as well.

Programmatically Set the Current PanoramaItem

The Panorama control lands on the most left PanoramaItem by default. Many applications implement a navigation menu on the left most pane but want the user to land on a PanoramaItem with content by default. We modify the PanoramaImageTitle project by adding a PanoramaItem to the left of the two existing PanoramaItem objects and mock up a menu.

The new PanoramaItem is named MenuPanoramaItem. The second PanoramaItem with the first set of content is named DefaultPanoramaItem, and will be displayed when the application first loads. A line of code is added to the MainPage_Loaded event to display the DefaultPanoramaItem upon load:

MainPanorama.DefaultItem = DefaultPanoramaItem;

When the user loads the application, it lands on the content page as before, but when wiping right the user will find the second set of content and then swiping again brings up the menu. The circular page scrolling in the Panorama control makes discoverability of the navigation menu via the menu very easy.

Now that I've discussed the Panorama control, let's switch over to the other major navigation control, the Pivot control.

Pivot

Upon initial examination, the Pivot control appears to be very similar to the Panorama control. It has a title and header, and swipes left and right to view additional content. However, upon closer examination, you will find significant differences. Create a new project and name it PivotApp based on the Windows Phone Pivot Application project template to get started. Figure 2-44 shows the default UI for the PivotApp project.

Visual differences for a Pivot compared with a Panorama

Figure 2.44. Visual differences for a Pivot compared with a Panorama

As you can see in Figure 2-44, there are visual differences compared to the Panorama. Also, note that while the Panorama has "peek" to indicate content to the right, the Pivot control header items show the selected PivotItem in the normal font Foreground color and additional PivotItem controls to the right or left in a faded font Foregroundcolor.

The other significant difference for the Pivot control is that PivotItem objects are dynamically created as they are scrolled to, which is unlike the Panorama control that loads all PanoramaItem objects upfront. This has implications in terms of start-up behavior, page weight, memory consumption, and so on.

Generally, a Pivot control can hold more containers of data than a Panorama control because of the dynamic memory allocation. Also, the Pivot is used more often to present a denser view of content as compared to the Panorama control. I cover additional differences below in the section titled Panorama vs. Pivot.

Pivot Background Image

Like the Panorama control, the Pivot control supports having a Background configured as a Brush (Color or Gradient), as well as an image in the same way that a Panorama can be configured. This includes data binding the background image as well as dynamically loading the image.

Pivot Title Customization

The PivotTitle property can be modified exactly like the Panorama as demonstrated in the section above covering either modifying the TitleTemplate or simply setting the value onto the Title property via element property syntax.

Programmatically Set the Current PivotItem

The Pivot control exposes a SelectedItem property that can be set in order to display a particular PivotItem other than the default leftmost PivotItem. Simply provide a name to the Pivot and PivotItem controls so that they can be identified in code. This code in MainPage_Loaded in MainPage.xaml sets the second PivotItem as the default:

MainPivot.SelectedItem = SecondPivotItem;

In the next section I conclude this chapter with a comparison of the Pivot Control vs. the Panorama control.

Pivot vs. Panorama

As mentioned, the Panorama and Pivot controls have a lot in common in terms of base functionality. Both controls mimic the built-in native control versions in terms of behavior and animations yet provide a simple programming interface with strong customization available. The controls include built-in touch navigation with support for flick and pan for a great navigation experience.

From a programming standpoint both controls function like tab controls with an Items collection for either Panorama or PivotItem controls allowing rich content presentation in compact amount of space. Both controls allow the developer to focus on building the content within the Item control panes, which is usually a matter of customizing a ListBox control, greatly simplifying programming tasks while providing a rich user experience.

The controls themselves can be data bound with content template properties and item container styles for the Title, Header, and Item Panel, and so on. The controls also include full Blend support such as control template modification and visual states.

In terms of usage, the vast majority of Windows Phone 7 Silverlight applications will open to an initial page containing either a Panorama or Pivot control. For rich initial content presentation, the Panorama control is usually the better choice. For denser content presentation, or larger amounts of content, the Pivot control is ideal.

Many applications will consist of a root Panorama control with a PanoramaItem dedicated to a menu. The menu items then use the navigation framework to navigate the UI to sub-pages consisting of Pivot controls or plain old page depending on content needs. The hardware Back button provides navigation back to the root Panorama control and is in incredibly important part of the navigation framework.

Conclusion

In this chapter I provide a sweeping overview of the Silverlight user experience controls starting with layout controls, data binding, and a demonstration of how to take advantage of sample data. I then move on to a discussion of control templates and an overview of animation in Expression Blend. In the last section I cover an overview of the Panorama and Pivot controls, which are the major navigation controls in Windows Phone 7. In the next chapter I will cover input on Windows Phone 7.

..................Content has been hidden....................

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