You are on page 1of 305

O F F I C I A L

M I C R O S O F T

L E A R N I N G

P R O D U C T

10554A and Lab Answer Key: Lab Instructions


Developing Rich Internet Applications Using Microsoft Silverlight 4

Information in this document, including URL and other website references, is subject to change without notice. Unless otherwise noted, the example companies, organizations, products, domain names, email addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, email address, logo, person, place, or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation. Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property. The names of manufacturers, products, or URLs are provided for informational purposes only and Microsoft makes no representations and warranties, either expressed, implied, or statutory, regarding these manufacturers or the use of the products with any Microsoft technologies. The inclusion of a manufacturer or product does not imply endorsement of Microsoft of the manufacturer or product. Links may be provided to third party sites. Such sites are not under the control of Microsoft and Microsoft is not responsible for the contents of any linked site or any link contained in a linked site, or any changes or updates to such sites. Microsoft is not responsible for webcasting or any other form of transmission received from any linked site. Microsoft is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement of Microsoft of the site or the products contained therein. 2011 Microsoft Corporation. All rights reserved. Microsoft, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. All other trademarks are property of their respective owners.

Product Number: 10554A Part Number: X17-91364 Released: 09/2011

Lab Instructions: Introduction to Building Silverlight Business Applications

Module 1
Lab Instructions: Introduction to Building Silverlight Business Applications
Contents:
Exercise 1: Creating a Silverlight Application 4 Exercise 2: Configuring Out-of-Browser settings for the Silverlight Application 7

Lab Instructions: Introduction to Building Silverlight Business Applications

Lab: Building Silverlight Business Applications

Lab Introduction
In this lab, you will create a new Silverlight application based on the Silverlight Business Application project template, and you will modify application resource strings for the solution. You will also experiment with the WCF RIA services that provide authentication and user registration functionality to the Silverlight application. Then, you will configure the application for running outside the browser, including setting elevated trust requirements, and you will experiment with the various installation and uninstallation processes. Finally, you will add code for detecting when the application is running outside the browser and will develop code that enables the user to close the application. The exercises for this lab are: Exercise 1: Creating a Silverlight Application Exercise 2: Configuring Out-of-Browser settings for the Silverlight Application

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Instructions: Introduction to Building Silverlight Business Applications

Lab Start State


There is no starter solution for this lab. You will start by creating a new Silverlight project.

Lab End State


At the end of the lab, your new Silverlight application will use Windows authentication to log on users, and will run outside the browser with a Borderless Round Corners window style. Therefore, it will include a close button that users will click to close the application Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed, working code is available in the Solution folders under the Labfiles folder for each lab exercise on the virtual machine.

Lab Instructions: Introduction to Building Silverlight Business Applications

Exercise 1: Creating a Silverlight Application


Task 1: Create a new project.
Open Microsoft Visual Studio 2010. Create a new Silverlight Business application, named GreetingCardManagement, in the D:\Labfiles\Mod01\VB\Starter or D:\Labfiles\Mod01\CS\Starter folder, by using the Silverlight Business Application template. A Silverlight project named GreetingCardManagement is created. A website named, GreetingCardManagement.Web, for hosting the Silverlight application and its services is also created.

Task 2: Test and examine the authentication and User Registration Services of the Silverlight application.
Start the application. Review the content on the Home page. Review the content on the About page. Log on by registering a new user with the following information. User name: KimA Friendly name: Kim Abercrombie Email: KimA@contoso.com Password: Pa$$w0rd Confirm password: Pa$$w0rd Security question: What is your pets name? Security answer: Buster

You are registered through the built-in authentication services provided by the application, and you are logged on to the application. The authentication is handled by the WCF service in the GreetingCardManagement.Web hosting application. Note that the application displays a welcome message that uses the friendly name you specified. Log off from the site. Note that the application welcome message is removed as is the friendly user name. Close Internet Explorer. Examine the Services\AuthenticationService.vb or Services\AuthenticationService.cs code file in the GreetingCardManagement.Web project. Notice how the AuthenticationService class is annotated with the EnableClientAccess attribute, to enable the Silverlight application to access it. The AuthenticationService class is derived from the generic AuthenticationBase(Of T) or AuthenticationBase<T> class, which in turn implements the generic AuthenticationBase<T> interface. The type of the user entity to authenticate is specified using T.

Lab Instructions: Introduction to Building Silverlight Business Applications

Examine the user entity, named User, by going to the definition of the class User. Notice how the User class in the User.shared.vb or User.shared.cs file is partial, because it extends the User type by adding shared properties and methods that are available both to the server application and the client application, Silverlight, in this case. The User class implements the DisplayName property

Examine the main partial class User, in the Models folder. Note how the main partial class User is derived from the UserBase class, and implements the FriendlyName property.

Examine the Services\UserRegistrationService.vb or Services\UserRegistrationService.cs code file in the GreetingCardManagement.Web project. Notice how the UserRegistrationService class is also annotated with the EnableClientAccess attribute. The UserRegistrationService class is derived from the abstract DomainService class, which is the base class for all System.ServiceModel.DomainServices.Server.DomainServices. The UserRegistrationService class uses the ASP.NET Membership and Roles API to provide the user registration services.

Examine the content of the App_Data folder in the GreetingCardManagement.Web project. Notice how the ASPNETDB.MDF SQL Server Express database is located in the App_Data folder. It was automatically created when you used the user registration services as part of creating or registering a new user.

Task 3: Modify the authentication mode of the Silverlight application.


Examine the Web.config file in the GreetingCardManagement.Web project. Locate the authentication element. Edit the authentication element so that it reads as follows.
<authentication mode="Windows"> </authentication >

Save the changes. Start the application. Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. Note that you are logged on automatically as 10554A-SEA-DEV\Student because you have configured the website to use Windows authentication.

Log off from the site. A custom dialog box with an error message appears, because it is not supported to log off from a Windows-authenticated application.

Close the custom error dialog box. Close Internet Explorer. Open the App.xaml.vb or App.xaml.cs code file in the GreetingCardManagement project. In the App class constructor, comment out the line of code that initializes forms authentication.

Lab Instructions: Introduction to Building Silverlight Business Applications

In the App class constructor, uncomment the line of code that initializes Windows authentication. Save the changes. Start the application. Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. Note that you are logged on automatically as 10554A-SEA-DEV\Student because you have configured the website to use Windows authentication. Note also that the logout link is no longer available, because you have configured the Silverlight application to correctly use Windows authentication.

Close Internet Explorer.

Lab Instructions: Introduction to Building Silverlight Business Applications

Exercise 2: Configuring Out-of-Browser settings for the Silverlight Application


Task 1: Control basic out-of-browser settings.
Hint Refer to the "Out-of-Browser Settings" topic in Lesson 3, "Developing Out-ofBrowser Applications with Silverlight". Open the Project Designer for the GreetingCardManagement project. Enable the application to run outside the browser. Set the following out-of-browser settings: Window Title: GreetingCard Desktop Management Width: 600 Height: 400 Set window location manually: selected Top: 100 Left: 100 Shortcut name: GreetingCard Desktop Management Show install menu: selected

Start the application. Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. The application is still running in the browser.

Install the application locally, and add shortcuts to the Start menu and the desktop. The application opens in its own window.

Close Internet Explorer. The application continues to run in its own window.

Close the GreetingCard Desktop Management localhost window. On the Start menu, click All Programs, and then click GreetingCard Desktop Management. The application opens directly in its own window.

Remove the locally installed application, by using the context menu.

Task 2: Control enhanced out-of-browser settings.


When running the GreetingCardManagement application out-of-browser, require elevated trust, and use round corners for the application border. Use the Silverlight page in the Project Designer for this task.

Lab Instructions: Introduction to Building Silverlight Business Applications

Task 3: Provide an Exit button for the out-of-browser mode.


Hint Refer to the "Closing Out-of-Browser Applications Programmatically" topic in Lesson 3, "Developing Out-of-Browser Applications with Silverlight". Open the MainPage.xaml form. In the XAML view, locate the HyperlinkButton control with a name of Link2. Immediately below the Link2 element, add the following markup.
<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="closeLink" Style="{StaticResource LinkStyle}" Content="Exit" Visibility="Collapsed"/>

Create an event handler for the Click event of the closeLink HyperlinkButton control. [Visual C# only] Visual Studio adds a Click attribute to the markup for the HyperlinkButton control. Visual Studio creates the event handler stub for the event, and the code file appears.

In the Click event handler, close the MainWindow form by using the App.Current property. Save the changes.

Task 4: Control Exit button visibility for the out-of-browser mode.


Hint Refer to the "Detecting Out-of-Browser Environments" topic in Lesson 3, "Developing Out-of-Browser Applications with Silverlight". In the MainPage class, in the constructor, append code to check if the application is running out-ofbrowser, and with elevated trust, by using the App.Current property. If so, make the closeLink HyperlinkButton control visible. Save the changes. Start the application. Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. The application is still running in the browser. Note that the Exit button is not visible. Install the application locally, add shortcuts to the Start menu and the desktop, and accept the security advice. Because the application now requests elevated trust when it runs outside the browser, Internet Explorer displays a security warning dialog box. The application opens in its own window, with a rounded borderless style. Note that the Exit button is visible. Close Internet Explorer. The application continues to run in its own window. Close the application.

Lab Instructions: Introduction to Building Silverlight Business Applications

Close Visual Studio.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Building Data-Driven Applications

Module 2
Lab Instructions: Building Data-Driven Applications
Contents:
Exercise 1: Connecting to a Database in a Silverlight Project Exercise 2: Querying and Displaying Data from a Database 4 5

Lab Instructions: Building Data-Driven Applications

Lab: Consuming Data

Lab Introduction
In this lab, you will be accessing database data by using the Entity Framework. You will add ADO.NET Entity Data Models to the GreetingCardManagement solution that is used by employees of the site. In the GreetingCardManagement solution, you will implement read-only data access for reporting purposes, but you will customize the data access by modifying the default queries in the Domain Service class. You will develop this solution to include data-bound controls and grid views, along with data paging, to build a master-detail view of the registered senders in the site and the details of the cards that they have sent. The exercises for this lab are: Exercise 1: Connecting to a Database in a Silverlight Project Exercise 2: Querying and Displaying Data from a Database

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


There is a starter solution for this lab that represents a model solution for the GreetingCardManagement solution from the previous lab. You will start by working with the GreetingCardManagement solution. No data access has yet been configured for this starter solution.

Lab Instructions: Building Data-Driven Applications

Lab End State


At the end of the lab, the GreetingCardManagement solution will include database access through the Entity Framework. Essentially, it will show each of the registered senders in the site and the cards they have sent in a master-detail view. This view will include the ability to page through the sender data. In this solution, the data will be read-only because it is essentially a reporting application for consumer activity. Note: Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed, working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Lab Instructions: Building Data-Driven Applications

Exercise 1: Connecting to a Database in a Silverlight Project


Task 1: Open the GreetingCardManagement Starter solution.
Open Visual Studio 2010. Open the GreetingCardManagement solution from the D:\Labfiles\Mod02\VB\Starter or D:\Labfiles\Mod02\CS\Starter folder. Build the solution. Briefly review the solutionit is very similar to the completed solution that you created for Lab 1. The solution consists of a simple Silverlight project and an ASP.NET Web application for hosting the Silverlight application and for providing WCF RIA Services.

Task 2: Add an ADO.NET Entity Data Model to GreetingCardManagement.Web.


To the GreetingCardManagement.Web project, add a new ADO.NET Entity Data Model named GreetingCardManagementEntities. The Entity Data Model Wizard appears. In the Entity Data Model Wizard, ensure that Generate from database is selected, and then click Next. Create a new connection to the 10554A-SEA-DEV\SQLEXPRESS SQL Server instance and the GreetingCard database. Ensure that the connection settings are saved to Web.config as GreetingCardEntities, and then move to the next page. Select the Card (dbo) and Sender (dbo) tables. Ensure that the Model Namespace box reads GreetingCardModel, and then click Finish. The ADO.NET Entity Data Model Designer appears and displays the tables and the relationship between them. Save the changes. Build the GreetingCardManagement.Web project. Hint: Refer to Lesson 2 for details on adding ADO.NET Entity Data Models to a solution.

Task 3: Add GreetingCardManagementDomainService Domain Service class.


To the GreetingCardManagement.Web project, add a Domain Service class named GreetingCardManagementDomainService. The Add New Domain Service Class wizard appears. For the GreetingCardManagementDomainService class, have the Add New Domain Service Class wizard generate associated metadata for the Card and Sender entities in the GreetingCardEntities collection, but do not enable editing of these entities. Leave Visual Studio runningyou will work with the data objects you have just created in the next exercise. Hint: Refer to Lesson 3 for details on adding Domain Service classes to a solution.

Lab Instructions: Building Data-Driven Applications

Exercise 2: Querying and Displaying Data from a Database


Task 1: Edit the GetSenders query in the Domain Service class.
Modify the code in the GetSenders method so that it reads:
[Visual Basic] Return Me.ObjectContext.Senders.Include("Cards") _ .OrderBy(Function(sender) sender.Email)

[Visual C#] return this.ObjectContext.Senders.Include("Cards") .OrderBy(sender => sender.Email);

Save the changes. Hint: Refer to the topic, Customizing Domain Services Queries for an example of how to sort data.

Task 2: Edit the SenderMetadata class.


In the GreetingCardManagement.Web project, open the GreetingCardManagementDomainService.metadata.vb or GreetingCardManagementDomainService.metadata.cs code file. Locate the following property declaration in the SenderMetadata class.
[Visual Basic] Public Property Cards As EntityCollection(Of Card)

[Visual C#] public EntityCollection<Card> Cards { get; set; }

Add the following property attribute immediately above the property you have just located.
[Visual Basic] <Include()>

[Visual C#] [Include]

Save the changes. Hint: Refer to the topic, Customizing Domain Services Queries for an example of how to use the Include function.

Lab Instructions: Building Data-Driven Applications

Task 3: Add data controls for senders data to the Silverlight application.
In the Views folder, open Home.xaml. Delete the Home TextBlock control. Delete the Home page content TextBlock control. Show the data sources for the GreetingCardManagement project. To show the data in master-details view, in the Data Sources window, select the details for the Sender entity. Drag the Sender item from the Data Sources window to the upper-left corner of Home.xaml in Design view. Delete the User ID grid row. Hint: Right-click the User ID label and then use the context menu to delete the row. In the Data Sources window, expand the Sender item, drag the Cards sub-item to Home.xaml in Design view and drop it below the Sender data you just added. Note: Ensure that you drag the Cards item that belongs to Sender, and not the top-level Card item. Open the editor for the columns collection of the DataGrid control for the Cards data. In the Collection Editor: Columns dialog box, remove the CardGuidColumn or cardGuidColumn, CardIDColumn or cardIDColumn, and SenderIDColumn or senderIDColumn DataGridTextColumn objects from the list on the left. Move up the RecipientEmailColumn or recipientEmailColumn DataGridTextColumn object on the list on the left. Show the Layout section for RecipientEmailColumn or recipientEmailColumn DataGridTextColumn. Set the following property value for RecipientEmailColumn or recipientEmailColumn DataGridTextColumn in the Layout section. Width: 300 Pixel

Show the Layout section for CardDataColumn or cardDataColumn DataGridTextColumn. Set the following property value for CardDataColumn or cardDataColumn DataGridTextColumn in the Layout section. Width: 295 Pixel

Close the Collection Editor: Columns dialog box, saving the changes. In the Properties window, set the following property values for the DataGrid control. Width: 600 HorizontalAlignment: Left VerticalAlignment: Top

Lab Instructions: Building Data-Driven Applications

Task 4: Add paging controls for senders data to the Silverlight application.
In the XAML window, locate the markup that begins with the following code.
<sdk:DataGrid

Insert a blank line immediately above the markup you have just located. Drag a DataPager control from the All Silverlight Controls section of the toolbox to the XAML window, where you just added a blank line. Review the markup for the DataPager control. A DataPager control is added to the XAML window, and to the design surface (between the Sender data and the Card grid). Arrange the data controls so that they resemble the following image.

From the Data Sources window, drag Sender and drop it on the DataPager control. Review the modified markup for the DataPager control and note that a Source element has been added that binds the DataPager to the Sender data. In the Properties window, set the following property values for the DataPager control. PageSize: 1 DisplayMode: FirstLastPreviousNextNumeric

Hint Refer to the Implementing Master-Detail Views of Data from Domain Services topic for details on how to bind a DataPager control. Save the changes.

Task 5: Test the data-driven application.


Start the application. Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site.

Lab Instructions: Building Data-Driven Applications

Review the sender data that is displayed, and then use the DataPager control to navigate through the data. Note how Card Data updates when different Senders are displayed. Close Internet Explorer. Close Visual Studio.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Advanced Data Management

Module 3
Lab Instructions: Advanced Data Management
Contents:
Exercise 1: Implementing Full Read-Write Scenarios 3

Lab Instructions: Advanced Data Management

Lab: Manipulating Data

Lab Introduction
In this lab, you will be modifying database data by using the Entity Framework. You will add an ADO.NET Entity Data Model to the GreetingCardConsumer solution that is used by site visitors. In the GreetingCardConsumer solution, you will also modify the default queries in the Domain Service class, which will restrict the data to the currently logged on user. You will also implement write operations for the data to add newly registered site users as senders in the GreetingCard database. Finally, you will implement an edit-and-save scenario that enables the currently logged on user to make changes to their email address or display name, and have those changes persisted in the database. The exercises for this lab are: Exercise 1: Implementing Full Read-Write Scenarios

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


There is no starter solution for this lab, but you will create a new solution as part of the lab. This solution will represent the consumers view of the GreetingCard scenario. Because you will be creating this solution, there is no starter solution for this consumer application.

Lab Instructions: Advanced Data Management

Lab End State


The GreetingCardConsumer solution that you will create, however, will implement read-write database access by using the Entity Framework. The read operations will involve restricting the data to that which belongs to the currently-logged on user. The data modification operations will include two different concepts: The first will be to add newly registered site users as senders in the GreetingCard database and the second will enable an edit-and-save scenario that enables the currently-logged on user to make changes to their email address or display name.

Exercise 1: Implementing Full Read-Write Scenarios


Task 1: Create the GreetingCardConsumer Application.
Open Microsoft Visual Studio 2010. Create a new Silverlight Business application named GreetingCardConsumer in the D:\Labfiles\Mod03\VB\Starter or D:\Labfiles\Mod03\CS\Starter folder, by using the Silverlight Business Application template. A Silverlight project named GreetingCardConsumer is created. A website named GreetingCardConsumer.Web for hosting the Silverlight application and its services is also created.

Task 2: Configure Silverlight Application Resources.


In the GreetingCardConsumer project, open the Resource Designer for the Assets\Resources\ApplicationStrings.resx resource file. The Resource Designer opens displaying a three-column grid containing the resource strings in the ApplicationStrings.resx resource file. Replace the value Application Name, with Greeting Card Consumer. Save the changes. Close the Resource Designer.

Task 3: Configure User Name to be an Email Address.


In the GreetingCardConsumer.Web project, open the Models\RegistrationData model code file. Locate the UserName property declaration. The RegularExpression attribute for the UserName property declaration currently reads:
"^[a-zA-Z0-9_]*$"

Edit the expression above so that it reads:


[Visual Basic] "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[09]{1,3})(\]?)$"

[Visual C#] @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[09]{1,3})(\]?)$"

You should type this expression all on a single line. It represents a pattern match for a valid email address.

Lab Instructions: Advanced Data Management

Hint You can copy the expression from the Email property, which is located just below the UserName property. In the GreetingCardConsumer.Web project, open the Resource Designer for the Resources\ValidationErrorResources.resx resource file. The Resource Designer opens displaying a three-column grid containing the resource strings in the ValidationErrorResources.resx resource file. In the row with a Name column value of ValidationErrorInvalidUserName, replace the content of the Value column with Invalid user name. You must use a valid email address. Save the changes. Close the Resource Designer.

Task 4: Add an existing ADO.NET Entity Data Model to GreetingCardConsumer.Web.


Add the existing ADO.NET Entity Data Model, GreetingCardModel, located in the D:\Labfiles\Mod03 folder, to GreetingCardConsumer.Web project. Build the GreetingCardConsumer.Web project.

Task 5: Update Entity Data Model.


In the GreetingCardConsumer.Web project, open the GreetingCardModel entity data model. Update the data model from database. The Update Wizard appears. Create a new connection to the 10554A-SEA-DEV\SQLEXPRESS SQL Server instance and the GreetingCard database. In the Update Wizard, on the Choose Your Data Connection, click Next. The connection string will now be saved to the Web.config file. Finish the Update Wizard, on the Choose Your Database Objects, click Finish. Save and close the GreetingCardModel entity data model. Build the solution.

Task 6: Add a Domain Service Class to GreetingCardConsumer.Web.


To theGreetingCardConsumer.Web project, add a Domain Service Class named GreetingCardConsumerDomainService. The Add New Domain Service Class wizard appears. For the GreetingCardConsumerDomainService class, have the Add New Domain Service Class wizard generate associated metadata for the Card and Sender entities in the GreetingCardEntities collection, and enable editing of these entities.

Task 7: Edit the GetSenders Query in the Domain Service Class to Restrict Data to the Current User.
In the GreetingCardConsumerDomainService code file, modify the code in the GetSenders method so that it reads:

Lab Instructions: Advanced Data Management

[Visual Basic] Dim userName As String = System.Web.HttpContext.Current.User.Identity.Name Return Me.ObjectContext.Senders.Include("Cards") _ .Where(Function(sndr) sndr.Email = userName)

[Visual C#] string userName = System.Web.HttpContext.Current.User.Identity.Name; return this.ObjectContext.Senders.Include("Cards") .Where(sndr => sndr.Email == userName);

Save the changes.

Task 8: Edit the SenderMetadata Class.


In the GreetingCardConsumer.Web project, open the GreetingCardConsumerDomainService.metadata code file. Locate the Cards property declaration in the SenderMetadata class. Add the Include attribute to the Cards property declaration. Save the changes.

Task 9: Add Data Controls for Senders Data to the Silverlight Application.
To the GreetingCardConsumer project, add a new Silverlight Page named Details to the Views folder. In the GreetingCardConsumer project, open MainPage.xaml. In MainPage.xaml, in the XAML view, locate the markup that begins <HyperlinkButton x:Name="Link2". Immediately above the located markup, add a new self-closing HyperlinkButton control element named Details. Set the following properties: Property Value Your Details /Details {StaticResource LinkStyle} ContentFrame

Property Name Content NavigateUri Style TargetName

The NavigateUri property specifies that when a user clicks the HyperlinkButton control, it should navigate to the Details.xaml page, by using a relative uri (/Details). The TargetFrame property specifies that the content available at the NavigateUri should be displayed in the ContentFrame navigation frame. This is part of the navigation automatically provided when creating a Silverlight Business Application. Immediately below the DetailsHyperlinkButton control, add a new self-closing Rectangle control element named DetailsDivider. Set the following property: Property Name Property Value

Lab Instructions: Advanced Data Management

Property Name Style Switch back to Details.xaml. Build the solution.

Property Value {StaticResource DividerStyle}

In Details.xaml, in the XAML view, select all the markup, and then type in the following markup or copy from the D:\Labfiles\Mod03\VB\DetailsMarkup.txt or D:\Labfiles\Mod03\CS\DetailsMarkup.txt file, and paste it in:
[Visual Basic] <navigation:Page x:Class="GreetingCardConsumer.Details" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Details Page" xmlns:riaControls="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:GreetingCardConsumer" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <sdk:Page.Resources> <CollectionViewSource x:Key="SenderCardsViewSource" Source="{Binding Path=Data.Cards, ElementName=SenderDomainDataSource}" /> </sdk:Page.Resources> <Grid x:Name="LayoutRoot"> <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Sender, CreateList=true}" Height="0" Name="SenderDomainDataSource" QueryName="GetSendersQuery" Width="0"> <riaControls:DomainDataSource.DomainContext> <my:GreetingCardConsumerDomainContext /> </riaControls:DomainDataSource.DomainContext> </riaControls:DomainDataSource> <Grid DataContext="{Binding ElementName=SenderDomainDataSource, Path=Data}" HorizontalAlignment="Left" Margin="12,12,0,0" Name="Grid1" VerticalAlignment="Top" Height="66" Width="220"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <sdk:Label Content="Display Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="DisplayNameTextBox" Text="{Binding Path=DisplayName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> <sdk:Label Content="Email:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="EmailTextBox" Text="{Binding Path=Email, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> </Grid> <sdk:DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource

Lab Instructions: Advanced Data Management

SenderCardsViewSource}}" Margin="12,84,0,0" Name="CardsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="600"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="RecipientEmailColumn" Binding="{Binding Path=RecipientEmail}" Header="Recipient Email" Width="300" /> <sdk:DataGridTextColumn x:Name="CardDataColumn" Binding="{Binding Path=CardData}" Header="Card Data" Width="295" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </Grid> </navigation:Page>

[Visual C#] <navigation:Page x:Class="GreetingCardConsumer.Details" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Details Page" xmlns:riaControls="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:GreetingCardConsumer.Web" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <sdk:Page.Resources> <CollectionViewSource x:Key="SenderCardsViewSource" Source="{Binding Path=Data.Cards, ElementName=SenderDomainDataSource}" /> </sdk:Page.Resources> <Grid x:Name="LayoutRoot"> <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Sender, CreateList=true}" Height="0" Name="SenderDomainDataSource" QueryName="GetSendersQuery" Width="0"> <riaControls:DomainDataSource.DomainContext> <my:GreetingCardConsumerDomainContext /> </riaControls:DomainDataSource.DomainContext> </riaControls:DomainDataSource> <Grid DataContext="{Binding ElementName=SenderDomainDataSource, Path=Data}" HorizontalAlignment="Left" Margin="12,12,0,0" Name="Grid1" VerticalAlignment="Top" Height="66" Width="220"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <sdk:Label Content="Display Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="DisplayNameTextBox" Text="{Binding Path=DisplayName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> <sdk:Label Content="Email:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="EmailTextBox" Text="{Binding Path=Email, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> </Grid>

Lab Instructions: Advanced Data Management

<sdk:DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource SenderCardsViewSource}}" Margin="12,84,0,0" Name="CardsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="600"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="RecipientEmailColumn" Binding="{Binding Path=RecipientEmail}" Header="Recipient Email" Width="300" /> <sdk:DataGridTextColumn x:Name="CardDataColumn" Binding="{Binding Path=CardData}" Header="Card Data" Width="295" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </Grid> </navigation:Page>

In the GreetingCardConsumer project, add a reference to the System.Windows.Controls.Data and System.Windows.Controls.DomainServices assemblies. Build the solution.

Task 10: Develop Code to Add Newly Registered Users to the GreetingCard Database.
In the GreetingCardConsumer project, open Views\Login\RegistrationForm.xaml in Code view. In the RegistrationForm class, locate the RegisterButton_Click event handler. Append code to the If/if block in the event handler to create and instantiate an instance of the GreetingCardConsumerDomainContext class, create and instantiate an instance of the Sender class. Set the Email property of the sender instance to the value of the local registrationData.UserName, set the DisplayName property of the sender instance to the value of the local registrationData.FriendlyName and add the sender instance to the Senders collection property of the GreetingCardConsumerDomainContext instance. Finally, use the GreetingCardConsumerDomainContext instance, to submit the changes. Save the changes.

Task 11: Implement Edit-and-Save Operations for Database Data.


In the GreetingCardConsumer project, add a new folder named Images to the Assets folder. Add the existing D:\Labfiles\Mod03\HeadPhoto.png image file to the Images folder. Switch back to Details.xaml. Disable the two TextBox controls. In the XAML view of Details.xaml, locate the markup that begins as follows:
<sdk:DataGrid

Insert an empty line above the markup that you located. Add the following markup to the space you have just created. You can type in the markup manually, or you can copy from the D:\Labfiles\Mod03\EditDetailsMarkup.txt file, and paste it in.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Border BorderBrush="Silver" BorderThickness="2" Height="70" Margin="10" Name="editDetails" Width="50" CornerRadius="10" VerticalAlignment="Top" Cursor="Hand"> <StackPanel Orientation="Vertical">

Lab Instructions: Advanced Data Management

<Border CornerRadius="10,10,0,0" Height="50"> <Border.Background> <ImageBrush ImageSource="/GreetingCardConsumer;component/Assets/Images/HeadPhoto.png"/> </Border.Background> </Border> <ContentControl Height="20" Content="Edit" HorizontalAlignment="Center" Background="Silver"/> </StackPanel> </Border> <StackPanel Orientation="Vertical" VerticalAlignment="Top" Margin="10" HorizontalAlignment="Left" x:Name="editControls" Visibility="Collapsed"> <Button x:Name="saveChanges" Content="Save" Width="50" Margin="5" Cursor="Hand"/> <Button x:Name="cancelChanges" Content="Cancel" Width="50" Margin="5" Cursor="Hand"/> </StackPanel> </StackPanel>

The markup adds controls for editing the details, wrapped a StackPanel control, which contains controls for displaying the image you added previously, and controls for saving or cancelling the changes. Save the changes. Add an event handler for the MouseLeftButtonDown event of the editDetailsBorder control. Add code to the event handler to check if the name of the current user, WebContext.Current.User.Name, is null or empty. If so, create and display a new error window, using the ErrorWindow.CreateNew method, displaying the message, You must log in to edit your data, but never show the stack trace. In addition, exit the method, if the name of the current user is null or empty. Otherwise, enable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Collapsed, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Visible. Switch back to the XAML view of Details.xaml. Add an event handler for the Click event of the saveChangesButton control. Add code to the event handler to use the SenderDomainDataSource or senderDomainDataSource object to submit the changes. Wrap the code in a Try...Catch...Finally or try...catch...finally construct, with just one general Catch or catch (Exception). If an exception is thrown, use the SenderDomainDataSource or senderDomainDataSource object to reject the changes, create and display a new error window, using the ErrorWindow.CreateNew method, displaying the message, The following problem occurred when attempting to save your changes, but never show the stack trace. To the error message, append content of the Message property of the caught exception. In the Finally or finally part, disable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Visible, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Collapsed. Switch back to the XAML view of Details.xaml. Add an event handler for the Click event of the cancelChangesButton control.

10

Lab Instructions: Advanced Data Management

Add code to the event handler to disable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Visible, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Collapsed. Finally, use the SenderDomainDataSource or senderDomainDataSource object to reject the changes. Save the changes.

Task 12: Test Data Operations in the Silverlight Application.


Open Microsoft SQL Server Management Studio as administrator. Connect to the 10554A-SEA-DEV\SQLEXPRESS SQL Server Instance. Locate the GreetingCard database. Show the tables for the GreetingCard database. View the first 1000 rows of the Sender table. Notice the 10 rows of users or senders in the Results window. Leave Microsoft SQL Server Management Studio running Switch back to Visual Studio. Start the application. Click Your Details. Click Edit. Note box. The error message, for which you wrote the validation for, is displayed in a dialog

Close the dialog box. Go to Home page Log in by registering a new user with the following information. User name: GregG Friendly name: Greg Guzik Email: GregG@contoso.com Password: Pa$$w0rd Confirm password: Pa$$w0rd Security question: What is your pets name? Security answer: Lily

Note that you cannot register because the user name must be a valid email address. You set this validation earlier. Change the user name to GregG@contoso.com, and register You are registered through the built-in authentication services provided by the application, and you are logged into the application. Leave Internet Explorer running.

Lab Instructions: Advanced Data Management

11

Switch back to Microsoft SQL Server Management Studio. On the Query menu, click Execute. The data refreshes and shows a new sender for the user you just registered in the Silverlight application.

Switch back to Internet Explorer. Go to Home page. Edit the details for the current user. Change the display name to Gregory, and save the change. Switch back to Microsoft SQL Server Management Studio. Rerun the top 1000 query. The data refreshes and shows the updated DisplayName for Gregory.

Close all applications. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Implementing User Controls and Navigation

Module 4
Lab Instructions: Implementing User Controls and Navigation
Contents:
Exercise 1: Adding a Navigation User Control Exercise 2: Updating the Number of Cards Periodically 4 6

Lab Instructions: Implementing User Controls and Navigation

Lab: Implementing User Controls and Navigation

Lab Introduction
In this lab, in the GreetingCardManagement solution, you will be creating a new user control for containing the navigation controls displayed to the user. The controls and code from the main user control will be moved to the new user control, which will be inserted into the main user control. You will add markup and code to the Home page to retrieve and display the number of cards in the database, at a regular interval. In the GreetingCardManagement.Web solution, you will add a new method for returning the number of rows in the Cards entity. The exercises for this lab are: Exercise 1: Adding a Navigation User Control Exercise 2: Updating the Number of Cards Periodically

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


The starter solution for this lab is a slightly modified version of the solution code for Module 2, the GreetingCardManagement solution.

Lab Instructions: Implementing User Controls and Navigation

Lab End State


The modified GreetingCardManagement solution will contain a new NavigationSidebar user control, which can be added or moved to different top-level user controls in different Silverlight projects. The Home page retrieves and displays the number of cards in the database at a regular interval by using the DispatcherTimer and Dispatcher objects for background threading. Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed, working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Lab Instructions: Implementing User Controls and Navigation

Exercise 1: Adding a Navigation User Control


Task 1: Open the GreetingCardManagement starter solution.
Open Visual Studio 2010. Open the GreetingCardManagement solution from the D:\Labfiles\Mod04\VB\Starter or D:\Labfiles\Mod04\CS\Starter folder. The solution consists of a simple Silverlight project and an ASP.NET Web application for hosting the Silverlight application and for providing Windows Communication Foundation (WCF) Rich Internet Applications (RIA) services. This is the solution code from Module 2.

Task 2: Create a new user control.


Add a new user control named NavigationSidebar to the GreetingCardManagement project, in the Views folder. Remove the standard white background from the Grid control. Save the changes.

Task 3: Move navigation controls.


In the GreetingCardManagement project, open the MainPage XAML file. Locate the Border control named LinksBorder. Select and cut the LinksBorder control, including the content. Format the MainPage.xaml document. Switch to the NavigationSidebar.xaml file. Locate the Grid control named LayoutRoot. Insert the cut markup between the opening and closing tags of the Grid control. Format the NavigationSidebar.xaml document. Save the changes. Open the NavigationSidebar.xaml code-behind file. Open the MainPage.xaml code-behind file. Locate the closeLink_Click event handler. Select and cut the closeLink_Click event handler definition and code. Switch to the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs file. Append the cut code at the end of NavigationSidebar class. Switch to the MainPage.xaml.vb or MainPage.xaml.cs file. Locate the constructor. Select and cut the constructor code that accesses the closeLink control. The code that accesses the closeLink control must be moved to the same file as the closeLink control. Switch to the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs file.

Lab Instructions: Implementing User Controls and Navigation

Locate the constructor. Append the cut code. Save the changes.

Task 4: Insert NavigationSidebar user control in MainPage.


Switch to the MainPage.xaml file. Add the XML namespace named local for the GreetingCardManagement or GreetingCardManagement.Views CLR namespace to the GreetingCardManagement.MainPage UserControl.
[Visual Basic] xmlns:local="clr-namespace:GreetingCardManagement"

[Visual C#] xmlns:local="clr-namespace:GreetingCardManagement.Views"

Append the NavigationSidebar user control with default values to the NavigationGrid Grid control. Name the control NavigationSidebar.
<local:NavigationSidebar x:Name="NavigationSidebar" />

Switch to the MainPage.xaml.vb or MainPage.xaml.cs file. If you are developing in Visual C#, bring the GreetingCardManagement.Views namespace into scope. Locate the ContentFrame_Navigated event handler. In the ContentFrame_Navigated event handler, add code to create a new StackPanel control named linkStackPanel, and assign the value of the LinksStackPanel control in the NavigationSidebar user control. You can use the FindName method of the UIElement class. In the ContentFrame_Navigated event handler, in the For Each/foreach loop, change the name of the control being iterated from LinksStackPanel to linkStackPanel. The code in the top-level user control correctly changes the visual state of the HyperlinkButton controls, now contained in the child NavigationSidebar user control.

Build the solution. Run the application. Check that the navigation controls are still displayed in the upper-right corner. Close Internet Explorer.

Lab Instructions: Implementing User Controls and Navigation

Exercise 2: Updating the Number of Cards Periodically


Task 1: Create a domain service method.
In the GreetingCardManagement.Web project, open the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs code file. Add a public method named GetCardCount that returns an Integer/int. Add the method after the existing GetCards method. To the public GetCardCount method, add code to return the number of rows in the Cards entity by using a LINQ query selecting on the CardID column. Save and close the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs file.

Task 2: Add a display control to the Home page.


In the GreetingCardManagement project, in the Views folder, open the Home.xaml file. Add a TextBlock control named NoCardsTextBlock below the DataGrid control. It should display the text Number of cards in database:, as shown in the following image.

In the GreetingCardManagement project, in the Views folder, open the Home.xaml code file. Locate the constructor. Append code to the constructor to create a new instance of the System.Windows.Threading.DispatcherTimer class. The timer will be used to regularly update the TextBlock control.

Append code to the constructor to create an anonymous event handler for the Tick event of the countTimer DispatcherTimer object. The event handler, which does not return a value, should create an instance of the GreetingCardManagementDomainContext domain context class. Name the instance gcmContext. Call the GetCardCount method on gcmContext, passing a callback method named OnGetCardCountCompleted and a null value as the only parameters. Finally, destroy the gcmContext object. Append code to the constructor to set the timer interval to 15 seconds and start the timer.

Lab Instructions: Implementing User Controls and Navigation

Append a new callback method named OnGetCardCountCompleted to the Home class. The method should accept a single parameter named op, of the generic type System.ServiceModel.DomainServices.Client.InvokeOperation, restricted to integers only. Add code to the callback method OnGetCardCountCompleted to call the SetCardCount method, which accepts an integer parameter. The method should check if the currently executing code is running on the UI thread by using the Dispatcher object, and subsequently call the SetCardCount method directly, or by using a new delegate named CardCountDelegate, which accepts a single integer parameter. Because the DispatcherTimer class is used, it is not necessary to check if the code is running on the current thread. However, you will now be able to use a different approach, such as using the System.Threading.Timer class instead by making simple adjustments to your code. The System.Threading.Timer class runs on a non-UI thread.

Append a new method named SetCardCount to the Home class. The method should accept a single integer parameter named cardCount. The Text property of the NoCardsTextBlock control should be updated with the text, Number of cards in database:, followed by the number of cards in the database, passed in the cardCount parameter. Build the solution. Run the application. Check that the number of cards, 501, is displayed after 15 seconds. Close Internet Explorer. Close all applications. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Creating Advanced User Interfaces

Module 5
Lab Instructions: Creating Advanced User Interfaces
Contents:
Exercise 1: Creating ItemsControl Objects Exercise 2: Configuring Content Classes for use in the ItemsControl Class Exercise 3: Using the Custom ItemsControl object in a User Control
4

7 11

Lab Instructions: Creating Advanced User Interfaces

Lab: Presenting Items, Classes, and Dependency Properties

Lab Introduction
In this lab, you will create a complex container control that displays categories of greeting cards in a coverflow style. You will also develop template classes, event arguments, and dependency properties to show the greeting cards in a slick, professional way in the coverflow control. In addition, you will create a class that can be used to instantiate objects that are added to the coverflow controlwhen the user clicks or otherwise selects a category in the coverflow container, the exposed properties of those objects will be used to populate other user interface elements in an engaging way. The exercises for this lab are: Exercise 1: Creating ItemsControl Objects Exercise 2: Configuring Content Classes for use in the ItemsControl Class Exercise 3: Using the Custom ItemsControl object in a User Control

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will begin this lab by working with a starter solution. The starter solution already consumes XML data that defines categories of greeting cards (similar to what you worked on in the previous lab). The starter solution also contains some of the user interface elements that will be used to display object properties. Some of the plumbing for the coverflow control already exists (given that it is a complex control) but you will complete some of the important aspects of the control.

Lab Instructions: Creating Advanced User Interfaces

Lab End State


When you have completed the lab, you will have created a complex container control that displays categories of greeting cards in a complex coverflow style. The control will be driven by the XML data that the application consumes. Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed, working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Lab Instructions: Creating Advanced User Interfaces

Exercise 1: Creating ItemsControl Objects


Task 1: Create the EventArgs class for the ItemsControl object.
Open Microsoft Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod05\VB\Starter or D:\Labfiles\Mod05\CS\Starter folder. To the GreetingCardConsumer project, add a new class named CoverFlowEventArgs. Modify the class declaration so that it reads as follows.
[Visual Basic] Public Class CoverFlowEventArgs Inherits EventArgs

[Visual C#] public class CoverFlowEventArgs : EventArgs

Add the following property declarations to the CoverFlowEventArgs class.


[Visual Basic] Public Property Index As Integer Public Property Item As Object Public Property MouseClick As Boolean

[Visual C#] public int Index { get; set; } public object Item { get; set; } public bool MouseClick { get; set; }

Save the changes. Hint Refer to the topic Creating Events for an ItemsControl Class in Lesson 1.

Task 2: Configure a class to inherit from the ItemsControl base class.


Open the CoverFlowControl class. Modify the class declaration so that it inherits from the ItemsControl base class, and implements the INotifyPropertyChanged interface.

Lab Instructions: Creating Advanced User Interfaces

Hint

Refer to the Creating an ItemsControl Class topic in Lesson 1.

Add an event delegate named SelectedItemChangedEvent immediately above the class declaration you have just modified. Ensure that the delegate accepts a parameter type of CoverFlowEventArgs. In the CoverFlowControl class, declare a public event of type SelectedItemChangedEvent and name it SelectedItemChanged. Hint Refer to the Creating Events for an ItemsControl Class topic in Lesson 1.

Declare a class-level variable of type ItemsPresenter and name it ItemsPresenter. Declare a class-level variable of type ItemsPresenter and name it ItemsPresenter. Declare a generic class-level variable of type List restricted to CoverFlowItemControl objects and name it cfItems. Add the following procedure to manage changes when an item is selected.
[Visual Basic] Private Sub IndexSelected(ByVal index As Integer, ByVal mouseclick As Boolean, ByVal layoutChild As Boolean) If Items.Count > 0 AndAlso Items.Count > index Then selIndex = index If layoutChild Then LayoutChildren() End If Dim e As CoverFlowEventArgs = New CoverFlowEventArgs() With { .Index = index, .Item = cfItems(index).Content, .MouseClick = mouseclick } RaiseEvent SelectedItemChanged(e) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SelectedIndex")) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SelectedItem")) End If End Sub

[Visual C#] private void IndexSelected(int index, bool mouseclick, bool layoutChildren) { if ((Items.Count > 0) && (Items.Count>index)) { selectedIndex = index; if(layoutChildren) { LayoutChildren(); } CoverFlowEventArgs e = new CoverFlowEventArgs() { Index = index, Item = cfItems[index].Content, MouseClick = mouseclick };

Lab Instructions: Creating Advanced User Interfaces

if (SelectedItemChanged != null) { SelectedItemChanged(e); } if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("SelectedIndex")); PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem")); }

Add the following property procedure.


[Visual Basic] Public Property RotationAngle() As Double Get Return CType(GetValue(RotationAngleProperty), Double) End Get Set(ByVal value As Double) SetValue(RotationAngleProperty, value) End Set End Property

[Visual C#] public double RotationAngle { get { return (double)GetValue(RotationAngleProperty); } set { SetValue(RotationAngleProperty, value); } }

Add the following code to create and register a dependency property.


[Visual Basic] Public Shared ReadOnly RotationAngleProperty As DependencyProperty _ = DependencyProperty.Register("RotationAngle", GetType(Double), GetType(CoverFlowControl), New PropertyMetadata(60R, New PropertyChangedCallback(AddressOf CoverFlowControl.OnValuesChanged)))

[Visual C#] public static readonly DependencyProperty RotationAngleProperty = DependencyProperty.Register("RotationAngle", typeof(double), typeof(CoverFlowControl), new PropertyMetadata(60d, new PropertyChangedCallback (CoverFlowControl.OnValuesChanged)));

Save the changes.

Lab Instructions: Creating Advanced User Interfaces

Exercise 2: Configuring Content Classes for use in the ItemsControl Class


Task 1: Configure a class as a ContentControl Template.
Open the CoverFlowItemControl class. Modify the class declaration so that it inherits from ContentControl. Hint Refer to the Creating Template Classes for Items topic in Lesson 2

Declare a class-level variable called ContentPresenter type of ContentControl. Add the following public event to the CoverFlowItemControl class.
[Visual Basic] Public Event ItemSelected As EventHandler

[Visual C#] public event EventHandler ItemSelected;

In the OnApplyTemplate procedure, locate the following comment.


TODO: Wire-up Mouse Event from Content Presenter

Add the following code directly beneath the comment you have just identified.
[Visual Basic] If Not IsNothing(ContentPresenter) Then AddHandler ContentPresenter.MouseLeftButtonUp, New MouseButtonEventHandler(AddressOf ContentPresenter_MouseLeftButtonUp) End If

[Visual C#] if (ContentPresenter != null) { ContentPresenter.MouseLeftButtonUp += new MouseButtonEventHandler(ContentPresenter_MouseLeftButtonUp); }

Add the following event handler directly beneath the OnApplyTemplate procedure.
[Visual Basic] Sub ContentPresenter_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs) RaiseEvent ItemSelected(Me, Nothing) End Sub

[Visual C#] void ContentPresenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (ItemSelected != null) {

Lab Instructions: Creating Advanced User Interfaces

ItemSelected(this, null);

Save the changes.

Task 2: Develop a class for use in the ItemsControl object.


To the GreetingCardConsumer project, add a new class called CardCategory to the Silverlight project, and configure it so that it imports the System.Xml.Linq and System.Collections.Generic namespaces. Add the following public properties to the CardCategory class.
[Visual Basic] Public Property Public Property Public Property Public Property Public Property Public Property Public Property modTitle As String modToolTip As String modImageUrl As String modMediaFileTitles As List(Of String) modMediaFileUrls As List(Of String) modMediaFileThumbnailPaths As List(Of String) modMediaFileTooltips As List(Of String)

[Visual C#] public string modTitle { get; set; } public string modToolTip { get; set; } public string modImageUrl { get; set; } public List<string> modMediaFileTitles { get; set; } public List<string> modMediaFileUrls { get; set; } public List<string> modMediaFileThumbnailPaths { get; set; } public List<string> modMediaFileTooltips { get; set; }

Lab Instructions: Creating Advanced User Interfaces

Add the following constructor to the CardCategory class.


[Visual Basic] Public Sub New(ByVal xModule As XElement) modMediaFileTitles = New List(Of String) modMediaFileUrls = New List(Of String) modMediaFileThumbnailPaths = New List(Of String) modMediaFileTooltips = New List(Of String) parseXML(xModule) End Sub

[Visual C#] public CardCategory(XElement xModule) { modMediaFileTitles = new List<string>(); modMediaFileUrls = new List<string>(); modMediaFileThumbnailPaths = new List<string>(); modMediaFileTooltips = new List<string>(); parseXML(xModule); }

Add the following procedure directly beneath the constructor you have just added.
[Visual Basic] Sub parseXML(ByVal xModule As XElement) If Not IsNothing(xModule.Element("THUMBNAIL")) Then Dim thumbNail As XElement = xModule.Element("THUMBNAIL") If Not IsNothing(thumbNail.Attribute("path")) Then modImageUrl = thumbNail.Attribute("path").Value End If If Not IsNothing(thumbNail.Attribute("tooltip")) Then modToolTip = thumbNail.Attribute("tooltip").Value End If End If If Not IsNothing(xModule.Element("CARDS")) Then Dim xMediaFile As XElement For Each xMediaFile In _ xModule.Element("CARDS").Descendants("CARD") If Not IsNothing(xMediaFile.Attribute("previewUrl")) Then modMediaFileUrls.Add _ (xMediaFile.Attribute("previewUrl").Value) Else modMediaFileUrls.Add(String.Empty) End If If Not IsNothing(xMediaFile.Attribute("previewThumb")) Then modMediaFileThumbnailPaths.Add _ (xMediaFile.Attribute("previewThumb").Value) Else modMediaFileThumbnailPaths.Add(String.Empty) End If If Not IsNothing(xMediaFile.Attribute("tooltip")) Then modMediaFileTooltips.Add _ (xMediaFile.Attribute("tooltip").Value) Else

10

Lab Instructions: Creating Advanced User Interfaces

modMediaFileTooltips.Add _ ("Tooltip has not been set in XML file") End If Next End If End Sub

[Visual C#] private void parseXML(XElement xModule) { if (xModule.Element("THUMBNAIL") != null) { XElement thumbNail = xModule.Element("THUMBNAIL"); if (thumbNail.Attribute("path") != null) { modImageUrl = thumbNail.Attribute("path").Value; } if (thumbNail.Attribute("tooltip") != null) { modToolTip = thumbNail.Attribute("tooltip").Value; } } if (xModule.Element("CARDS") != null) { foreach (XElement xMediaFile in xModule.Element("CARDS").Descendants("CARD")) { if (xMediaFile.Attribute("previewUrl") != null) { modMediaFileUrls.Add (xMediaFile.Attribute("previewUrl").Value); } else { modMediaFileUrls.Add(string.Empty); } if (xMediaFile.Attribute("previewThumb") != null) { modMediaFileThumbnailPaths.Add (xMediaFile.Attribute("previewThumb").Value); } else { modMediaFileThumbnailPaths.Add(string.Empty); } if (xMediaFile.Attribute("tooltip") != null) { modMediaFileTooltips.Add (xMediaFile.Attribute("tooltip").Value); } else { modMediaFileTooltips.Add ("Tooltip has not been set in XML file"); } } } }

Save the changes.

Lab Instructions: Creating Advanced User Interfaces

11

Exercise 3: Using the Custom ItemsControl object in a User Control


Task 1: Configure XAML to use the custom ItemsControl object.
Open Home.xaml and add the following namespace declaration to the XAML.
xmlns:local="clr-namespace:GreetingCardConsumer"

Between the opening and closing tags of the MainGrid Grid element add the following markup.
<local:CoverFlowControl x:Name="flowControl" Margin="0,0,0,0" Width="600"> <local:CoverFlowControl.ItemTemplate> <DataTemplate> <Border CornerRadius="1"> <Image Source="{Binding modImageUrl}" CacheMode="BitmapCache" Grid.Row="0" Height="130" ToolTipService.ToolTip="{Binding modToolTip}"/> </Border> </DataTemplate> </local:CoverFlowControl.ItemTemplate> </local:CoverFlowControl>

Save the changes.

Task 2: Populate the CoverFlowControl from external XML data.


Review the contents of the GreetingCardConfig.xml in the ClientBin folder of the GreetingCardConsumer.Web project. You have already consumed parts of this file in the lab for a previous module. Now you will use the rest of the XML to populate and configure the CoverFlowControl contents. In the GreetingCardConsumer project, open the Views\Home.xaml file in code view. In the webClient_DownloadStringCompleted event handler, locate the following comment.
TODO: Create card categories

Add the following code directly below the comment you have just located.
[Visual Basic] For Each xModule As XElement in xDoc.Descendants("CATEGORY") Dim cardCat As New CardCategory(xModule) categories.Add(cardCat) Next

[Visual C#] foreach (XElement xModule in xDoc.Descendants("CATEGORY")) { CardCategory cardCategory = new CardCategory(xModule); categories.Add(cardCategory); }

Build the solution. Press Ctrl+F5 to run and test the application.

12

Lab Instructions: Creating Advanced User Interfaces

The application loads categories of cards in the CoverFlowControl that you created in this lab. Each category displays a number of different cards, as specified by the GreetingCardConfig.xml file. Click each of the card categories in the CoverFlowControl to see how the contents of each category are updated. The contents of each category are represented by the XML file, and you exposed the relevant data as properties of the CardCategory class to update the other components in the user interface. Close all applications.

You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shutdown the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Using Local Assets

Module 6
Lab Instructions: Using Local Assets
Contents:
Exercise 1: Printing from Silverlight Applications Exercise 2: Accessing the Clipboard in Silverlight Applications Exercise 3: Accessing Isolated Storage in Silverlight Applications Exercise 4: Accessing the File System in Silverlight Applications 4 6 8 10

Lab Instructions: Using Local Assets

Lab: Using Local Assets

Lab Introduction
In this lab, you will add various features to the GreetingCardConsumer project and the GreetingCardManagement project. You will start by adding custom multi-page printing support to the GreetingCardConsumer project, and then develop that project by adding copy and paste clipboard operations. In addition, you will implement multi-session isolated storage in the GreetingCardConsumer project to enable the user to choose a default card category. Finally, you will develop the GreetingCardManagement project as an out-of-browser elevated trust application. The application will read and write diagnostic information in files on the local file system, for use in a customer-support instant messaging scenario. The exercises in this lab are: Exercise 1: Printing from Silverlight Applications Exercise 2: Accessing the Clipboard in Silverlight Applications Exercise 3: Accessing Isolated Storage in Silverlight Applications Exercise 4: Accessing the File System in Silverlight Applications

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Instructions: Using Local Assets

Lab Start State


You will begin this lab by working with starter solutions. The starter solutions are similar to the completed solutions on which you worked in the previous labs, but they contain various additional buttons that will be used to implement the objectives for this lab. The buttons currently do not perform any actions, so you will write the code to achieve the lab outcomes.

Lab End State


When you have completed the lab, the GreetingCardConsumer project will include the following functionality: Custom multi-page printing support Support for custom copy and paste clipboard operations Multi-session isolated storage support

Additionally, the GreetingCardManagement project will include the ability to read and write diagnostic information in files on the local file system. Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. The completed working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Lab Instructions: Using Local Assets

Exercise 1: Printing from Silverlight Applications


Task 1: Add code for printing in a Silverlight application.
Open Microsoft Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod06\VB\Starter or D:\Labfiles\Mod06\CS\Starter folder. Build the solution. In the GreetingCardConsumer project, in the Views folder, open Home.xaml. Create an event handler for the Print button. Visual Studio creates an event handler for the Click event of the button. In the Home.xaml code file, bring the System.Windows.Printing namespace into scope. Add the following class-level variable declaration directly below the declaration of the viewThumbs class-level variable declaration.
[Visual Basic] Private currentPage As Integer = 0

[Visual C#] int currentPage = 0;

Locate the print_Click event handler that Visual Studio created for you. Add code to create and instantiate a new PrintDocument class named docToPrint. Create a new generic EventHandler, constrained to PrintPageEventArgs objects, and assign it to the PrintPageevent of the PrintDocument object, passing the docToPrint_PrintPage method (not yet created). Finally, call the Print method of the PrintDocument object, passing the text, Silverlight Document. Save the changes.

Task 2: Add an event handler to deal with multi-page printing.


Create a new method named docToPrint_PrintPage, which returns no value, accepting the standard event handler parameters; sender of type Object/object, and e of type PrintPageEventArgs. To the docToPrint_PrintPage method, add code to perform the following operations: a. b. c. d. Increment the currentPage class-level variable by one. Check if the value of the currentPage variable is less than flowControl.Items.Count, and set the value of e.HasMorePages accordingly. Assign the value of currentPage - 1 to flowControl.SelectedIndex. Assign the LayoutRootUIElement to e.PageVisual.

Save the changes. Run the application. In Internet Explorer, click Print.

Lab Instructions: Using Local Assets

Print to OneNote 2010. After a few seconds, OneNote appears.

In the Select Location in OneNote dialog box, click OK. OneNote displays a page for each card category in the Silverlight application.

Close OneNote, and then close Internet Explorer.

Lab Instructions: Using Local Assets

Exercise 2: Accessing the Clipboard in Silverlight Applications


Task 1: Copy text to the clipboard programmatically.
In the Home.xaml code file, locate the webClient_DownloadStringCompleted event handler. Add a class-level variable named contentsToCopy immediately above the webClient_DownloadStringCompleted event handler. The variable must be of type String/string and be assigned an empty string. In the webClient_DownloadStringCompleted event handler, locate the TODO comment, Populate contentsToCopy variable. Immediately below the comment, assign the e.Result property to the contentsToCopy class-level variable. Create an event handler for the Copy button by using the Design view of Home.xaml. Visual Studio creates an event handler for the Click event of the button. In the Click event handler for the Copy button, copy the value of the contentsToCopy class-level variable to the clipboard. Save the changes. Hint Refer to the Copying Content to the Windows Clipboard topic in Lesson 2.

Task 2: Paste text from the clipboard programmatically.


In the GreetingCardConsumer project, in the Views folder, open About.xaml. Create an event handler for the Paste button by using the Design view of About.xaml. Visual Studio creates an event handler for the Click event of the button. In the Click event handler for the Paste button, assign current text content of the clipboard to the Text property of the imContent control. Save the changes. Hint Refer to the Pasting Content from the Windows Clipboard topic in Lesson 2.

Task 3: Test copy and paste actions.


Run the application. In Internet Explorer, click Copy. In the Microsoft Silverlight dialog box, click Yes. Navigate to the About page. In Internet Explorer, Click Paste.

Lab Instructions: Using Local Assets

The contents of the clipboard are pasted into the instant messaging text box. Open Notepad. Paste the copied content into Notepad. The contents of the clipboard are pasted into Notepad. Close Notepad, not saving the changes, and then close Internet Explorer.

Lab Instructions: Using Local Assets

Exercise 3: Accessing Isolated Storage in Silverlight Applications


Task 1: Store persistent data in isolated storage.
Switch to the Home.xaml code file. Bring the System.IO.IsolatedStorage namespace into scope. Create a class-level variable named storage, of type IsolatedStorageSettings, and instantiate it to the value of the IsolatedStorageSettings. ApplicationSettings property. Switch to the Home.xaml markup file. Hint Refer to the Persisting Data in Isolated Storage topic in Lesson 2.

Create an event handler for the Set Default button by using the Design view of Home.xaml. Visual Studio creates the snapshot_Click event handler for the Click event of the button.

Add code to the snapshot_Click event handler to check if the storage variable contains a setting named currentCategory. If it does, set the currentCategory setting to the value of flowControl.SelectedIndex; otherwise, add the currentCategory setting with a value of flowControl.SelectedIndex. Save the changes. Hint Refer to the Persisting Data in Isolated Storage topic in Lesson 2.

Task 2: Retrieve persistent data from isolated storage.


In the Home.xaml code file, locate the webClient_DownloadStringCompleted event handler. Append code to the webClient_DownloadStringCompleted event handler to check if the storage variable contains a setting named currentCategory. If it does, set the flowControl.SelectedIndex property to the value of currentCategory setting. Save the changes. Hint Refer to the Retrieving Data from Isolated Storage topic in Lesson 2.

Lab Instructions: Using Local Assets

Task 3: Test persistent data storage and retrieval.


Run the application. Use the coverflow control to navigate to the Greeting Cards for General Occasions category. Click Set Default. Close Internet Explorer. Run the application again. Note that the Greeting Cards for General Occasions category is selected by default. Close Internet Explorer, and then close Visual Studio.

10

Lab Instructions: Using Local Assets

Exercise 4: Accessing the File System in Silverlight Applications


Task 1: Save a file to the file system programmatically.
Open Microsoft Visual Studio 2010. Open the GreetingCardManagement solution from the D:\Demofiles\Mod06\VB\Starter or D:\Demofiles\Mod06\CS\Starter folder. Build the solution. In the GreetingCardManagement project, in the Views folder, open Home.xaml. Create an event handler for the Save Diagnostic File button. Visual Studio creates an event handler for the Click event of the button. Add the following code to the save_Click event handler.

[Visual Basic] Try Dim filePathName As String = _ System.IO.Path.Combine(Environment.GetFolderPath( _ Environment.SpecialFolder.MyDocuments), _ "GreetingCardDiagnostics.txt") If (File.Exists(filePathName)) Then File.Delete(filePathName) End If Dim fileContents As StreamWriter = File.CreateText(filePathName) Dim displayName As String = "Your Display Name is: " & _ displayNameTextBox.Text Dim email As String = "Your Email Address is: " & _ emailTextBox.Text fileContents.WriteLine(displayName) fileContents.WriteLine(email) fileContents.Close() Catch secEx As System.Security.SecurityException ErrorWindow.CreateNew(New Exception( _ "Only out-of-browser applications can save files")) Catch ex As Exception ErrorWindow.CreateNew(ex) End Try

[Visual C#] try { string filePathName = System.IO.Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "GreetingCardDiagnostics.txt"); if (File.Exists(filePathName)) File.Delete(filePathName); StreamWriter fileContents = File.CreateText(filePathName); string displayName = "Your Display Name is: "

Lab Instructions: Using Local Assets

11

+ displayNameTextBox.Text; string email = "Your Email Address is: " + emailTextBox.Text; fileContents.WriteLine(displayName); fileContents.WriteLine(email); fileContents.Close();

} catch (System.Security.SecurityException secEx) { ErrorWindow.CreateNew(new Exception ("Only out-of-browser applications can save files")); } catch (Exception ex) { ErrorWindow.CreateNew(ex); }

Save the changes.

Task 2: Read a file from the file system programmatically.


In the GreetingCardManagement project, in the Views folder, open About.xaml. Create an event handler for the Open Diagnostic File button. Visual Studio creates an event handler for the Click event of the button. Add the following code to the open_Click event handler.
[Visual Basic] Try Dim filePathName As String = System.IO.Path.Combine( _ Environment.GetFolderPath( _ Environment.SpecialFolder.MyDocuments), _ "GreetingCardDiagnostics.txt") If Not File.Exists(filePathName) Then ErrorWindow.CreateNew(New Exception("Diagnostic file does not exist")) Return End If Dim fileContents As StreamReader = New StreamReader(filePathName) imContent.Text = fileContents.ReadToEnd() fileContents.Close() Catch secEx As System.Security.SecurityException ErrorWindow.CreateNew(New Exception( _ "Only out-of-browser applications can open files ")) Catch ex As Exception ErrorWindow.CreateNew(ex) End Try

[Visual C#] try { string filePathName = System.IO.Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "GreetingCardDiagnostics.txt"); if (!File.Exists(filePathName))

12

Lab Instructions: Using Local Assets

ErrorWindow.CreateNew(new Exception ("Diagnostic file does not exist")); return;

} catch (System.Security.SecurityException secEx) { ErrorWindow.CreateNew(new Exception ("Only out-of-browser applications can open files")); }

StreamReader fileContents = new StreamReader(filePathName); imContent.Text = fileContents.ReadToEnd(); fileContents.Close();

Save the changes.

Task 3: Test file access in Silverlight


Open the Project Designer. Ensure the application can be run out of the browser. Open the Out-of-Browser Settings dialog box. Ensure the application has elevated permissions when running outside the browser, and close the Out-of-Browser Settings dialog box. Run the application. Save the diagnostic file. Note The error window displays your error message because you are not running the application outside the browser. Close the error window. Install the GreetingCardManagement application locally. The Security Warning dialog box is shown. Accept the security warning and continue with the installation. The application opens in its own window. Close Internet Explorer. In the GreetingCard management application, save the diagnostic file. Open the GreetingCardDiagnostics.txt file saved to the Documents folder, in Notepad. Close Notepad. Switch back to the GreetingCardManagement application. Navigate to the About page. Open the diagnostic file.

Lab Instructions: Using Local Assets

13

Review the content that is added to the instant messaging text box. It should be the same content you saw in the diagnostic file. Close all open applications, including Visual Studio.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

Module 7
Lab Instructions: Implementing Advanced Media Techniques in Silverlight
Contents:
Exercise 1: Adding a Deep Zoom Image Exercise 2: Adding a Media Player 3 5

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

Lab: Implementing Advanced Media Techniques in Silverlight

Lab Introduction
In this lab, you will work on a Greenfield project that will ultimately be added to the GreetingCard online presence. In addition to the somewhat static e-greeting cards, the company also wants offer the customers to be able to zoom in and out of the images used, and offer videos as greeting cards. This means you will create a deep zoom image as part of the solution. This will allow the user to see multiple images displayed as a fast loading single image with zoom and pan capabilities. In addition, you will create a media player that will play greeting videos. The exercises in this lab are: Exercise 1: Adding a Deep Zoom Image Exercise 2: Adding a Media Player

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will begin this lab by creating a new Silverlight solution.

Lab End State


When you have completed the lab, the Silverlight solution will include:

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

A deep zoom image with display. A media player.

Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. The completed working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Exercise 1: Adding a Deep Zoom Image


Task 1: Create a new project.
Open Microsoft Visual Studio 2010. Create a new Silverlight application named GreetingCardGreenfield in the D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter folder by using the Silverlight Business Application template. A Silverlight project named GreetingCardGreenfield is created. A website named GreetingCardGreenfield.Web for hosting the Silverlight application and its services is also created.

Task 2: Create the Deep Zoom images.


Open Deep Zoom Composer. Create a new project named DeepZoomImage in the D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter folder. Add the images from the C:\Users\Public\Pictures\Sample Pictures folder to the solution.

Task 3: Compose the Deep Zoom images.


Compose the Deep Zoom images. Drag all of the images from the Images pane onto the work space. Align the 8 images in two rows of 4 equally sized images.

Task 4: Export the Deep Zoom images.


Export the composed Deep Zoom images. Set the following settings. Output type: Silverlight Deep Zoom Name: DeepZoomImage Export options: Export as a collection (multiple images) Templates: Deep Zoom Navigation (Default)

Click Export. Close Deep Zoom Composer, saving the project.

Task 5: Load the Deep Zoom images.


Add the generated image file folder, GeneratedImages, in the D:\Labfiles\Mod07\VB\Starter\DeepZoomImage \Exported Data\deepzoomimage or D:\Labfiles\Mod07\CS\Starter\DeepZoomImage\

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

Exported Data\deepzoomimage folder, to the GreetingCardGreenfield.Web project, by using Windows Explorer. Close Windows Explorer and switch to Visual Studio. In the MainPage.xaml window, change the Grid control to a StackPanel control with no property values set explicitly. Add a MultiScaleImage control named, dzMultiScaleImage, to the StackPanel control. Set the Source property to http://localhost:26982/GeneratedImages/dzc_output.xml. The port number is most likely different on your setup, so use the Project Designer for the GreetingCardGreenfield.Web project to find the actual port number. If the port number is different than 26982, change the number in markup after localhost:. Build the solution. The deep zoom images will display in the Design view. Run the application to see the results. Close Internet Explorer.

Task 6: Add zoom functionality.


Add two Button controls to the StackPanel control, named zoomIn and zoomOut. Add the controls before the MultiScaleImage control, and set the Content property to a value of + or -, respectively. Create an event handler for the Click event for each of the two Button controls. Add code to the zoomIn_Click event handler, to zoom in on the image, by using the ZoomAboutLogicalPoint method, with a zoom parameter value of 3, a logicalPoint.X value of 0.5, and a logicalPoint.Y value of 0.5. Add code to the zoomOut_Click event handler, to zoom out of the image, by using the ZoomAboutLogicalPoint method, with a zoom parameter value of 0.3, a logicalPoint.X value of 0.5, and a logicalPoint.Y value of 0.5. Run the application to see the results, by pressing both buttons several times. Close Internet Explorer.

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

Exercise 2: Adding a Media Player


Task 1: Add a video file.
Add the video,C:\Users\Public\Videos\Sample Videos\Wildlife.wmv, to the root of the GreetingCardGreenfield.Web project.

Task 2: Add a new user control.


Add a new UserControl named,Media,to the GreetingCardGreenfield project. In the Media.xaml window, add the following markup written with bold formatting.
<UserControl x:Class="Media.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <MediaElement Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Source="http://localhost:26982/Wildlife.wmv" Name="videoMediaElement" /> </Grid> </UserControl>

If the port number is different than 26982, change the number in markup after localhost:. You checked the port number in the previous exercise.

Task 3: Change the startup XAML file.


Open the App.xaml code file. In the App class constructor, set the VisualRoot property of the App class to a new instance of the MediaUserControl. Run the application to see the results, and notice that the playback starts automatically (after the page and video has been loaded). Close Internet Explorer. Close the App.xaml.vb or App.xaml.cs window.

Task 4: Create media buttons for user interaction.


To the Media.xaml file, add three Button controls to the Gridcontrol, named stopButton, pauseButton, and playButton. Add the controls after the MediaElement control, and set the Grid.Row property to a value of 1, and the Grid.Column property to a value of 0, 1, or 2, respectively. Set the Content property to a value of Stop, Pause, and Play, respectively. Create an event handler for the Click event for each of the three Button controls.

Lab Instructions: Implementing Advanced Media Techniques in Silverlight

Add code to the stopButton_Click event handler to call theStop method of the MediaElement control. Add code to the pauseButton_Click event handler to call the Pause method of the MediaElement control. Add code to the playButton_Click event handler to call the Play method of the MediaElement control. Run the application and demonstrate the video controls. Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Developing Silverlight Media Framework Solutions

Module 8
Lab Instructions: Developing Silverlight Media Framework Solutions
Contents:
Exercise 1: Adding Support for the Silverlight Media Framework Exercise 2: Configuring the Silverlight Media Framework Player 4 6

Lab Instructions: Developing Silverlight Media Framework Solutions

Lab: Developing Silverlight Media Framework Solutions

Lab Introduction
In this lab, you will create a media player based on the Silverlight Media Framework. The media player will be embedded in the GreetingCardConsumer application with which you have already been working, and will support advanced features such as closed captions and custom full-screen capabilities. The exercises in this lab are: Exercise 1: Adding Support for the Silverlight Media Framework Exercise 2: Configuring the Silverlight Media Framework Player

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will begin this lab by working with starter solutions. The starter solutions are similar to the completed solutions on which you worked in the previous lab. You will extend the starter solutions to include the Silverlight Media Framework media player.

Lab Instructions: Developing Silverlight Media Framework Solutions

Lab End State


When you have completed the lab, the GreetingCardConsumer project will include: References to the Silverlight Media Framework assemblies. XAML definitions for the SMFPlayer object. Code to populate playlists dynamically. Code to play videos in the SMFPlayer object. Code to manage full-screen and normal mode positioning of the SMFPlayer object. Code to add closed captions to the SMFPlayer object. Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed, working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Lab Instructions: Developing Silverlight Media Framework Solutions

Exercise 1: Adding Support for the Silverlight Media Framework


Task 1: Add references to the Silverlight Media Framework DLLs.
Open Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod08\VB\Starter or D:\Labfiles\Mod08\CS\Starter folder. To access the SMF functionality, add a reference to the following assemblies, all located in the D:\microsoft-smf-bin-2.2010.1221.1 folder: Microsoft.SilverlightMediaFramework.Core.dll Microsoft.SilverlightMediaFramework.Plugins. ClearTextCaptions.dll Microsoft.SilverlightMediaFramework.Plugins.dll Microsoft.SilverlightMediaFramework.Plugins. Heuristics.dll Microsoft.SilverlightMediaFramework.Plugins. Progressive.dll Microsoft.SilverlightMediaFramework.Plugins. SmoothStreaming.dll Microsoft.SilverlightMediaFramework.Plugins. TimedText.dll Microsoft.SilverlightMediaFramework.Utilities.dll

Build the solution. Hint Refer to the Referencing Silverlight Media Framework DLLs topic in Lesson 1.

Task 2: Add Silverlight Media Framework namespaces.


Open About.xaml from the Views folder in GreetingCardConsumer project. In the XAML pane, locate the following namespace declaration.
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly= System.Windows.Controls.Navigation"

Place the cursor at the end of the line you have just located, and then press Enter. On the empty line you have just created, add the following namespace declaration.
xmlns:SMF="clr-namespace:Microsoft.SilverlightMediaFramework.Core; assembly=Microsoft.SilverlightMediaFramework.Core"

Note

Ensure you add the preceding namespace declaration all on a single line.

Lab Instructions: Developing Silverlight Media Framework Solutions

Switch to Code view. Import the following namespaces in the code file: Microsoft.SilverlightMediaFramework.Core Microsoft.SilverlightMediaFramework.Core.Media Microsoft.SilverlightMediaFramework.Plugins. Primitives

Save the changes.

Lab Instructions: Developing Silverlight Media Framework Solutions

Exercise 2: Configuring the Silverlight Media Framework Player


Task 1: Review the XML and configuration data for videos.
In the GreetingCardApplication.Web project, open the GreetingCardConsumerTestPage.aspx page. In the body section of the page, locate the object tag and review the initParams data. Note how the path to a video and a path to the transcript file are provided as initiation parameters, in addition to the configXmlFileUri parameter that you have already worked with in previous labs. Open VideoTranscript.xml in the ClientBin folder, and review the transcript markup.

Task 2: Add the Silverlight Media Framework player XAML.


Switch to About.xaml. In the XAML pane, locate the following comment.
TODO: Add the SMF Player Here

To add a media player to the About page, wrapped in a Canvas element, add the following markup directly beneath the comment that you have just located.
<Canvas x:Name="videoPlayer" Canvas.ZIndex="0" Width="350" Height="310"> <Canvas.RenderTransform> <TranslateTransform x:Name="videoPlayerPosition" X="10" Y="10"></TranslateTransform> </Canvas.RenderTransform> <SMF:SMFPlayer x:Name="xVideoPlayer" AutoLoad="False" AutoPlay="False" PlaylistVisibility="Disabled" ScriptableName="VideoPlayer" CaptionsVisibility="Visible" ChaptersVisibility="Disabled" LoggingConsoleVisibility="Disabled" PlayerGraphVisibility="Disabled" VersionInformationVisibility="Disabled" AllowFullScreenPinning="True" Width="350" Height="310"/> </Canvas>

Save the changes.

Task 3: Add code to manage full screen view.


In Solution Explorer, right-click App.xaml and then click View Code. Locate the following comment.
TODO: Add Full Screen Management Code

Add the following code directly beneath the comment you have just located.
[Visual Basic] Public Shared vidToResize As SMFPlayer

Lab Instructions: Developing Silverlight Media Framework Solutions

Public Shared vidToMove As TranslateTransform Public Shared vidContainer As Canvas Public Shared Sub PositionVideo() Dim thisVid As SMFPlayer = App.vidToResize Dim thisVidPos As TranslateTransform = App.vidToMove Dim thisVidContainer As Canvas = App.vidContainer If Application.Current.Host.Content.IsFullScreen = False Then ' Reset to default position thisVidContainer.Height = 310 thisVid.Height = 310 thisVidContainer.Width = 350 thisVid.Width = 350 thisVidPos.X = 10 thisVidPos.Y = 10 Return End If ' Make the video fill the screen thisVid.Height = _ Application.Current.Host.Content.ActualHeight - 100 thisVid.Width = _ Application.Current.Host.Content.ActualWidth - 5 thisVidContainer.Height = _ Application.Current.Host.Content.ActualHeight - 100 thisVidContainer.Width = _ Application.Current.Host.Content.ActualWidth - 5 thisVidPos.X = 0 thisVidPos.Y = 0 End Sub

[Visual C#] public static SMFPlayer vidToResize; public static TranslateTransform vidToMove; public static Canvas vidContainer; public static void PositionVideo() { SMFPlayer thisVid = App.vidToResize; TranslateTransform thisVidPos = App.vidToMove; Canvas thisVidContainer = App.vidContainer; if (!Application.Current.Host.Content.IsFullScreen) { // Reset to default position thisVidContainer.Height = 310; thisVid.Height = 310; thisVidContainer.Width = 350; thisVid.Width = 350; thisVidPos.X = 10; thisVidPos.Y = 10; } return;

// Make the video fill the screen thisVid.Height = Application.Current.Host.Content.ActualHeight - 100; thisVid.Width =

Lab Instructions: Developing Silverlight Media Framework Solutions

Application.Current.Host.Content.ActualWidth - 5; thisVidContainer.Height = Application.Current.Host.Content.ActualHeight - 100; thisVidContainer.Width = Application.Current.Host.Content.ActualWidth - 5; thisVidPos.X = 0; thisVidPos.Y = 0;

Open About.xaml in Code view. Add the following code to the Page_Loaded or About_Loaded event handler.
[Visual Basic] App.vidToResize = xVideoPlayer App.vidContainer = videoPlayer App.vidToMove = videoPlayerPosition App.PositionVideo() AddHandler xVideoPlayer.FullScreenChanged, _ AddressOf xVideoPlayer_FullScreenChanged

[Visual C#] App.vidToResize = xVideoPlayer; App.vidContainer = videoPlayer; App.vidToMove = videoPlayerPosition; App.PositionVideo(); xVideoPlayer.FullScreenChanged += new EventHandler(xVideoPlayer_FullScreenChanged);

Add the following code to the xVideoPlayer_FullScreenChanged procedure.


[Visual Basic] App.PositionVideo()

Lab Instructions: Developing Silverlight Media Framework Solutions

[Visual C#] App.PositionVideo();

Save the changes.

Task 4: Add code to set the MediaSource for a video.


Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] Dim videoUri As String = _ App.Current.Resources("videoPath").ToString() xVideoPlayer.CurrentPlaylistItem = Nothing xVideoPlayer.Playlist.Clear() Dim currentVid As PlaylistItem = New PlaylistItem() currentVid.MediaSource = New Uri(videoUri, UriKind.Absolute) currentVid.DeliveryMethod = DeliveryMethods.ProgressiveDownload

[Visual C#] string videoUri = App.Current.Resources["videoPath"].ToString(); xVideoPlayer.CurrentPlaylistItem = null; xVideoPlayer.Playlist.Clear(); PlaylistItem currentVid = new PlaylistItem(); currentVid.MediaSource = new Uri(videoUri, UriKind.Absolute); currentVid.DeliveryMethod = DeliveryMethods.ProgressiveDownload;

Save the changes.

Task 5: Add code to set captions for the video.


Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] Dim captionUri As String = _ App.Current.Resources("transcriptPath").ToString() Try Dim vidMarkerResource As MarkerResource = New MarkerResource() vidMarkerResource.Format = "TTAF1-DFXP" vidMarkerResource.Source = New Uri(captionUri, UriKind.Absolute) currentVid.MarkerResource = vidMarkerResource Catch ' Silent failure if captions are missing ' Video will play without captions. End Try

[Visual C#] string captionUri = App.Current.Resources["transcriptPath"].ToString(); try {

MarkerResource vidMarkerResource = new MarkerResource(); vidMarkerResource.Format = "TTAF1-DFXP"; vidMarkerResource.Source = new Uri(captionUri, UriKind.Absolute);

10

Lab Instructions: Developing Silverlight Media Framework Solutions

currentVid.MarkerResource = vidMarkerResource; } catch { // Silent failure if captions are missing // Video will play without captions. }

Save the changes.

Task 6: Add code to play a video.


Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] xVideoPlayer.Playlist.Add(currentVid) xVideoPlayer.Play()

[Visual C#] xVideoPlayer.Playlist.Add(currentVid); xVideoPlayer.Play();

Save the changes. Start the application. Click About. The video plays and displays the captions from the caption file.

Near the lower part of the video player, click CC. The captions are hidden.

Click CC to turn the captions back on. Near the lower-right of the video player, click the full screen button. In the Microsoft Silverlight dialog box, click Yes. The application switches to full screen view and the video is resized and positioned to occupy most of the screen. You wrote the code to position and resize the video in this lab.

Switch back to non-full screen view. The application switches out of full screen view and the video is resized and positioned to occupy its original location. You wrote the code to position and resize the video in this lab.

Close all applications. You have now completed this lab.

Lab Instructions: Developing Silverlight Media Framework Solutions

11

Lab Shutdown
After finishing the lab, you must shutdown the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Accessing Hardware in Silverlight Applications

Module 9
Lab Instructions: Accessing Hardware in Silverlight Applications
Contents:
Exercise 1: Interacting with the Mouse Wheel Exercise 2: Interacting with the Keyboard 3 5

Lab Instructions: Accessing Hardware in Silverlight Applications

Lab: Interacting with Hardware Programmatically

Lab Introduction
In this lab, you will develop a solution that interacts with hardware such as mouse wheels and keyboard keys. The exercises for this lab are: Exercise 1: Interacting with the mouse wheel Exercise 2: Interacting with the keyboard

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will begin this lab by working with starter solutions. The starter solutions are similar to the completed solutions on which you worked, in a previous lab. You will extend the starter solutions to include interaction with mouse, keyboard, audio, and video hardware.

Lab End State


When you have completed the lab, the GreetingCardConsumer project will include: Event handlers that enable the user to use the mouse wheel to scroll through the CoverFlowControl of card categories.

Lab Instructions: Accessing Hardware in Silverlight Applications

Event handlers that enable the user to use keyboard navigation keys to scroll through the CoverFlowControl of card categories.

Exercise 1: Interacting with the Mouse Wheel


Task 1: Attach to HTML mouse wheel events.
Open Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod09\VB\Starter or D:\Labfiles\Mod09\CS\Starter folder. In the GreetingCardConsumer project, in the Views folder, open Home.xaml in Code view. Locate the following comment in the Page_Loaded or Home_Loaded event handler.
TODO: Attach HTML Events

Add code directly beneath the comment you have just located, to attach the following event handlers to the corresponding event of the specified object, by using the AttachEvent method. This will help ensure the mouse wheel works on different platforms than Windows, and different browsers than Internet Explorer. Object Window Window Document Event Name DOMMouseScroll onmousewheel onmousewheel Event Handler OnMouseWheel OnMouseWheel OnMouseWheel

Overload the private event handler named, OnMouseWheel, with the usual event handler signature, accepting the sender argument of type Object/object, and args argument of type HtmlEventArgs. Add code to suppress the events by calling the PreventDefault method of the args argument. This will help ensure the mouse wheel works on different platforms than Windows, and different browsers than Internet Explorer. Save the changes.

Task 2: Create and configure the mouse wheel event handler.


[Visual C# only] Bring the System.Windows.Input namespace into scope. Append code to the Page_Loaded or Home_Loaded event handler to add an event handler for the MouseWheel event of the flowControl object. Add an event handler named, flowControl_MouseWheel, with the usual event handler signature, accepting the sender argument of type Object/object, and e argument of type MouseWheelEventArgs. Add the event handler directly beneath the Page_Loaded or Home_Loaded event handler. Add code to the flowControl_MouseWheel event handler to perform the following operations: a. Create a variable named, i, of type Integer/int, and assign the value of the Delta property of the MouseWheelEventArgs parameter, divided by 120. Negate the result before assigning. This means the control will navigate one cover for each mouse scroll.

Lab Instructions: Accessing Hardware in Silverlight Applications

b.

Create a variable named, index, of type Integer/int, and assign the value of the flowControl.SelectedIndex property, plus the value of the variable i. This means the control will navigate one cover for each mouse scroll. Check if the value of index is less than 0, and if it is, call the First method of the flowControl object. If not, check if index is larger than the value of the flowControl.Items.Count property, minus 1. If it is, call the Last method of the flowControl object. If not, set the flowControl.SelectedIndex property to the value of the index variable. This ensures the selected cover will never be less than 0 or higher than the last cover.

c.

Save the changes.

Task 3: Test the mouse wheel interaction.


Run the application. Click the flow control, and point to the categories it contains, and then use the mouse wheel to navigate back and forth through the categories. Close Internet Explorer.

Lab Instructions: Accessing Hardware in Silverlight Applications

Exercise 2: Interacting with the Keyboard


Task 1: Configure the keyboard event handler.
Append code to the Page_Loaded or Home_Loaded event handler to add an event handler for the KeyDown event of the current object. In the GreetingCardConsumer project, open the CoverFlowControl code file. Locate the OnKeyDown event handler. Notice the code in the OnKeyDown event handler, which handles the cursor keys for navigating through the covers.
[Visual Basic] Public Shadows Sub OnKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) If e.Key = Key.Right OrElse e.Key = Key.Down OrElse e.Key = Key.PageDown Then NextItem() e.Handled = True ElseIf e.Key = Key.Left OrElse e.Key = Key.Up OrElse e.Key = Key.PageUp Then PreviousItem() e.Handled = True ElseIf e.Key = Key.Home OrElse e.Key = Key.Q Then First() e.Handled = True ElseIf e.Key = Key.End OrElse e.Key = Key.E Then Last() e.Handled = True End If End Sub

[Visual C#] public void OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Right || e.Key == Key.Down || e.Key == Key.PageDown) { NextItem(); e.Handled = true; } else if (e.Key == Key.Left || e.Key == Key.Up || e.Key == Key.PageUp) { PreviousItem(); e.Handled = true; } else if (e.Key == Key.Home || e.Key == Key.Q) { First(); e.Handled = true; } else if (e.Key == Key.End || e.Key == Key.E) { Last(); e.Handled = true; } }

Locate the IndexSelected method that accepts three arguments, and add code at the top of the method, to set focus to the current object. Save the changes.

Lab Instructions: Accessing Hardware in Silverlight Applications

Task 2: Test the keyboard interaction.


Run the application. Use the Down, Up, Right, and Left cursor keys to navigate through the card categories in the coverflow control. The Page control cannot receive focus, so it does not receive the keyboard input. The Home control is of type Page. Click the coverflow control. The coverflow control can receive focus, so it receives the keyboard input. Use the Down, Up, Right, and Left cursor keys to navigate through the card categories in the coverflow control. Click the Set Default button. The Button control can receive focus, so it receives the keyboard input. Use the Page Up and Page Down keys to navigate through the card categories in the coverflow control. Use the Home and End keys to navigate through the card categories in the coverflow control. Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Globalization and Localization

Module 10
Lab Instructions: Globalization and Localization
Contents:
Exercise 1: Globalizing an Application Exercise 2: Localizing an Application 3 6

Lab Instructions: Globalization and Localization

Lab: Globalizing and Localizing Applications

Lab Introduction
In this lab you will globalize and localize the existing GreetingCardConsumer application, to make it ready for international customers. The exercises in this lab are: Exercise 1: Globalization Exercise 2: Localization

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will begin this lab by working with a starter solution. The starter solution is similar to the completed solutions on which you worked in previous labs. You will globalize and localize the starter solution.

Lab End State


When you have completed the lab, the Silverlight solution will include: A globalized Silverlight application. A localized Silverlight application.

Lab Instructions: Globalization and Localization

Note Step-by-step instructions for completing the labs in this course are available in the lab answer keys provided. Completed working code is available in the Solution folders under the Lab files folder for each lab exercise on the virtual machine.

Exercise 1: Globalizing an Application


Task 1: Internationalize GreetingCardConsumer Application.
Open Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod10\VB\Starter or D:\Labfiles\Mod10\CS\Starter folder. Build the solution. In the GreetingCardConsumer project, open App.xaml. Notice the markup with ResourceWrapper defined:
<app:ResourceWrapper x:Key="ResourceWrapper" />

The sealed ResourceWrapper class is defined in the ResourceWrapper.vb or ResourceWrapper.cs file, located in the Helpers folder. The file is automatically generated when you create a Silverlight by using the Silverlight Business Application project template. In the GreetingCardConsumer project, in the Helpers folder, open ResourceWrapper.vb or ResourceWrapper.cs. In the ResourceWrapper.vb or ResourceWrapper.cs file, notice that two read-only properties exist, ApplicationStrings and SecurityQuestions. These two properties return the following shared/static member fields: _applicationStrings or applicationStrings and _securityQuestions or securityQuestions. They are type ApplicationStrings and SecurityQuestions. In the GreetingCardConsumer project, in the Assets\Resources folder, open ApplicationStrings.resx. The Resource Designer opens. In the Resource Designer, notice the Name column, which holds the resource key, used for looking up a specific value, which is shown the Value column. One example is the ApplicationName key, which has a current value of Greeting Card Consumer. In the GreetingCardConsumer project, open MainPage.xaml. In the MainPage.xaml window, in the XAML view, locate the TextBlock control named ApplicationNameTextBlock.
<TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}" Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>

Notice that the Text property is bound to the ApplicationStrings.ApplicationName property, found in the ResourceWrapper resource. When you build the application, the ApplicationStrings class is automatically generated by the resource compiler, from the resource files, .resx, making it accessible from within your application. The two HyperlinkButton controls have also been bound to properties in the ApplicationStrings class, so at this stage, MainPage.xaml needs no further attention.

Lab Instructions: Globalization and Localization

Close MainPage.xaml.

Task 2: Internationalize Home Page.


In the GreetingCardConsumer project, in the Views folder, open Home.xaml. Locate the StackPanel control.
<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center">

In the StackPanel control, locate the copyButton control, and notice the Content property holds a static or hardcoded string, Copy. The same is true for the print and snapshotButton controls.
<Button Grid.Row="1" Grid.Column="1" Content="Copy" Height="23" HorizontalAlignment="Left" Name="copy" VerticalAlignment="Top" Width="75" />

Add a resource file named HomeStrings.resx to the Assets/Resources folder. Make the resources publicly available. Set the custom tool namespace for the HomeStrings.resx file to an empty string (Visual Basic) or GreetingCardConsumer (Visual C#), by using the Properties window. Build the solution. Switch back to the Resource Designer. Add a new resource string named CopyButton with a value of Copy. Add a new resource string named PrintButton with a value of Print. Add a new resource string named SnapShotButton with a value of Set Default. Build the solution. Switch to ResourceWrapper.vb or ResourceWrapper.cs. Create a new shared/static member level field named _homeStrings or homeStrings of type HomeStrings. Create a new readonly property named HomeStrings of type HomeStrings. The property must return the shared/static member variable _homeStrings or homeStrings. Switch to Home.xaml. In the XAML view, modify the Content property of the copyButton control so it contains the following value:
{Binding HomeStrings.CopyButton, Source={StaticResource ResourceWrapper}}

In the XAML view, modify the Content property of the printButton control so it contains the following value:
{Binding HomeStrings.PrintButton, Source={StaticResource ResourceWrapper}}

Lab Instructions: Globalization and Localization

In the XAML view, modify the Content property of the snapshotButton control so it contains the following value:
{Binding HomeStrings.SnapShotButton, Source={StaticResource ResourceWrapper}}

Run the application. Check to see if the button captions contain the text from the resource files. Close Internet Explorer.

Lab Instructions: Globalization and Localization

Exercise 2: Localizing an Application


Task 1: Localize Home.xaml.
Add a resource file named HomeStrings.de-DE.resx to the Assets/Resources folder. Make the resources publicly available. Set the custom tool namespace for the HomeStrings.de-DE.resx file to an empty string (Visual Basic) or GreetingCardConsumer (Visual C#) by using the Properties window. Build the solution. Switch back to the Resource Designer. Add a new resource string named CopyButton with a value of Kopieren. Add a new resource string named PrintButton with a value of Ausdrucken. Add a new resource string named SnapShotButton with a value of Standard. Build the solution.

Task 2: Set the default culture.


Open the Project Designer for the GreetingCardConsumer project. Set the default or neutral culture to English. Save the changes.

Task 3: Force the culture to German.


In the GreetingCardConsumer project, open MainPage.xaml in Code view. In the constructor for the MainPage class, after the call to the InitializeComponent method, add code to set the CurrentUICulture property of the current thread to a new CultureInfo object based on the de-DE culture. Run the application and notice that the resource values displayed in the Button controls have been localized. Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Implementing Network Communications

Module 11
Lab Instructions: Implementing Network Communications
Contents:
Exercise 1: Consuming Initiation Parameters Exercise 2: Consuming Data by Using HTTPWebRequest Objects Exercise 3: Consuming Data by Using WebClient Objects Exercise 4: Sending and Receiving Data by Using Local Connections 3 5 8 10

Lab Instructions: Implementing Network Communications

Lab: Building Dynamic Silverlight Applications

Lab Introduction
In this lab, you will put into practice many of the concepts you have learned in this module. You will continue working with the Greeting Card scenario and you will implement initiation parameters that point to XML configuration files. You will retrieve those URIs at run time and you will then use both the HttpWebRequest and the WebClient objects to connect to and consume the data in the XML files. Finally, you will implement local connections for instant-messaging style communications between the GreetingCardConsumer application and the GreetingCardManagement application. The exercises for this lab are: Exercise 1: Consuming Initiation Parameters Exercise 2: Consuming Data by Using the HttpWebRequest Objects Exercise 3: Consuming Data by Using the WebClient Objects Exercise 4: Sending and Receiving Data by Using Local Connections

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will start with solutions that represent some aspects of the GreetingCardConsumer application and the GreetingCardManagement application that you have worked on in previous labs. These solutions have

Lab Instructions: Implementing Network Communications

some features already completed, but they do not have initiation parameters or code for communicating with XML files or each other. You will add these required features as part of the lab.

Lab End State


When you have completed the lab, the GreetingCardConsumer application will include initiation parameters that point to XML file URIs. You will have added code that retrieves these parameters and uses them to initiate communication with the XML files. You will use both HttpWebRequest and the WebClient objects to learn how these objects differ from each other. The two solutions will also communicate with each other in an instant-messaging help scenario by using local connections. You will write the code for all of these features.

Exercise 1: Consuming Initiation Parameters


Task 1: Add initiation parameters to the hosting control for the GreetingCardConsumer application.
Open Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod11\VB\Starter or D:\Labfiles\Mod11\CS\Starter folder. In the GreetingCardConsumer.Web project, open GreetingCardConsumerTestPage.aspx. Locate the following line of markup.
<param name="autoUpgrade" value="true" />

Add a new line immediately after the located markup. Add the following markup to the empty line you have just created.
<param name="initParams" value="configXmlFileUri=http://localhost:2234/ClientBin/GreetingCardConfig.xml,colorXmlF ileUri=http://localhost:2234/ClientBin/GreetingCardColors.xml" />

Note

Add the markup in a single line.

Save the changes. In the GreetingCardConsumer.Web project, in the ClientBin folder, open GreetingCardColors.xml. You will consume this data in Exercise 2.

In the GreetingCardConsumer.Web project, in the ClientBin folder, open GreetingCardConfig.xml. Hint The files are located in the ClientBin folder of the Web application.

You will consume this data in Exercise 3.

Task 2: Retrieve the initiation parameters at run time and add them to the application Resources collection.
In the GreetingCardConsumer project, open App.xaml in Code view.

Lab Instructions: Implementing Network Communications

Locate the following comment.


TODO: Read Init Params and add them to the Resources Collection

Add code directly beneath the comment that checks if e.InitParams is not null, and if so, creates a new local variable name item of type Object/object. Subsequently, loop through the items in the e.InitParams collection and add them to the Resources collection by using the Add method, passing the Key and Value properties of the current item. Save the changes. Hint Refer to the Consuming and Storing Initiation Parameters topic in Lesson 1 of this module for an example of storing initiation parameters in the Resources collection.

Task 3: Retrieve the initiation parameters in a user control.


In the GreetingCardConsumer project, in the Views folder, open Home.xaml in Code view. Locate the following comment in the Home_Loaded or Page_Loaded event handler.
TODO: Retrieve Init Params from the Resources Collection

Directly beneath the comment you have just located, add code to create the following local variables, assigned specific initial values. Variable Name colorSettingsUri Variable Type Initial Value String/string App.Current.Resources("colorXmlFileUri"). ToString() / App.Current.Resources["colorXmlFileUri"]. ToString() App.Current.Resources("configXmlFileUri"). ToString() / App.Current.Resources["configXmlFileUri"]. ToString()

categorySettingsUri

String/string

Add code immediately after the previously added code, to show the value of the colorSettingsUri and categorySettingsUri variables, each in a separate message box. Save the changes. Hint Refer to the Consuming and Storing Initiation Parameters topic in Lesson 1 of this module for an example of assigning values from the Resources collection to string variables.

Run the application. Two message boxes should be displayed showing the URLs you will use later in the lab. Take a note of these URLs.

Close Internet Explorer and switch back to Visual Studio 2010.

Lab Instructions: Implementing Network Communications

Exercise 2: Consuming Data by Using HTTPWebRequest Objects


Task 1: Call an asynchronous HTTP request to read XML data.
Add code to create a local variable named httpRequest of type HttpWebRequest and assign the value returned by the following method call. The code must replace the two calls to the MessageBox.Show method in the Home_Loaded or Page_Loaded event handler.
[Visual Basic] HttpWebRequest.Create( _ New Uri(colorSettingsUri, UriKind.Absolute))

[Visual C#] (HttpWebRequest) HttpWebRequest.Create(new Uri(colorSettingsUri, UriKind.Absolute));

In the Home_Loaded or Page_Loaded event handler, append code to call the BeginGetResponse method of the httpRequest object. Pass in a new AsyncCallback object with the httpRequest_CallBack method and the httpRequest object. Hint Refer to the Initiating Communication by Using HttpWebRequest Objects topic in Lesson 2 of this module.

Task 2: Create a callback method for the asynchronous HTTP request.


Create a new member variable named settings of type String/string and assign an empty string. Add the variable declaration after the Home_Loaded or Page_Loaded event handler. Add the following method after the variable declaration you have just added.
[Visual Basic] Sub httpRequest_CallBack(ByVal result As IAsyncResult) Dim httpRequest As HttpWebRequest = result.AsyncState Dim httpResponse As HttpWebResponse = _ httpRequest.EndGetResponse(result) Dim strmReader As StreamReader = _ New StreamReader(httpResponse.GetResponseStream()) Using (strmReader) settings = strmReader.ReadToEnd() End Using Dispatcher.BeginInvoke(AddressOf setColors) End Sub

[Visual C#] void httpRequest_CallBack(IAsyncResult result) { HttpWebRequest httpRequest = (HttpWebRequest) result.AsyncState; HttpWebResponse httpResponse = (HttpWebResponse) httpRequest.EndGetResponse(result); using (StreamReader strmReader = new StreamReader(httpResponse.GetResponseStream())) { settings = strmReader.ReadToEnd();

Lab Instructions: Implementing Network Communications

} } Dispatcher.BeginInvoke(setColors);

Important You must call the procedure the same name as you specified when you wrote code to call the HttpWebRequests BeginGetResponse method. Also, refer to the Receiving Replies to HttpWebRequest Object Calls topic in Lesson 2 of this module to see an example of the procedure signature. Hint Refer to the Managing HttpWebRequest Objects and Threading Issues topic in Lesson 2 of this module to see how to switch execution back to the main UI thread.

Task 3: Create a function that updates the user interface from the main UI thread.
Add the following method after the method you have just added.
[Visual Basic] Sub setColors() Dim xDoc As XDocument = XDocument.Parse(settings) Dim root As XElement = xDoc.Root Dim bannerColor As String = String.Empty Dim backgroundColor As String = String.Empty Dim playerSettings As XElement = root.Element("PLAYERSETTINGS") Dim colorSettings As XElement = _ playerSettings.Element("COLORSETTINGS") If Not IsNothing(colorSettings.Attribute("bannerColor")) Then bannerColor = colorSettings.Attribute("bannerColor").Value End If If Not IsNothing(colorSettings.Attribute("backgroundColor")) Then backgroundColor = _ colorSettings.Attribute("backgroundColor").Value End If Dim bannerCol As SolidColorBrush = _ New SolidColorBrush(makeColor(bannerColor)) Dim backgroundCol As SolidColorBrush = _ New SolidColorBrush(makeColor(backgroundColor)) App.NavigationGrid.Background = bannerCol App.LayoutRoot.Background = backgroundCol End Sub

[Visual C#] void setColors() { XDocument xDoc = XDocument.Parse(settings); XElement root = xDoc.Root; string bannerColor = string.Empty; string backgroundColor = string.Empty; XElement playerSettings = root.Element("PLAYERSETTINGS"); XElement colorSettings = playerSettings.Element("COLORSETTINGS"); if (colorSettings.Attribute("bannerColor") != null) { bannerColor = colorSettings.Attribute("bannerColor").Value; }

Lab Instructions: Implementing Network Communications

if (colorSettings.Attribute("backgroundColor") != null) { backgroundColor = colorSettings.Attribute("backgroundColor").Value; } SolidColorBrush bannerCol = new SolidColorBrush(makeColor(bannerColor)); SolidColorBrush backgroundCol = new SolidColorBrush(makeColor(backgroundColor)); App.NavigationGrid.Background = bannerCol; App.LayoutRoot.Background = backgroundCol;

Review the function named makeColor that already exists in the class in which you have been working. Your code calls this function to convert the hexadecimal string data into a .NET color. Silverlight does not have methods for converting hexadecimal string data into a .NET color, so this function has been provided for you as part of the starter solution.

Save the changes. Run and test the application. The section at the top of the Silverlight application is now orange and the background of the main section is grey.

Close Internet Explorer and switch back to Visual Studio 2010.

Lab Instructions: Implementing Network Communications

Exercise 3: Consuming Data by Using WebClient Objects


Task 1: Call an asynchronous WebClient request to read XML data.
After the existing code in the Home_Loaded or Page_Loaded event handler, perform the following tasks: a. b. c. d. Declare and instantiate a new instance of a WebClient object, named webClient. Add code to add a new event handler for the DownloadStringCompleted event for the WebClient object. Add code that creates a new absolute URI based on the GreetingCardConfig.xml file that you stored in a string variable in Task 3 of Exercise 1. Call the DownloadStringAsync method of the WebClient object to initiate communication with the URI you have just constructed.

Hint Refer to the Initiating Communication by Using WebClient Objects topic in Lesson 2 of this module. Save the changes.

Task 2: Create the DownloadStringCompleted event handler for the WebClient.


Add the following code immediately after the Home_Loaded or Page_Loaded event handler.

Lab Instructions: Implementing Network Communications

[Visual Basic] Sub webClient_DownloadStringCompleted(ByVal sender As Object, _ ByVal e As DownloadStringCompletedEventArgs) If Not IsNothing(e.Error) Then MessageBox.Show("There was an error retrieving xml") Return End If Dim xDoc As XDocument = XDocument.Parse(e.Result) Dim root As XElement = xDoc.Root Dim appTitle As String = String.Empty If Not IsNothing(root.Attribute("title")) Then appTitle = root.Attribute("title").Value App.ApplicationNameTextBlock.Text = appTitle End If End Sub

[Visual C#] void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was an error retrieving xml"); } return;

XDocument xDoc = XDocument.Parse(e.Result); XElement root = xDoc.Root; string appTitle = string.Empty; if (root.Attribute("title") != null) { appTitle = root.Attribute("title").Value; App.ApplicationNameTextBlock.Text = appTitle; }

Save the changes. Run and test the application. The application displays the text Greeting Card! This text was retrieved from the GreetingCardConfig.xml file. You will work with the rest of the XML data that was retrieved in subsequent labs.

Close Internet Explorer and switch back to Visual Studio 2010.

10

Lab Instructions: Implementing Network Communications

Exercise 4: Sending and Receiving Data by Using Local Connections


Task 1: Add controls for sending and receiving messages to About.xaml.
In the GreetingCardConsumer project, in the Views folder, open About.xaml. In the XAML pane, locate the StackPanel element. Add the following markup between the opening and closing tags of the StackPanel element.
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Instant Communications"/> <TextBox x:Name="imContent" Width="400" Height="200" HorizontalAlignment="Left"></TextBox> <TextBlock x:Name="imReceived" Width="400" Height="200" HorizontalAlignment="Left"></TextBlock>

Create an event handler for the KeyUp event of the imContent TextBox control. Visual Studio creates an event handler stub for the KeyUp event.

Leave the current instance of Visual Studio running. Open a second instance of Visual Studio. A second instance of Visual Studio appears.

Open the GreetingCardManagement solution from the D:\Labfiles\Mod11\VB\Starter or D:\Labfiles\Mod11\CS\Starter folder. In the GreetingCardManagement project, in the Views folder, open About.xaml. In the XAML pane, locate the StackPanel element. Add the following markup between the opening and closing tags of the StackPanel element, replacing the existing content.
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Instant Communications"/> <TextBox x:Name="imContent" Width="400" Height="200" HorizontalAlignment="Left"></TextBox> <TextBlock x:Name="imReceived" Width="400" Height="200" HorizontalAlignment="Left"></TextBlock>

Leave both instances of Visual Studio running.

Task 2: Add code for sending and receiving messages to the GreetingCardConsumer application.
Switch to the instance of Visual Studio that has the GreetingCardConsumer solution open. Ensure that you are viewing the code file for About.xaml. Bring the System.Windows.Messaging namespace into scope. Above the imContent_KeyUp event handler, declare the following member variables and instantiate them by passing the constructor values indicated. Name msgSender Type LocalMessageSender Constructor Value GreetingCardConsumer

Lab Instructions: Implementing Network Communications

11

Name msgReceiver

Type LocalMessageReceiver

Constructor Value GreetingCardManagement

Create a new event handler named msgReceiver_MessageReceived, with the standard event handler signature, accepting an argument named sender of type Object/object, and an argument named e of type MessageReceivedEventArgs. Place the event handler immediately below the imContent_KeyUp event handler. Add code to the imContent_KeyUp event handler to call the SendAsync method of the msgSender object, passing the value of the imContent.Text property. Add code to the OnNavigatedTo event handler to map an event handler named msgReceiver_MessageReceived to the MessageReceived method of the msgReceiver, and then call the Listen method of the msgReceiver object. Save the changes.

Task 3: Add code for sending and receiving messages to the GreetingCardManagement application.
Switch to the instance of Visual Studio that has the GreetingCardManagement solution open. Ensure that you are viewing the code file for About.xaml. Above the imContent_KeyUp event handler, declare the following member variables and instantiate them by passing the constructor values indicated. Name msgSender msgReceiver Type LocalMessageSender LocalMessageReceiver Constructor Value GreetingCardManagement GreetingCardConsumer

Note Note that these names are the opposite of the messages you defined in Task 2. This enables the two applications to communicate with each other over two well-defined connections. Build the solution.

Task 4: Test the communications over the local connections.


Ensure that the current instance of Visual Studio has the GreetingCardManagement solution open. Run the application. Internet Explorer starts and displays the application. Click About. Leave Internet Explorer running. Switch to the instance of Visual Studio that has the GreetingCardConsumer solution open. Run the application. Internet Explorer starts and displays the application. Click About.

12

Lab Instructions: Implementing Network Communications

Arrange the two Internet Explorer windows so that they are side-by-side. In the instance of Internet Explorer that has the Greeting Card Consumer application running, in the text box, type Help! Note Note that the text Help! is displayed in the GreetingCard Management application.

In the GreetingCard Management application, in the text box, type OK! Note Note that the text OK! is displayed in the GreetingCard Consumer application.

Close all applications. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Deploying Silverlight Applications

Module 12
Lab Instructions: Deploying Silverlight Applications
Contents:
Exercise 1: Adding Application Features Exercise 2: Loading Resources Dynamically 3 6

Lab Instructions: Deploying Silverlight Applications

Lab: Deploying Silverlight Applications

Lab Introduction
In this lab, you will put into practice some of the concepts you have learned in this module. You will continue working with the Greeting Card scenario and you will add toast notifications, for running out-ofbrowser, which appear whenever the network connection changes. In addition, you will enable assembly caching and load external resources on demand to reduce the size of the Silverlight application package and enable the application to start faster. The exercises for this lab are: Exercise 1: Adding Application Features Exercise 2: Loading Resources Dynamically

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will start with a solution that represents most aspects of the GreetingCardConsumer application that you have worked on in previous labs.

Lab End State


When you have completed the lab, the GreetingCardConsumer application will have added toast notifications, for running out-of-browser, which appear whenever the network connection changes. In addition, application assemblies and external assemblies are loaded on demand.

Lab Instructions: Deploying Silverlight Applications

Exercise 1: Adding Application Features


Task 1: Ensure that the application runs out-of-browser.
Open Visual Studio 2010. Open the GreetingCardConsumer solution from the D:\Labfiles\Mod12\VB\Starter or D:\Labfiles\Mod12\CS\Starter folder. Open the Project Designer for the GreetingCardConsumer project. Enable the application to run outside the browser.

Task 2: Require elevated trust for the application.


Ensure that the application has elevated trust when running outside the browser. Close the Project Designer.

Task 3: Add network check.


In the GreetingCardConsumer project, open MainPage.xaml in Code view. To the MainPage class, add a private shared/static event handler named OnNetworkChange, with the standard .NET Framework event handler signature. Bring the System.Net.NetworkInformation namespace into scope. To the MainPage class constructor, append code to map the event handler method named OnNetworkChange to the NetworkChange.NetworkAddressChanged event.

Task 4: Display toast notification on network change.


Add a private shared/static member variable named notificationWnd, of type NotificationWindow, to the MainPage class. Add code to the MainPage class constructor in an If...Then/if construct to check if the application is currently out-of-browser. If the application is currently running out-of-browser, add a check to see if the notificationWnd object is null, and if it is, instantiate it as a NotificationWindow object. Add the code before the event handler is added. To the OnNetworkChange method in an If...Then/if construct, add a local variable named message, of type String/string, and add a check to see if the application is currently running out-of-browser. To the OnNetworkChange method in the If...Then/if construct, add code to check if the notificationWnd object is currently visible by comparing the Visibility property with the System.Windows.Visibility.Visible enum member value. If it is visible, close the notificationWnd object to prevent an exception being thrown. To the OnNetworkChange method in an If...Then...Else/if...else construct, add code to check if a network is available. Append the code to the existing If...Then/if construct that checks if the application is running out-of-browser. Set the value of the message variable to indicate if a network is available. Save the changes.

Task 5: Add new UserControl.


Add a new UserControl named NetworkChangeNotification to the GreetingCardConsumer project in the Views folder.

Lab Instructions: Deploying Silverlight Applications

In the NetworkChangeNotification.xaml window, set the Width property of the Grid control to 200, and the Height property to 50. In the NetworkChangeNotification.xaml window, to the Grid control, add a self-closing TextBlock element, which is centered both horizontally and vertically. Bind the Text property, without specifying the exact binding. Save the changes. Switch to MainPage.xaml in Code view. [Visual C# only] Bring the GreetingCardConsumer.Views namespace into scope. Build the solution. To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to instantiate a new object of type NetworkChangeNotification, named nwWindow. Set the Content property of the notificationWnd object to the nwWindow object. To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to set the Content.DataContext property of the notificationWnd object to the message variable. This way, you can programmatically set the correct message to appear, without using different windows/user controls. In addition, set the Height and Width properties to the corresponding values of the LayoutRoot object of the nwWindow object. This will ensure that your notification window has the same size as the UserControl you just created. Note that you need to use the Height and Width of the LayoutRoot, which in this case is the Grid control in the UserControl, because the Height and Width of the UserControl is not accessible at this stage because the UserControl is not displayed. To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to show the notificationWnd object for 5 seconds, and then activate the MainWindow of the current application.

Task 6: Test the notification window.


Run the application. Install the application with default settings. Close Internet Explorer. Open the Settings window for the Hyper-V guest. Arrange the Hyper-V guest and the Settings windows so that you can see the system tray of Hyper-V guest in the right lower-most corner of your screen, and the Settings window in the left upper-most corner. If the windows overlap, arrange the Settings window on top of the Hyper-V guest window. In the Settings window, change the network adapter from Private Network to Not connected.

Lab Instructions: Deploying Silverlight Applications

Notice the toast notification being displayed for 5 seconds as the network connection is now unavailable. In the Settings window, change the network adapter from Not connected to Private Network. Notice the toast notification being displayed for 5 seconds as the network connection is available again. Close the Settings window. Uninstall the application.

Lab Instructions: Deploying Silverlight Applications

Exercise 2: Loading Resources Dynamically


Task 1: Enable assembly caching.
Open the Project Designer for the GreetingCardConsumer project. Disable the application to run outside the browser. Enable assembly caching. Save the changes. Close the Project Designer.

Task 2: Add external resources.


Add a new Silverlight Class Library project named FabrikamLibrary to the solution. The library will contain the external resources to be loaded on demand. Delete the default code file Class1. Add the existing DynamicPage.xaml file to the FabrikamLibrary project. The file is located in the Starter folder. In the FabrikamLibrary project, add a reference to the System.Windows.Controls.Navigation assembly. Open the DynamicPage.xaml page. Examine the DynamicPage.xaml page content. Notice the value of the Text property of the TextBlock element named ContentText. Notice the use of various styles that do not exist in the current project. Build the FabrikamLibrary project. Copy the output assembly, FabrikamLibrary.dll, from the D:\Labfiles\Mod12\VB\Starter\FabrikamLibrary\Bin\Debug or D:\Labfiles\Mod12\CS\Starter\FabrikamLibrary\Bin\Debug folder to the ClientBin folder in the root of the GreetingCardConsumer.Web project by using Windows Explorer.

Task 3: Set up assembly on demand loading.


In the GreetingCardConsumer project, open Views\Home.xaml in Code view. Bring the System.Reflection namespace into scope. To the Home class, append a private event handler named wClient_OpenReadCompleted, with the standard .NET Framework event handler signature; an argument named sender, of type Object/object, and an argument named e, of type OpenReadCompletedEventArgs. The event handler will handle the download of the assembly from the hosting web application. To the wClient_OpenReadCompleted method in an If...Then/if construct, check if the user did not cancel the download by examining the e.Cancelled property. To the wClient_OpenReadCompleted method in the If...Then/if construct, add code to create and instantiate a variable named assmPart, of type AssemblyPart, and create a variable named assmbly, of type Assembly. Use the Load method of the assmPart object to assign the downloaded assembly to assmbly. Pass e.Result to the Load method. To the wClient_OpenReadCompleted method in the If...Then/if construct, append code to load the DynamicPage.xaml file from the loaded assembly. Use the Application.LoadComponent method

Lab Instructions: Deploying Silverlight Applications

and pass the current object and a new System.Uri object with the following relative URI: /FabrikamLibrary;component/DynamicPage.xaml Locate the Home_Loaded or Page_Loaded event handler method. Append code to the Home_Loaded or Page_Loaded method to create and instantiate a variable named wClient, of type WebClient. Append the code to the existing If...Then/if construct. Append code to the Home_Loaded or Page_Loaded method to map the OpenReadCompleted event of the existing wClient object to the wClient_OpenReadCompleted method. Append the code to the existing If...Then/if construct. Append code to the Home_Loaded or Page_Loaded method to start the asynchronous download of the FabrikamLibrary.dll assembly by calling the OpenReadAsync method of the wClient object, passing a relative uri for the FabrikamLibrary.dll assembly. Run and test the application. Notice how the content of the Home page is replaced with the content loaded from the DynamicPage.xaml file, and how the styles are merged with the current project. Close all applications. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Application Guidance

Module 13
Lab Instructions: Application Guidance
Contents:
Exercise 1: Installing the Simple MVVM Toolkit Exercise 2: Examining a Silverlight MVVM project Exercise 3: Implementing MVVM Items 3 4 8

Lab Instructions: Application Guidance

Lab: Implementing the MVVM Design Pattern

Lab Introduction
In this lab, you will put into practice some of the concepts you learned in this module. You will work on a new MVVM-based project, and modify it to display data from the GreetingCard database. The exercises for this lab are: Exercise 1: Installing the Simple MVVM Toolkit Exercise 2: Examining a Silverlight MVVM Project Exercise 3: Implementing MVVM Items

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will start with a new solution, named MVVMGreetingCardManagement that represents some aspects of the GreetingCardManagement application that you have worked on in previous labs. The new solution has been created to start working with the MVVM design pattern, and yet maintain the look and feel of the existing GreetingCardManagement application. You will start by examining the existing solution, with particular focus on the MVVM bits that are different to previous implementations of the GreetingCardManagement solutions. Finally, you must add a new client model, a view-model, a view, and modify various other items used to implement MVVM as part of the lab. The solution has been built by using the Simple MVVM Toolkit, which you need to install as part of the lab.

Lab Instructions: Application Guidance

Lab End State


When you have completed the lab, the MVVMGreetingCardManagement application will contain a new view and all required MVVM items to make it a part of the application.

Exercise 1: Installing the Simple MVVM Toolkit


Task 1: Get the Simple MVVM Toolkit installer.
If you have an Internet connection on your virtual machine, 10554A-SEA-DEV, you can download the installer directly and save it to the desktop. Alternatively, you can get a copy from your instructor, who can supply an ISO file for you to attach to the virtual machine. Get the Simple MVVM Toolkit installer from CodePlex, http://go.microsoft.com/fwlink/?LinkId=225227 Note: In this lab, version 2.1.0.0 has been used. If a newer version is available, and you want to use 2.1.0.0, on the http://go.microsoft.com/fwlink/?LinkId=225227 page, click View all downloads in the upper-right download box. On the Downloads page, in the Other Downloads box, click Simple MVVM Toolkit v2.1.0.0, and then on the left of the page, click Simple MVVM Toolkit v2.1.0.0 to initiate the download. Get the Simple MVVM Toolkit installer from your instructor, located in an ISO file, and attach it to the virtual machine.

Task 2: Run the Simple MVVM Toolkit installer.


Double-click the executable installer file, SimpleMvvmInstaller.exe, to start the installation. In the Simple Mvvm Toolkit InstallShield Wizard box, on the Welcome to the InstallShield Wizard for Simple Mvvm Toolkit page, click Next. On the Readme Information page, click Next. On the Ready to install the Program page, click Install. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. On the InstallShield Wizard Completed page, clear the Show the readme file check box, and then click Finish.

Task 3: Register the Simple MVVM Toolkit project and item templates.
On the Start menu, click All Programs, expand Accessories, right-click Command Prompt, and then click Run as administrator. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. In the Administrator: Command Prompt box, at the prompt, type cd C:\Program Files\SimpleMvvmToolkit, and then press Enter. At the prompt, type SimpleMvvm-32wp.reg, and then press Enter. In the Registry Editor dialog box, click Yes. In the Registry Editor dialog box, click OK. Close the Administrator: Command Prompt box.

Lab Instructions: Application Guidance

Exercise 2: Examining a Silverlight MVVM project


Task 1: Open the MVVMGreetingCardManagement solution.
Open Visual Studio 2010. Open the MVVMGreetingCardManagement solution from the D:\Labfiles\Mod13\VB\Starter or D:\Labfiles\Mod13\CS\Starter folder. The Visual C# solution was created by using the SimpleMvvmRiaServices project template, and then customizing it slightly. The Visual Basic solution was created by using the Silverlight Business Application project template, and then adding the missing pieces, to make the two solutions as identical as possible. The two project templates are quite similar, with the SimpleMvvmRiaServices project template being a customization of the Silverlight Business Application project template. Notice the hosting ASP.NET Web Application project named, MVVMGreetingCardManagement.Web, which is the same type of hosting application you have been using throughout this course.

Task 2: Examine the model.


In the MVVMGreetingCardManagement project, expand the Models folder. Notice how the Models folder only contains the standard client model files created by the Silverlight Business Application project template. Currently, no application specific data models have been created. In the MVVMGreetingCardManagement.Web project, expand the Models folder. Notice how the Models folder contains the GreetingCardModel.edmx file with which you have worked previously. The server data model has been created for you.

Task 3: Examine the view-models.


In the MVVMGreetingCardManagement project, open and examine the HomeViewModel viewmodel, located in the ViewModels folder. Notice how the HomeViewModel inherits from the ViewModelBase class, which is one of two view-model base classes used with the Simple MVVM Toolkit. This one can be used for displaying a collection of objects, or used as a default view-model, if you have not planned which data will be displayed yet. Notice how the non-default constructor accepts an argument of type, IHomeServiceAgent, which is saved to the private serviceAgent member variable. The service agent is responsible for retrieving the data for the view-model to expose. Expand the collapsed regions. There is currently no code in the Properties, Methods, and Commands regions, because it is not needed for this view-model. Notice the ErrorNotice event declaration, located in the Notifications region, which is used by the NotifyError method, located in the Helpers region to inform the view of an error. The NotifyError method calls the Notify method of the base class, ViewModelBase.

Lab Instructions: Application Guidance

Close the HomeViewModel view-model. Open and examine the MainPageViewModel view-model, located in the ViewModels folder. Notice how the default constructor calls the RegisterToReceiveMessages method, inherited from the base class, to register or subscribe to messages that arrive on the MessageBus implementation. Only navigation token messages are subscribed to, by specifying the MessageTokens.Navigation constant value. This value is defined in the MessageTokens class, located in the Others folder. The Navigation value is currently the only value defined, but to extend the messaging system, you can add new constant values to this class.

Expand the collapsed regions. Notice the SelectedPage property declaration, located in the Properties region. This property and the corresponding backing member field are used to keep track of the current page in the navigation system implemented, and the view can bind to this property. You will see more of how navigation is implemented by using an event handler, methods, and the MainPage view later.

Notice the Navigate and OnNavigationRequested methods, both located in the Methods region. The latter should be familiar because it is the same event handler method you have seen throughout the implementations of the Silverlight Business Application and Silverlight Navigation Application. However, unlike the previous implementations, the OnNavigationRequested method calls the Navigate method, passing the page name, stored in the Message property of the NotificationEventArgs argument. This class is custom to the Simple MVVM Toolkit, and part of the messaging implementation.

Notice the NavigateCommand property, located in the Commands region. This property is used by the HyperlinkButton controls, used as part of the menu and user exposed navigation implementation, by way of binding. The DelegateCommand is custom to the Simple MVVM Toolkit, and used as the type for the NavigateCommand property.

Close the MainPageViewModel view-model.

Task 4: Examine the views.


Open and examine the HomeView view, located in the Views folder. Notice how the designer and the XAML view look more or less the same as the Home.xaml page used in the previous implementations of the Silverlight Business Application project template. One exception is how the DataContext property of the Page control is bound to the HomeViewModel by using a static resource that locates the view-model. This is bound the same way as you saw during the demonstrations. Close the HomeView view. Open and examine the MainPage view, located in the root folder. Notice how the designer and the XAML view look similar to the MainPage.xaml UserControl used in the previous implementations of the Silverlight Business Application project template. There are a few differences though, as detailed in the next few steps. The DataContext property of the UserControl control is bound to the MainPageViewModel, just like the HomeView view.

Lab Instructions: Application Guidance

The Source property of the Frame control used by the Silverlight navigation system is bound to the SelectedPage property of the MainPageViewModel. The HyperlinkButton control, named Link1, uses the Command and CommandParameter properties for navigation, instead of the NavigateUri property used by previous implementations of the MainPage.xaml view. The Command property binds to the NavigateCommand property of the MainPageViewModel property, passing the string Home, in the CommandParameter property.

Close the MainPage view.

Task 5: Examine the services.


Examine the IHomeServiceAgent interface, located in the Services folder. Notice how the interface is empty, and unlike the implementation you saw in the demonstration, does not define any methods. Close the IHomeServiceAgent code file. Examine the HomeServiceAgent class. Notice how the class is empty. The interface and the class are currently empty, awaiting any data methods to be added, if the view-model needs to expose properties and/or methods for the view to consume. Notice how there is no service agent for the MainPageViewModel in the Services folder; the MainPageViewModel does not need any because it really only serves the purpose of a master page or main page, enabling and facilitating navigation, and exposing the frame, in which Page controls can be shown. The HomeView currently does not need a service agent either, but it has implemented with a service agent, to ensure it is easy to add at a later date. Close the HomeServiceAgent code file. In the MVVMGreetingCardManagement.Web project, expand the Services folder. Notice how the Services folder contains the GreetingCardDomainService.vb or GreetingCardDomainService.cs and the GreetingCardDomainService.metadata.vb or GreetingCardDomainService.metadata.cs files, with which you have worked previously. The server service layer has been created for you.

Task 6: Examine the App and View-Model locator.


In the MVVMGreetingCardManagement project, examine App.xaml. In the XAML view, notice how an instance of the InjectedViewModelLocator class is added to the Application.Resources resource dictionary, ensuring its availability throughout the lifetime of the application. Close the App.xaml file. Examine the InjectedViewModelLocator class, located in the Locators folder. In the InjectedViewModelLocator class, notice the shared/static constructor that checks if the element or control is currently running in the context of a designer, such as Visual Studio or

Lab Instructions: Application Guidance

Expression Blend. If not, then a new DeploymentCatalog object is created and passed to the CompositionHost.Initialize method. This is used with the Microsoft Extensibility Framework (MEF) for supporting dependency injection of the service agents. Without going into details beyond the scope of this course, it basically means that you can "inject" any type of service agent. Notice how a public property named AgentType, and the corresponding backing member variable, get or set the type of service agents used. The property returns a member of the AgentType enumeration, which contains three members: Mock, Real, and Unspecified. You use the values to specify whether you want to use the Mock or the Real service agents, allowing you to dynamically select if mock data or real data should be used. In the InjectedViewModelLocator class, notice the default constructor that also checks if the element or controls is currently running in the context of a designer. If not, the CompositionInitializer.SatisfyImports MEF method is used inject the current service agent object. In addition, the Debug.Assert method is used to throw an exception, if the HomeViewModel is not created correctly, and thus, the corresponding service agent and the correct agent type. The actual instantiation of the both of these objects happens when the Debug.Assert method is called, or when the HomeViewModel property, covered later, is bound to from the view. Notice the public and read-only property named, HomeViewModel, which creates and returns an instance of the HomeViewModel. If a corresponding service agent is found, it is created, and passed the HomeViewModel constructor. Notice the public and read-only property named MainPageViewModel, which returns an instance of the MainPageViewModel. The MainPageViewModel does not need a service agent, so the property code is straight-forward. Close the InjectedViewModelLocator code file.

Task 7: Test the application.


Run the application. Notice how the application looks like the GreetingCard applications you have created previously in this course. The logon functionality also works, using the Student user credentials. Close Internet Explorer.

Lab Instructions: Application Guidance

Exercise 3: Implementing MVVM Items


Task 1: Add the SendersServiceAgent service agent.
In the MVVMGreetingCardManagement project, add a new service agent interface, named ISendersServiceAgent, to the Services folder. The service agent will help with the data management for the SendersViewModel view-model, which you will build later. Change the added project item from a class to an interface by modifying the generated code to resemble to following code.
[Visual Basic] Public Interface ISendersServiceAgent End Interface

[Visual C#] public interface ISendersServiceAgent { }

[Visual C# only] Bring the System.Collections.Generic and MVVMGreetingCardManagement.Web.Models namespaces into scope in the ISendersServiceAgent.cs code file. These namespaces contain the argument types used in the method added next.

Add a method named, GetSenders, to the interface. The method should not return a value, but accept one argument named, completed. The argument must be of delegate type, Action, which accepts a generic List of type, Sender, and an Exception.

Save and close the ISendersServiceAgent code file. Implement the ISendersServiceAgent service agent interface in a new class named, SendersServiceAgent. [Visual C# only] Bring the MVVMGreetingCardManagement.Web.Services namespace into scope in the SendersServiceAgent.cs code file. This namespace contains the argument types used in the variable added next.

Bring the SimpleMvvmToolkit namespace into scope in the SendersServiceAgent code file. This namespace contains the attribute type applied to the class next. To the SendersServiceAgent class, apply the ServiceAgentExport attribute. This attribute is used to specify which type of service agents are exported, and the type of agent. The attribute should resemble the following code.
[Visual Basic] <ServiceAgentExport(GetType(ISendersServiceAgent), AgentType:=AgentType.Real)>

[Visual C#] [ServiceAgentExport(typeof(ISendersServiceAgent), AgentType = AgentType.Real)]

Lab Instructions: Application Guidance

In the SendersServiceAgent class, add and instantiate a new private member variable named, gcDomainContext, of type, GreetingCardDomainContext. This variable will be used for accessing the Entity Data Model on the hosting server, by using the generated RIA Service code, available on the client.

Bring the System.ServiceModel.DomainServices.Client namespace into scope in the SendersServiceAgent code file. This namespace contains the argument types used in the method implemented next.

[Visual C# only] Bring the MVVMGreetingCardManagement.Web.Models, System.Linq, and System.Collections.Generic namespaces into scope in the SendersServiceAgent.cs code file. These namespaces contain the argument types used in the method implemented next.

In the SendersServiceAgent class, to the GetSenders method, add the following code (overwriting any existing code). The code creates a new entity query that calls the GetSenders query on the server (named GetSendersQuery on the client), by using the private gcDomainContext variable. Subsequently, the load operation is initiated and executed. If everything goes well, the retrieved collection of Sender objects is assigned to the completed argument callback.
[Visual Basic] Dim query As EntityQuery(Of Sender) = gcDomainContext.GetSendersQuery() ' Load GetSendersQuery gcDomainContext.Load(query, Sub(load) ' Declare error and result Dim err As Exception = Nothing Dim senders As IEnumerable(Of Sender) = Nothing ' Set error or result If load.HasError Then err = load.Error Else senders = load.Entities End If ' Invoke completion callback completed(senders.ToList, err) End Sub, Nothing)

[Visual C#] EntityQuery<Sender> query = gcDomainContext.GetSendersQuery(); // Load GetSendersQuery gcDomainContext.Load(query, load => { // Declare error and result Exception err = null; IEnumerable<Sender> senders = null; // Set error or result if (load.HasError) { err = load.Error; } else

10

Lab Instructions: Application Guidance

{ }

senders = load.Entities;

// Invoke completion callback completed(senders.ToList(), err); }, null);

Save and close the SendersServiceAgent code file.

Task 2: Add the SendersViewModel view-model.


In the MVVMGreetingCardManagement project, add a new view-model, named SendersViewModel, to the ViewModels folder. [Visual C# only] Change the namespace for the SendersViewModel class from MVVMGreetingCardManagement.ViewModels to MVVMGreetingCardManagement. This will ensure the namespace is the same as the existing view-model classes. Bring the SimpleMvvmToolkit and System.ServiceModel.DomainServices.Client namespaces into scope in the SendersViewModel code file. These namespaces contain the argument types used in the class modification next. Derive the SendersViewModel class from the generic ViewModelBase class, of SendersViewModel. In the SendersViewModel class, declare a new private member variable named, serviceAgent, of type, ISendersServiceAgent. This variable will be used for storing a reference to the service agent used for retrieving data from the model. Bring the System.Collections.ObjectModel namespace into scope in the SendersViewModel code file. This namespace contain the argument types used by the private member variables declared next. [Visual C# only] Bring the MVVMGreetingCardManagement.Web.Models namespace into scope in the SendersViewModel.cs code file. This namespace contain the argument types used by the private member variables declared next. Add the following private member variables. The sndrs variable is used for storing an ObservableCollection of the retrieved Sender objects from the model. The selSender variable is used to point to the currently selected Sender in the UI. The two Boolean member variables are used to set and check if the view-model is busy with an operation, or if the senders can be loaded.
[Visual Private Private Private Private Basic] sndrs As ObservableCollection(Of Sender) selSender As Sender busy As Boolean ableToLoad As Boolean = True

[Visual private private private

C#] ObservableCollection<Sender> sndrs; Sender selSender; bool busy;

Lab Instructions: Application Guidance

11

private bool ableToLoad = true;

Create an empty default constructor. [Visual C# only] Bring the MVVMGreetingCardManagement.Services namespace into scope in the SendersViewModel.cs code file. This namespace contains the argument types used in the nondefault constructor implemented next.

Create a non-default constructor that accepts a single argument of type, ISendersServiceAgent. The constructor must assign the passed service agent argument to the private member variable, serviceAgent, and call the LoadSenders method to be created later. The constructor is used by the view-model locator.

Append the following code to the SendersViewModel class. The Notifications region contains two public events, used to make the view aware of an error or when the sender objects have been loaded from the model.
[Visual Basic] #Region "Notifications" Public Event ErrorNotice As EventHandler(Of NotificationEventArgs(Of Exception)) Public Event SendersLoadedNotice As EventHandler(Of NotificationEventArgs) #End Region

[Visual C#] #region Notifications public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice; public event EventHandler<NotificationEventArgs> SendersLoadedNotice; #endregion

Append the following code to the SendersViewModel class. The Properties region contains several public properties, all used by the view and the view-model for binding the two objects and managing when an operation can be performed. All properties ensure that any change to the property value is notified to those binding to the property, such as controls in the view.
[Visual Basic] #Region "Properties" Public Property Senders As ObservableCollection(Of Sender) Get Return Me.sndrs End Get Set(ByVal value As ObservableCollection(Of Sender)) Me.sndrs = value NotifyPropertyChanged(Function(m) m.Senders) End Set End Property Public Property SelectedSender As Sender Get Return Me.selSender End Get

12

Lab Instructions: Application Guidance

Set(ByVal value As Sender) Me.selSender = value Me.CanLoad = Not IsBusy NotifyPropertyChanged(Function(m) m.SelectedSender) End Set End Property Public Property IsBusy As Boolean Get Return Me.busy End Get Set(ByVal value As Boolean) Me.busy = value Me.CanLoad = Not IsBusy NotifyPropertyChanged(Function(m) m.IsBusy) End Set End Property Public Property CanLoad As Boolean Get Return Me.ableToLoad End Get Set(ByVal value As Boolean) Me.ableToLoad = value NotifyPropertyChanged(Function(m) m.CanLoad) End Set End Property #End Region

[Visual C#] #region Notifications public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice; public event EventHandler<NotificationEventArgs> SendersLoadedNotice; #endregion #region Properties public ObservableCollection<Sender> Senders { get { return this.sndrs; } set { this.sndrs = value; NotifyPropertyChanged(m => m.Senders); } } public Sender SelectedSender { get { return this.selSender; } set { this.selSender = value;

Lab Instructions: Application Guidance

13

this.CanLoad = !IsBusy; NotifyPropertyChanged(m => m.SelectedSender);

public bool IsBusy { get { return this.busy; } set { this.busy = value; this.CanLoad = !IsBusy; NotifyPropertyChanged(m => m.IsBusy); } } public bool CanLoad { get { return this.ableToLoad; } set { this.ableToLoad = value; NotifyPropertyChanged(m => m.CanLoad); } } #endregion

Append the following code to the SendersViewModel class. The Methods region contains a single method named, LoadSenders, which does as the name indicates; it uses the GetSenders method of the service agent to initiate and execute the loading of the senders from the model.
[Visual Basic] #Region "Methods" Public Sub LoadSenders() serviceAgent.GetSenders( _ Sub(entities, err) SendersLoaded(entities, err) End Sub ) ' Reset property Me.Senders = Nothing ' Flip busy flag Me.IsBusy = True End Sub #End Region

[Visual C#] #region Methods

14

Lab Instructions: Application Guidance

public void LoadSenders() { serviceAgent.GetSenders( (entities, err) => { SendersLoaded(entities, err); }); // Reset property this.Senders = null; // Flip busy flag this.IsBusy = true;

#endregion

[Visual C# only] Bring the System.Collections.Generic namespace into scope in the SendersViewModel.cs code file. This namespace contains the types used in the callback methods implemented next.

Append the following code to the SendersViewModel class. The Completion Callbacks region contains a single method named, SendersLoaded, which is asynchronously invoked from the LoadSenders method, described previously. The SendersLoaded method checks for errors, and notifies the view if an error occurred. If no error occurred, the Senders property is set, the SelectedSender is set to the first Sender object returned, and finally the view is notified that the loading of the sender objects has completed.
[Visual Basic] #Region "Completion Callbacks" Private Sub SendersLoaded(ByVal entities As List(Of Sender), ByVal err As Exception) ' If no error is returned, set the model to entities If err Is Nothing Then Senders = New ObservableCollection(Of Sender)(entities) Else NotifyError("Unable to retrieve sender", err) End If ' Set SelectedSender to the first item If Senders.Count > 0 Then SelectedSender = Senders(0) End If ' Notify view Notify(SendersLoadedNoticeEvent, New NotificationEventArgs("Senders were successfully loaded")) ' Finished IsBusy = False End Sub #End Region

[Visual C#] #region Completion Callbacks

Lab Instructions: Application Guidance

15

private void SendersLoaded(List<Sender> entities, Exception err) { // If no error is returned, set the model to entities if (err == null) { Senders = new ObservableCollection<Sender>(entities); } else { NotifyError("Unable to retrieve sender", err); } // Set SelectedSender to the first item if (Senders.Count > 0) { SelectedSender = Senders[0]; } // Notify view Notify(SendersLoadedNotice, new NotificationEventArgs("Senders were successfully loaded")); // Finished IsBusy = false; } #endregion

Append the following code to the SendersViewModel class. The Helpers region contains a single method, NotifyError, which was described previously in Task 3 of Exercise 2.
[Visual Basic] #Region "Helpers" ' Helper method to notify View of an error Private Sub NotifyError(ByVal message As String, ByVal err As Exception) ' Notify view of an error Notify(Of Exception)(ErrorNoticeEvent, New NotificationEventArgs(Of Exception)(message, err)) End Sub #End Region

[Visual C#] #region Helpers // Helper method to notify View of an error private void NotifyError(string message, Exception err) { // Notify view of an error Notify<Exception>(ErrorNotice, new NotificationEventArgs<Exception>(message, err)); } #endregion

Save and close the SendersViewModel code file.

16

Lab Instructions: Application Guidance

Task 3: Add the SendersView view.


To the MVVMGreetingCardManagement project, add an existing Silverlight Page named, SendersView, to the Views folder. Open the SendersView view. Notice how the designer and the XAML view look more or less the same as the Home.xaml page used in the lab exercises for Module 2. In the designer, you can see the Label and TextBox controls for displaying the display name and email fields for a Sender entity. Then, there is a DataPager control for moving back and forth between the Sender entities, and below that, a DataGrid control for displaying the Card entities for the selected Sender entity, in true master-detail style. In the XAML view, you can see how the DataContext property of the Page control is bound to the SendersViewModel by using a static resource that locates the view-model. The two TextBox controls are bound to the SelectedSender.DisplayName and SelectedSender.Email properties of the SendersViewModel view-model. The DataGrid control is bound to the SelectedSender.Cards property, whereas the DataPager control is not bound declaratively. Close the SendersView view. Open the SendersView view, in Code view. In the SendersView class, in the default constructor, you can see how the private model variable is bound to the SendersViewModel through the DataContext property. The ErrorNotice and SendersLoadedNotice events of the SendersViewModel view-model are handled by the corresponding event handlers, OnErrorNotice and OnSendersLoadedNotice. This way, the viewmodel can communicate with the view. Notice the OnErrorNotice event handler method, which shows an error message and outputs trace information. Notice the OnSendersLoadedNotice event handler method, which sets the Source property of the DataPager control to a new PagedCollectionView collection, which wraps the Senders collection from the view-model. It is wrapped in a PagedCollectionView collection, to ensure the DataPager control can properly enumerate the items. Notice the SendersDataPager_PageIndexChanged event handler method, which sets the SelectedSender property of the view-model to the currently selected page index. The DataPager page index is set to 1, which means this index matches the order of the Senders collection of the view-model. Close the SendersView code file. Open MainPage.xaml. In MainPage.xaml, in the XAML view, locate the following markup.
<Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>

Immediately below the located markup, but above the closing StackPanel tag, add a new selfclosing HyperlinkButton control element named, SendersHyperlinkButton. The HyperlinkButton control is bound to the NavigateCommand property of the MainPageViewModel, which you examined in Exercise 2. The name of the view to which to

Lab Instructions: Application Guidance

17

navigate is passed to the NavigateCommand property by setting the CommandParameter property of the HyperlinkButton. Set the following properties.
Property Name Content Command CommandParameter Style TargetName Property Value {Binding Path=ApplicationStrings.SendersPageTitle, Source={StaticResource ResourceWrapper}} {Binding NavigateCommand} SendersView {StaticResource LinkStyle} ContentFrame

Save and close MainPage.xaml. Build the solution.

Task 4: Configure the application resources.


In the MVVMGreetingCardManagement project, open the Resource Designer for the Assets\Resources\ApplicationStrings.resx resource file. The Resource Designer opens, displaying a three-column grid containing the resource strings in the ApplicationStrings.resx resource file. Add a new key named, SendersPageTitle, with a value, Senders. Save the changes. Close the Resource Designer.

Task 5: Modify the View-Model locator.


Open the InjectedViewModelLocator.vb or InjectedViewModelLocator.cs code file, located in the Locators folder. In the default non-shared/non-static constructor, append the following code to the If/if construct.
[Visual Basic] Debug.Assert(Not Me.SendersViewModel Is Nothing, String.Format(ApplicationStrings.ServiceAgentNotFound, "ISendersServiceAgent", AgentType))

[Visual C#] Debug.Assert(this.SendersViewModel != null, string.Format(ApplicationStrings.ServiceAgentNotFound, "ISendersServiceAgent", agentType));

[Visual C# only] Bring the MVVMGreetingCardManagement.Services namespace into scope in the InjectedViewModelLocator.cs code file. The namespace contain the types used in the properties added next.

To the InjectedViewModelLocator class, append the following code.


[Visual Basic] <ImportMany()> Public Property SendersServiceAgents As Lazy(Of ISendersServiceAgent, IServiceAgentMetadata)()

18

Lab Instructions: Application Guidance

Public ReadOnly Property SendersViewModel As SendersViewModel Get Dim serviceAgent = SendersServiceAgents _ .Where(Function(sa) sa.Metadata.AgentType = AgentType).FirstOrDefault() Dim viewModel As SendersViewModel = Nothing If Not serviceAgent Is Nothing Then viewModel = New SendersViewModel(serviceAgent.Value) ElseIf DesignerProperties.IsInDesignTool Then viewModel = New SendersViewModel() End If Return viewModel End Get End Property

[Visual C#] [ImportMany] public Lazy<ISendersServiceAgent, IServiceAgentMetadata>[] SendersServiceAgents { get; set; } public SendersViewModel SendersViewModel { get { var serviceAgent = SendersServiceAgents .Where(sa => sa.Metadata.AgentType == agentType).FirstOrDefault(); SendersViewModel viewModel = null; if (serviceAgent != null) viewModel = new SendersViewModel(serviceAgent.Value); else if (DesignerProperties.IsInDesignTool) viewModel = new SendersViewModel(); } return viewModel;

Task 6: Test the application.


Run and test the application. In Internet Explorer, click Senders. Notice how the Sender data is displayed. Navigate back and forth with the DataPager control to see all the Sender entities. Close all applications. You have now completed this lab.

Lab Instructions: Application Guidance

19

Lab Shutdown
After finishing the lab, you must shutdown the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Instructions: Windows Phone DevelopmentFirst Look

Module 14
Lab Instructions: Windows Phone DevelopmentFirst Look
Contents:
Exercise 1: Capturing User Input Exercise 2: Responding to Orientation Changes Exercise 3: Adding Page Navigation Exercise 4: Monitoring Game Status Exercise 5: Sharing Data Between Pages 3 6 9 10 13

Lab Instructions: Windows Phone DevelopmentFirst Look

Lab: Creating a Windows Phone Application

Lab Introduction
In this lab, you will put into practice some of the concepts you have learned in this module. You will work with a Tic Tac Toe game, where you will examine how to capture user input and ensure the application can respond to orientation changes. In addition, you will add navigation between the two application pages, and set up game monitoring by using a DispatcherTimer object. Finally, you will set up data sharing between pages by using a public property in the App class. The exercises for this lab are: Exercise 1: Capturing User Input Exercise 2: Responding to Orientation Changes Exercise 3: Adding Page Navigation Exercise 4: Monitoring Game Status Exercise 5: Sharing Data Between Pages

Lab Setup
For this lab, you will use the available virtual machine environment. Before you begin the lab, you must: Start the 10554A-SEA-DEV virtual machine, and then log on by using the following credentials: User name: Student Password: Pa$$w0rd

Lab Start State


You will start with a starter Windows Phone solution, TicTacToe, partly implementing a Tic Tac Toe game.

Lab Instructions: Windows Phone DevelopmentFirst Look

Lab End State


When you have completed the lab, the TicTacToe application will respond to orientation changes, and you will be able to navigate between the two application pages. You will also monitor the game by using a DispatcherTimer object. Sharing the players name is also implemented by using a public property in the App class.

Exercise 1: Capturing User Input


Task 1: Examine the standard input behavior.
Open Visual Studio 2010. Open the TicTacToe solution from the D:\Labfiles\Mod14\VB\Starter or D:\Labfiles\Mod14\CS\Starter folder. Set the Windows Phone 7 emulator as the target for Silverlight for Windows Phone projects by using the list on the Standard toolbar. Run the application. The Windows Phone emulator opens. It may take a while before your application is deployed, loaded, and displayed. Click the Player 1 text box, and notice how the Software Input Panel (SIP) keyboard automatically slides open. In the Player 1 text box, type Student, by using the SIP keyboard. In the Player 1 text box, click the text Student. Notice how the text is selected, and the copy icon is displayed above the selected text.

Copy the text by using the copy icon. Notice how the paste icon is displayed just above the SIP keyboard.

Lab Instructions: Windows Phone DevelopmentFirst Look

Close the SIP keyboard by clicking the application background.

Task 2: Play the game.


In the game pad, click any of the square boxes, to start the game. Notice how the application automatically selects a box. You, as Player 1, use the X as the symbol for a selected box, whereas the application or computer as Player 2 uses the O symbol. Keep playing till you win, or till you have three X symbols on a single line. This can be horizontal, vertical, or diagonal. Notice the message box that pops up with the winning message. Close the message box. Notice the new message box, prompting you to play another game. Cancel a new game. Close the Windows Phone 7 emulator.

Task 3: Examine the MainPage.xaml page.


In the TicTacToe project, open MainPage.xaml. In the MainPage.xaml window, locate the control named player1TextBox. Examine the player1TextBox control, which is a TextBox control.
[Visual Basic] <TextBox Height="73" HorizontalAlignment="Left" Margin="26,60,0,0" Name="player1TextBox" Text="enter name to begin" VerticalAlignment="Top" Width="272" Grid.Row="1" />

[Visual C#] <TextBox Height="73" HorizontalAlignment="Left" Margin="26,60,0,0" Name="player1TextBox" Text="enter name to begin" VerticalAlignment="Top" Width="272" GotFocus="player1TextBox_GotFocus" Grid.Row="1" />

In the MainPage.xaml window, locate the control named textBlock1.

Lab Instructions: Windows Phone DevelopmentFirst Look

Examine the textBlock1 control, which is a TextBlock control. In addition, notice the player2TextBox and textBlock2 controls that are used for player display and user input.
[Visual Basic] <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,24,0,0" Name="textBlock1" Text="Player 1" VerticalAlignment="Top" Grid.Row="1" /> <TextBox Height="73" HorizontalAlignment="Left" Margin="26,172,0,0" Name="player2TextBox" Text="Computer" VerticalAlignment="Top" Width="269" Grid.Row="1" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,136,0,0" Name="textBlock2" Text="Player 2" VerticalAlignment="Top" Grid.Row="1" />

[Visual C#] <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,24,0,0" Name="textBlock1" Text="Player 1" VerticalAlignment="Top" Grid.Row="1" /> <TextBox Height="73" HorizontalAlignment="Left" Margin="26,172,0,0" Name="player2TextBox" Text="Computer" VerticalAlignment="Top" Width="269" Grid.Row="1" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,136,0,0" Name="textBlock2" Text="Player 2" VerticalAlignment="Top" Grid.Row="1" />

Open the MainPage.xaml in Code view. Examine the GotFocus event handler for the player1TextBox control. Notice that the current text in the TextBox control is selected, when the TextBox control receives focus by calling the SelectAll method of the TextBox class.
[Visual Basic] ' select the text name of player 1 when the TextBox gets focus - makes a name change easier Private Sub player1TextBox_GotFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles player1TextBox.GotFocus player1TextBox.SelectAll() End Sub

[Visual C#] // select the text name of player 1 when the TextBox gets focus - makes a name change easier private void player1TextBox_GotFocus(object sender, RoutedEventArgs e) { player1TextBox.SelectAll(); }

Lab Instructions: Windows Phone DevelopmentFirst Look

Exercise 2: Responding to Orientation Changes


Task 1: Modify MainPage.xaml to support all orientations.
Switch to MainPage.xaml. Locate the opening tag for the main PhoneApplicationPage control or element.
<phone:PhoneApplicationPage x:Class="TicTacToe.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">

Locate the markup for the SupportedOrientations property.


SupportedOrientations="Portrait"

Modify the value for the SupportedOrientations property, to support both portrait and landscape orientations. Save the changes.

Task 2: Modify MainPage.xaml to handle the OrientationChanged event and support the Grid layout technique.
Switch to the MainPage.xaml code file. Locate the TODO comment, Call the PositionControls method, in the MainPage_OrientationChanged or OnOrientationChanged event handler.

Lab Instructions: Windows Phone DevelopmentFirst Look

[Visual Basic] ' this method responds to a phone orientation change Private Sub MainPage_OrientationChanged(ByVal sender As Object, ByVal e As Microsoft.Phone.Controls.OrientationChangedEventArgs) Handles MyBase.OrientationChanged MyBase.OnOrientationChanged(e) ' TODO: Call the PositionControls method End Sub

[Visual C#] // this method responds to a phone orientation change protected override void OnOrientationChanged(OrientationChangedEventArgs args) { base.OnOrientationChanged(args); // TODO: Call the PositionControls method }

To the MainPage_OrientationChanged or OnOrientationChanged event handler, append code to call the PositionControls method, passing the event arguments received. Locate the TODO comment, Change the display location of controls, in the PositionControls method.
[Visual Basic] ... ' If not in portrait, move buttonList content to visible row and column. Else ' TODO: Change the display location of controls End If

[Visual C#] ... // If not in portrait, move buttonList content to visible row and column. else { // TODO: Change the display location of controls }

In the PositionControls method, append code to the Else/else part of the If...Then...Else/if...else structure, to place the textBlock1, player1TextBox, textBlock2, player2TextBox, and textBlock3 controls, in row 1, column 2, by using the grid layout technique, and the Grid.SetRow and Grid.SetColumn methods. Remember that the row and column numbers are zero based. Save the changes.

Lab Instructions: Windows Phone DevelopmentFirst Look

Task 3: Test the orientation changes.


Run the application. In the Windows Phone 7 emulator, change from portrait orientation to landscape left orientation, and notice the flow of the controls is exactly the same as in portrait orientation. In the Windows Phone 7 emulator, change from landscape left orientation to portrait orientation, and notice the flow the controls is now exactly the same as when you started the application. Close the Windows Phone 7 emulator.

Lab Instructions: Windows Phone DevelopmentFirst Look

Exercise 3: Adding Page Navigation


Task 1: Add code to navigate to the AdvancedGamePlay page.
In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment Construct the code to navigate to the AdvancedGamePlay page, in the textBlock3_ManipulationStarted event handler. In the textBlock3_ManipulationStarted event handler method, append code to navigate to the page, which has the name stored in the local destinationPage string variable. Use the shared/static NavigationService.Navigate, passing in a new relative URI. In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, Construct the code to navigate back to the MainPage using the NavigationService, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. Notice how the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file is opened, and the cursor placed at the TODO comment. In the textBlock3_ManipulationStarted event handler method, append code to navigate back to the MainPage page. Use the shared/static NavigationService.Navigate, passing in a new relative URI. Save the changes.

10

Lab Instructions: Windows Phone DevelopmentFirst Look

Exercise 4: Monitoring Game Status


Task 1: Examine the AdvancedGamePlay.xaml page.
In the TicTacToe project, open AdvancedGamePlay.xaml. In the AdvancedGamePlay.xaml window, locate the Grid control named buttonFrameGrid. Examine the buttonFrameGrid control, which in addition to the Button controls in the MainPage.xaml page for selecting a square, also holds a number of Polyline controls.
<Polyline Stroke="White" StrokeThickness="5" Points="10,10,290,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineDiagonalRightAndDown" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,290,290,10" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineDiagonalRightAndUp" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="50,10,50,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalLeftColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="150,10,150,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalCenterColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="250,10,250,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalRightColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,50,290,50" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalTopRow" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,150,290,150" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalCenterRow" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,250,290,250" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalBottomRow" Visibility="Collapsed" />

The Polyline control is generally used for drawing a series of connected straight lines. In the context of the Tic Tac Toe game, it is used to draw a straight line covering the three winning squares, when a game is won. Open the AdvancedGamePlay.xaml in Code view. Locate and examine the PrepareForWinnerLineDraw method. myPolyline is declared as a member variable at the top of the class as a Polyline object, and firstPoint and secondPoint are declared as member variables at the top of the class as Point objects. This method is used to initialize myPolyline with the data from winnerLine, which is also declared as a member variable at the top of the class as a Polyline object.
[Visual Basic] ' This method is used to initialize myPolyline with data from the winnerLine Public Sub PrepareForWinnerLineDraw() myPolyline = winnerLine ' get the first and last point of the winning path (polyline) firstPoint = winnerLine.Points.First() lastPoint = winnerLine.Points.Last() myPolyline.Points.Clear() ' add the first point of the winning path to the new polyline myPolyline.Points.Add(firstPoint) myPolyline.Visibility = System.Windows.Visibility.Visible ' create a point that is the end of the line as it is constructed/drawn myEndPoint = myPolyline.Points.First() End Sub

Lab Instructions: Windows Phone DevelopmentFirst Look

11

[Visual C#] // This method is used to initialize myPolyline with data from the winnerLine public void PrepareForWinnerLineDraw() { myPolyline = winnerLine; // get the first and last point of the winning path (polyline) firstPoint = winnerLine.Points.First(); lastPoint = winnerLine.Points.Last(); myPolyline.Points.Clear(); // add the first point of the winning path to the new polyline myPolyline.Points.Add(firstPoint); myPolyline.Visibility = System.Windows.Visibility.Visible; // create a point that is the end of the line as it is constructed/drawn myEndPoint = myPolyline.Points.First();

Locate and examine the DrawWinnerLine method, which is used to draw the actual winner line.
[Visual Basic] Public Sub DrawWinnerLine() ' construct the next point to add to the polyline Dim myNextPoint As New Point() myNextPoint.X = myEndPoint.X + ((lastPoint.X - firstPoint.X) / CType(numberOfLineSegments, Double)) myNextPoint.Y = myEndPoint.Y + ((lastPoint.Y - firstPoint.Y) / CType(numberOfLineSegments, Double)) ' add the point of the winning path to the new polyline myPolyline.Points.Add(myNextPoint) lineSegmentCounter += 1 If lineSegmentCounter >= numberOfLineSegments Then gameStatus = "game complete, announcing game result" Else myEndPoint = myNextPoint End If End Sub

[Visual C#] public void DrawWinnerLine() { // construct the next point to add to the polyline Point myNextPoint = new Point(); myNextPoint.X = myEndPoint.X + ((lastPoint.X - firstPoint.X) / (double) numberOfLineSegments); myNextPoint.Y = myEndPoint.Y + ((lastPoint.Y - firstPoint.Y) / (double) numberOfLineSegments); // add the point of the winning path to the new polyline myPolyline.Points.Add(myNextPoint); lineSegmentCounter++; if (lineSegmentCounter >= numberOfLineSegments) { gameStatus = "game complete, announcing game result";

12

Lab Instructions: Windows Phone DevelopmentFirst Look

} else { } }

myEndPoint = myNextPoint;

Lab Instructions: Windows Phone DevelopmentFirst Look

13

Exercise 5: Sharing Data Between Pages


Task 1: Create a public property for sharing data between pages.
In the App.xaml.vb or App.xaml.cs file, locate the TODO comment, Create a public property that can be used to facilitate sharing data between pages, at the top of the App class. In the App class, after the located comment, add code to create an auto-implemented property named, FirstPlayerTextString, of type, String/string. In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, Construct code to share data between pages, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. In the textBlock3_ManipulationStarted event handler method, after the located comment, assign the value of the Text property of the player1TextBox to the FirstPlayerTextString property in the App class. In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment, Construct code in MainPage to share data between pages, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. In the textBlock3_ManipulationStarted event handler method, after the located comment, assign the value of the Text property of the player1TextBox to the FirstPlayerTextString property in the App class. In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment, In MainPage assign the value of the shared data (FirstPlayerTextString) to nameString below, in the OnNavigatedTo event handler. Use the Task List window to locate the comment. In the OnNavigatedTo event handler method, after the located comment, assign the value of the FirstPlayerTextString property in the App class to the Text property of the player1TextBox. In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, assign the value of the shared data (FirstPlayerTextString) to nameString below, in the OnNavigatedTo event handler. Use the Task List window to locate the comment. In the OnNavigatedTo event handler method, after the located comment, assign the value of the FirstPlayerTextString property in the App class to the Text property of the player1TextBox. In the constructor, after the located comment, create the variable property of monitorGameStatusDispatcherTimer as a new instance of DispatcherTimer. Set the Interval property of property of monitorGameStatusDispatcherTimer to 34 milliseconds using a new TimeSpan object. Wire up the existing MonitorGameStatus method to the Tick event of monitorGameStatusDispatcherTimer. Start monitorGameStatusDispatcherTimer.

Task 2: Play the game.


Run the application. The Windows Phone emulator opens. It may take a while before your application is deployed, loaded, and displayed. Click the Player 1 text box. In the Player 1 text box, type Student by using the SIP keyboard. Click the application background to close the SIP keyboard.

14

Lab Instructions: Windows Phone DevelopmentFirst Look

Switch to the advanced level. Notice how the Student name has been copied across from the MainPage and is now stored in the Player 1 text box. In the game pad, click any of the squares, separated by a dashed line, to start the game. Notice how the application automatically selects a box. This time the application selection is more advanced; it is seriously trying to win. You, as Player 1, use the X as the symbol for a selected box, whereas the application or computer as Player 2 uses the O symbol. Keep playing till you win, draw, or lose. Notice that if you draw, the message box pops up with the winning message. If you win or lose, you will see a message box stating whether the X's or O's win. In addition, notice the straight line being drawn across the three winning squares. Close the message box. Notice the new message box, prompting you to play another game. Cancel a new game. Switch to the basic level. Close the Windows Phone 7 emulator. Close all applications. You have now completed this lab.

Lab Shutdown
After finishing the lab, you must shut down the virtual machine and revert the changes to prepare for the next lab. In the Hyper-V virtual machine window, on the Action menu, click Turn Off. In the Turn Off Machine dialog box, click Turn Off. On the Action menu, click Revert. In the Revert Virtual Machine dialog box, click Revert.

Lab Answer Key: Introduction to Building Silverlight Business Applications

Module 1
Lab Answer Key: Introduction to Building Silverlight Business Applications
Contents:
Exercise 1: Creating a Silverlight Application 2 Exercise 2: Configuring Out-of-Browser settings for the Silverlight Application 6

Lab Answer Key: Introduction to Building Silverlight Business Applications

Lab: Building Silverlight Business Applications


Exercise 1: Creating a Silverlight Application
Task 1: Create a new project.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Create a new Silverlight business application named GreetingCardManagement in the D:\Labfiles\Mod01\VB\Starter or D:\Labfiles\Mod01\CS\Starter folder, by using the Silverlight Business Application template. a. b. c. d. e. f. On the File menu, point to New, and then click Project. In the Installed Templates section, expand Visual Basic or Visual C#, and then click Silverlight. In the list of project types, click Silverlight Business Application. In the Name box, type GreetingCardManagement. In the Location box, type D:\Labfiles\Mod01\VB\Starter or D:\Labfiles\Mod01\CS\Starter. Click OK.

A Silverlight project named GreetingCardManagement is created. A website named GreetingCardManagement.Web for hosting the Silverlight application and its services is also created.

Task 2: Test and examine the authentication and User Registration Services of the Silverlight application.
1. Start the application. 2. 3. Press Ctrl+F5 to start the application.

Review the content on the Home page. Review the content on the About page. Click About and review the content on the About page.

4.

Log on by registering a new user with the following information: a. User name: KimA Friendly name: Kim Abercrombie Email: KimA@contoso.com Password: Pa$$w0rd Confirm password: Pa$$w0rd Security question: What is your pets name? Security answer: Buster Click Login.

Lab Answer Key: Introduction to Building Silverlight Business Applications

b. c. d. e. f. g. h. i. j.

In the Login dialog box, click Register now. In the User name box, type KimA In the Friendly name box, type Kim Abercrombie. In the Email box, type KimA@contoso.com. In the Password box, type Pa$$w0rd. In the Confirm password box, type Pa$$w0rd. In the Security question list, click What is your pets name? In the Security answer box, type Buster. Click OK.

You are registered through the built-in authentication services provided by the application, and you are logged into the application. The authentication is handled by the WCF service in the GreetingCardManagement.Web hosting application. Note that the application displays a welcome message that uses the friendly name you specified. 5. Log off from the site. Click logout.

Note that the application welcome message is removed as is the friendly user name. 6. 7. Close Internet Explorer. Examine the Services\AuthenticationService.vb or Services\AuthenticationService.cs code file in the GreetingCardManagement.Web project. In Solution Explorer, under GreetingCardManagement.Web, expand Services, and then doubleclick AuthenticationService.vb or AuthenticationService.cs.

Notice how the AuthenticationService class is annotated with the EnableClientAccess attribute, to enable the Silverlight application to access it. The AuthenticationService class is derived from the generic AuthenticationBase(Of T)or AuthenticationBase<T>class, which in turn implements the generic AuthenticationBase<T> interface. The type of the user entity to authenticate is specified by using T. 8. Examine the user entity, named User, by going to the definition of the class User. a. b. In the AuthenticationService.vb or AuthenticationService.cs code file, right-click User, and then click Go To Definition, or press F12. [Visual C# only] In the Find Symbols Results window, double-click D:\Labfiles\Mod01\CS\Starter\GreetingCardManagement\ GreetingCardManagement.Web\Models\Shared\User.shared.cs.

Notice how the User class in the User.shared.vb or User.shared.cs file is partial because it extends the User type by adding shared properties and methods that are available both to the server application and the client application, Silverlight, in this case. The User class implements the DisplayName property 9. Examine the main partial class User, in the Models folder. In Solution Explorer, under GreetingCardManagement.Web, double-click Models\User.vb or Models\User.cs.

Lab Answer Key: Introduction to Building Silverlight Business Applications

Note how the main partial class, User, is derived from the UserBase class and implements the FriendlyName property. 10. Examine the Services\UserRegistrationService.vb or Services\UserRegistrationService.cs code file in the GreetingCardManagement.Web project. In Solution Explorer, under GreetingCardManagement.Web, expand Services, and then doubleclick UserRegistrationService.vb or UserRegistrationService.cs.

Notice how the UserRegistrationService class is also annotated with the EnableClientAccess attribute. The UserRegistrationService class is derived from the abstract DomainService class, which is the base class for all System.ServiceModel.DomainServices.Server.DomainServices. The UserRegistrationService class uses the ASP.NET Membership and Roles API to provide the user registration services. 11. Examine the content of the App_Data folder in the GreetingCardManagement.Web project. a. b. In Solution Explorer, click GreetingCardManagement.Web, and then click the Show All Files button. Expand App_Data.

Notice how the ASPNETDB.MDF SQL Server Express database is located in the App_Data folder. It was automatically created when you used the user registration services as part of creating or registering a new user.

Task 3: Modify the authentication mode of the Silverlight application.


1. Examine the Web.config file in the GreetingCardManagement.Web project. 2. In Solution Explorer, expand GreetingCardManagement.Web, and then double-click Web.config.

Locate the authentication element.

<authentication mode="Forms"> <forms name=".GreetingCardManagement_ASPXAUTH" /> </authentication >

3.

Edit the authentication element so that it reads.

<authentication mode="Windows"> </authentication >

4.

Save the changes. On the File menu, click Save All.

5.

Start the application. Press Ctrl+F5 to start the application.

Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. Note that you are logged on automatically as 10554A-SEA-DEV\Student because you have configured the website to use Windows authentication. 6. Log off from the site. Click logout.

Lab Answer Key: Introduction to Building Silverlight Business Applications

A custom dialog box displaying an error message appears, because it is not supported to log off from a Windows-authenticated application. 7. Close the custom error dialog box. 8. 9. In the custom error dialog box, click OK.

Close Internet Explorer. Open the App.xaml.vb or App.xaml.cs code file in the GreetingCardManagement project. In Solution Explorer, under GreetingCardManagement, expand App.xaml, and then doubleclick App.xaml.vb or App.xaml.cs.

10. In the App class constructor, comment out the line of code that initializes forms authentication.
[Visual Basic] webContext.Authentication = New FormsAuthentication() [Visual C#] webContext.Authentication = new FormsAuthentication();

11. In the App class constructor, uncomment the line of code that initializes Windows authentication.
[Visual Basic] webContext.Authentication = New WindowsAuthentication() [Visual C#] webContext.Authentication = new WindowsAuthentication();

12. Save the changes. On the File menu, click Save All.

13. Start the application. Press Ctrl+F5 to start the application.

Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. Note that you are logged on automatically as 10554A-SEA-DEV\Student because you have configured the website to use Windows authentication. Note also that the logout link is no longer available because you have configured the Silverlight application to correctly use Windows authentication. 14. Close Internet Explorer.

Lab Answer Key: Introduction to Building Silverlight Business Applications

Exercise 2: Configuring Out-of-Browser settings for the Silverlight Application


Task 1: Control Basic Out-of-Browser Settings.
1. Open the Project Designer for the GreetingCardManagement project. 2. In Solution Explorer, right-click GreetingCardManagement, and then click Properties.

Enable the application to run outside of the browser. Open the Silverlight page, and then ensure that the Enable running application out of the browser check box is selected.

3.

Set the following out-of-browser settings: a. b. c. d. e. f. g. h. i. Window Title: GreetingCard Desktop Management Width: 600 Height: 400 Set window location manually: Selected Top: 100 Left: 100 Shortcut name: GreetingCard Desktop Management Show install menu: selected Click Out-of-Browser Settings. In the Window Title box, type GreetingCard Desktop Management. In the Width box, type 600. In the Height box, type 400. Select the Set window location manually check box. In the Top box, type 100. In the Left box, type 100. In the Shortcut name box, type GreetingCard Desktop Management. Ensure that the Show install menu check box is selected and then click OK.

4.

Start the application. Press Ctrl+F5 to start the application.

Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. The application is still running in the browser. 5. Install the application locally, and add shortcuts to the Start menu and the desktop. a. b. Right-click the background of the application, and then click Install GreetingCard Desktop Management onto this computer. Ensure that Start menu and Desktop check boxes are selected and then click OK.

The application opens in its own window. 6. Close Internet Explorer.

Lab Answer Key: Introduction to Building Silverlight Business Applications

The application continues to run in its own window. 7. 8. Close the GreetingCard Desktop Management localhost window. On the Start menu, click All Programs, and then click GreetingCard Desktop Management. The application opens directly in its own window. 9. Remove the locally installed application, by using the context menu. a. b. In the application, right-click anywhere, and then click Remove this application. Click Yes.

Task 2: Control enhanced Out-of-Browser settings.


When running the GreetingCardManagement application out-of-browser, require elevated trust, and use round corners for the application border. Use the Silverlight page in the Project Designer for this task. a. b. c. d. In the Project Designer, on the Silverlight page, click Out-of-Browser Settings. Select the Require elevated trust when running outside the browser check box. In the Window Style list, click Borderless Round Corners. Click OK.-

Task 3: Provide an Exit button for the Out-of-Browser mode.


1. Open the MainPage.xaml form. 2. 3. In Solution Explorer, under GreetingCardManagement, double-click MainPage.xaml.

In the XAML view, locate the HyperlinkButton control with a name of Link2. Under the Link2 element, add the following markup.

<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="closeLink" Style="{StaticResource LinkStyle}" Content="Exit" Visibility="Collapsed"/>

4.

Create a Click event handler for the closeLink HyperlinkButton control. a. b. Ensure that the insertion point is in the markup for the closeLink HyperlinkButton control. In the Properties window, click Events, and then double-click Click.

[Visual C# only] Visual Studio adds a Click attribute to the markup for the HyperlinkButton control. Visual Studio creates the event handler stub for the event, and the code file appears. 5. In the Click event handler, close the MainWindow form by using the App.Current property. Add the following code to the closeLink_Click event handler.

[Visual Basic] App.Current.MainWindow.Close() [Visual C#]

Lab Answer Key: Introduction to Building Silverlight Business Applications

App.Current.MainWindow.Close();

6.

Save the changes. On the File menu, click Save All.

Task 4: Control the visibility of the Exit button in the Out-of-Browser mode.
1. In the MainPage class, in the constructor append code to check if the application is running out-ofbrowser and with elevated trust, by using the App.Current property. If so, make closeLink HyperlinkButton control visible.

[Visual Basic] If App.Current.IsRunningOutOfBrowser AndAlso App.Current.HasElevatedPermissions Then closeLink.Visibility = Visibility.Visible End If [Visual C#] if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions) { closeLink.Visibility = Visibility.Visible; }

2.

Save the changes. On the File menu, click Save All.

3.

Start the application. Press Ctrl+F5 to start the application.

Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. The application is still running in the browser. Note that the Exit button is not visible. 4. Install the application locally, add shortcuts to the Start menu and the desktop, and accept the security advice. a. In the application, right-click anywhere, and then click Install GreetingCard Desktop Management onto this computer.

Because the application now requests elevated trust when it runs outside the browser, Internet Explorer displays a security warning dialog box. b. c. Click More options and ensure that Start menu and Desktop check boxes are checked. Click Install.

The application opens in its own window, with a rounded borderless style. Note that the Exit button is visible. 5. Close Internet Explorer. The application continues to run in its own window. 6. Close the application.
7.

Click Exit.

Close Visual Studio.

Lab Answer Key: Building Data-Driven Applications

Module 2
Lab Answer Key: Building Data-Driven Applications
Contents:
Exercise 1: Connecting to a Database in a Silverlight Project Exercise 2: Querying and Displaying Data from a Database 2 4

Lab Answer Key: Building Data-Driven Applications

Lab: Consuming Data


Exercise 1: Connecting to a Database in a Silverlight Project
Task 1: Open the GreetingCardManagement Starter solution.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardManagement solution from the D:\Labfiles\Mod02\VB\Starter or D:\Labfiles\Mod02\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod02\VB\Starter\ GreetingCardManagement.sln or D:\Labfiles\Mod02\CS\Starter\ GreetingCardManagement.sln, and then click Open.

3.

Build the solution. On the Build menu, click Build Solution.

4.

Briefly review the solutionit is very similar to the completed solution that you created for Lab 1. The solution consists of a simple Silverlight project and an ASP.NET Web application for hosting the Silverlight application and for providing WCF RIA Services.

Task 2: Add an ADO.NET Entity Data Model to GreetingCardManagement.Web.


1. To the GreetingCardManagement.Web project, add a new ADO.NET Entity Data Model named GreetingCardManagementEntities. a. b. c. In Solution Explorer, right-click GreetingCardManagement.Web, point to Add, and then click New Item. In the Add New Item GreetingCardManagement.Web dialog box, in the Installed Templates section, click Data. Click ADO.NET Entity Data Model, in the Name box, type GreetingCardManagementEntities, and then click Add.

The Entity Data Model Wizard appears. 2. 3. In the Entity Data Model Wizard, ensure that Generate from database is selected, and then click Next. Create a new connection to the 10554A-SEA-DEV\SQLEXPRESS SQL Server instance and the GreetingCard database. a. b. c. d. In the Entity Data Model Wizard, on the Choose Your Data Connection page, click New Connection. In the Choose Data Source dialog box, click Microsoft SQL Server, and then click Continue. In the Connection Properties dialog box, in the Server name box, type 10554A-SEADEV\SQLEXPRESS. In the Select or enter a database name list, click GreetingCard, and then click OK.

Lab Answer Key: Building Data-Driven Applications

4.

Ensure that the connection settings are saved to Web.config as GreetingCardEntities, and then move to the next page. Ensure that the Save entity connection settings in Web.config as check box is selected, GreetingCardEntities is entered in the Save entity connection settings in Web.config as box, and then click Next.

5.

Select the Card (dbo) and Sender (dbo) tables. In the Entity Data Model Wizard, on the Choose Your Database Objects page, in the Which database objects do you want to include in your model? list, expand Tables, and then select the Card (dbo) and Sender (dbo) check boxes.

6.

Ensure that the Model Namespace box reads GreetingCardModel, and then click Finish. The ADO.NET Entity Data Model Designer appears and displays the tables and the relationship between them.

7. 8.

Save the changes. Build the GreetingCardManagement.Web project. On the Build menu, click Build GreetingCardManagement.Web.

Task 3: Add GreetingCardManagementDomainService Domain Service class.


1. To the GreetingCardManagement.Web project, add a Domain Service class named GreetingCardManagementDomainService. a. b. In Solution Explorer, right-click the GreetingCardManagement.Web project, point to Add, and then click New Item. In the Add New Item - GreetingCardManagement.Web dialog box, in the Installed Templates section, click Web, in the templates list, click Domain Service Class, in the Name box, type GreetingCardManagementDomainService, and then click Add.

The Add New Domain Service Class wizard appears. 2. For the GreetingCardManagementDomainService class, have the Add New Domain Service Class wizard generate associated metadata for the Card and Sender entities in the GreetingCardEntities collection, but do not enable editing of these entities. In the Add New Domain Service Class wizard, in the list, select the Card and Sender check boxes, ensure that the corresponding Enable editing check boxes are cleared, and then click OK.

Leave Visual Studio runningyou will work with the data objects you have just created in the next exercise.

Lab Answer Key: Building Data-Driven Applications

Exercise 2: Querying and Displaying Data from a Database


Task 1: Edit the GetSenders query in the Domain Service class.
1. Modify the code in the GetSenders method so that it reads as shown.
[Visual Basic] Return Me.ObjectContext.Senders.Include("Cards") _ .OrderBy(Function(sender) sender.Email)

[Visual C#] return this.ObjectContext.Senders.Include("Cards") .OrderBy(sender => sender.Email);

2.

Save the changes.

Task 2: Edit the SenderMetadata class.


1. In the GreetingCardManagement.Web project, open the GreetingCardManagementDomainService.metadata.vb or GreetingCardManagementDomainService.metadata.cs code file. In Solution Explorer, in the GreetingCardManagement.Web project, double-click GreetingCardManagementDomainService.metadata.vb or GreetingCardManagementDomainService.metadata.cs.

2.

Locate the following property declaration in the SenderMetadata class.

[Visual Basic] Public Property Cards As EntityCollection(Of Card)

[Visual C#] public EntityCollection<Card> Cards { get; set; }

3.

Add the following property attribute immediately above the property you have just located.

[Visual Basic] <Include()> [Visual C#] [Include]

4.

Save the changes.

Task 3: Add data controls for senders data to the Silverlight application.
1. In the Views folder, open Home.xaml. 2. In Solution Explorer, in the GreetingCardManagement project, expand the Views folder, and then double-click Home.xaml.

Delete the Home TextBlock control.

Lab Answer Key: Building Data-Driven Applications

3. 4.

Delete the Home page content TextBlock control. Show the data sources for the GreetingCardManagement project. On the Data menu, click Show Data Sources.

5.

To show the data in master-details view, in the Data Sources window, select the details for the Sender entity. In the Data Sources window, click Sender, click the drop-down arrow for the Sender item, and then click Details.

6. 7.

Drag the Sender item from the Data Sources window to the upper-left corner of Home.xaml in Design view. Delete the User ID grid row. Right-click User ID, point to Grid Row, and then click Delete.

8.

In the Data Sources window, expand the Sender item, drag the Cards sub-item to Home.xaml in Design view and drop it below the Sender data you just added. Note: Ensure that you drag the Cards item that belongs to Sender, and not the top-level Card item.

9.

Open the editor for the columns collection of the DataGrid control for the Cards data. Ensure that the DataGrid control for the Cards data in Home.xaml is selected, and then in the Properties window, click Columns. Click the ellipsis () button for the Columns property.

10. In the Collection Editor: Columns dialog box, remove the CardGuidColumn or cardGuidColumn, CardIDColumn or cardIDColumn, and SenderIDColumn or senderIDColumn DataGridTextColumn objects from the list on the left. a. b. c. In the Collection Editor: Columns dialog box, click DataGridTextColumn (CardGuidColumn) or DataGridTextColumn (cardGuidColumn), and then click the Remove item button. Click DataGridTextColumn (CardIDColumn) or DataGridTextColumn (cardIDColumn), and then click the Remove item button. Click DataGridTextColumn (SenderIDColumn) or DataGridTextColumn (senderIDColumn), and then click the Remove item button.

11. Move up the RecipientEmailColumn or recipientEmailColumn DataGridTextColumn object on the list on the left. Click DataGridTextColumn (RecipientEmailColumn) or DataGridTextColumn (recipientEmailColumn), and then click the Move item up button.

12. Show the Layout section for RecipientEmailColumn or recipientEmailColumn DataGridTextColumn. Ensure that DataGridTextColumn (RecipientEmailColumn) or DataGridTextColumn (recipientEmailColumn) is selected, and then in the Properties section, expand Layout.

13. Set the following property value for RecipientEmailColumn or recipientEmailColumn DataGridTextColumn in the Layout section. Width: 300 Pixel

Lab Answer Key: Building Data-Driven Applications

a. b.

In the Width list, click Pixel. In the box, type 300.

14. Show the Layout section for the CardDataColumn or cardDataColumn DataGridTextColumn. Ensure that DataGridTextColumn (CardDataColumn) or DataGridTextColumn (cardDataColumn) is selected, and then in the Properties section, expand Layout.

15. Set the following property value for CardDataColumn or cardDataColumn DataGridTextColumn in the Layout section. a. b. Width: 295 Pixel In the Width list, click Pixel. In the box, type 295.

16. Close the Collection Editor: Columns dialog box, saving the changes. Click OK.

17. In the Properties window, set the following property values for the DataGrid control. a. b. c. d. Width: 600 HorizontalAlignment: Left VerticalAlignment: Top Ensure that the DataGrid for the Cards data is selected. In the Properties window, expand Layout, click Width, type 600, and then press Enter. Click HorizontalAlignment, and then click Left in the list. Click VerticalAlignment, and then click Top in the list.

Task 4: Add paging controls for senders data to the Silverlight application.
1. In the XAML window, locate the markup that begins with the following code.
<sdk:DataGrid

2. 3.

Insert a blank line immediately above the markup you have just located. Drag a DataPager control from the All Silverlight Controls section of the toolbox to the XAML window, where you just added a blank line. Review the markup for the DataPager control. A DataPager control is added to the XAML window, and to the design surface (between the Sender data and the Card grid). Arrange the data controls so that they resemble the following image.

Lab Answer Key: Building Data-Driven Applications

4. 5. 6.

From the Data Sources window, drag Sender and drop it on the DataPager control. Review the modified markup for the DataPager control and note that a Source element has been added that binds the DataPager to the Sender data. In the Properties window, set the following property values for the DataPager control. a. b. PageSize: 1 DisplayMode: FirstLastPreviousNextNumeric Ensure that the DataPager control is selected and then, in the Properties window, expand Other, click PageSize, type 1, and then press Enter. Expand Common, click DisplayMode, and then click FirstLastPreviousNextNumeric.

7.

Save the changes.

Task 5: Test the data-driven application.


1. Start the application. Press Ctrl+F5.

Internet Explorer appears and navigates to the test page in the GreetingCardManagement.Web site. 2. 3. 4. Review the sender data that is displayed, and then use the DataPager control to navigate through the data. Note how Card Data updates when different Senders are displayed. Close Internet Explorer. Close Visual Studio.

Lab Answer Key: Advanced Data Management

Module 3
Lab Answer Key: Advanced Data Management
Contents:
Exercise 1: Implementing Full Read-Write Scenarios 2

Lab Answer Key: Advanced Data Management

Lab: Manipulating Data


Exercise 1: Implementing Full Read-Write Scenarios
Task 1: Create the GreetingCardConsumer Application.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Create a new Silverlight Business application named GreetingCardConsumer in the D:\Labfiles\Mod03\VB\Starter or D:\Labfiles\Mod03\CS\Starter folder, by using the Silverlight Business Application template. a. b. c. d. e. f. On the File menu, point to New, and then click Project. In the Installed Templates section, expand Visual Basic or Visual C#, and then click Silverlight. In the list of project types, click Silverlight Business Application. In the Name box, type GreetingCardConsumer. In the Location box, type D:\Labfiles\Mod03\VB\Starter or D:\Labfiles\Mod03\CS\Starter. Click OK.

A Silverlight project named GreetingCardConsumer is created. A website named GreetingCardConsumer.Web for hosting the Silverlight application and its services is also created.

Task 2: Configure Silverlight Application Resources.


1. In the GreetingCardConsumer project, open the Resource Designer for the Assets\Resources\ApplicationStrings.resx resource file. In Solution Explorer, in the GreetingCardConsumer project, expand Assets, expand Resources, and then double-click ApplicationStrings.resx.

The Resource Designer opens displaying a three-column grid containing the resource strings in the ApplicationStrings.resx resource file. 2. Replace the value Application Name with Greeting Card Consumer. 3. 4. In the Value column, select the text that reads Application Name, type Greeting Card Consumer, and press Enter.

Save the changes. Close the Resource Designer.

Task 3: Configure User Name to be an Email Address.


1. In the GreetingCardConsumer.Web project, open the Models\RegistrationData model code file. 2. In Solution Explorer, in the GreetingCardConsumer.Web project, expand Models, and then double-click RegistrationData.vb or RegistrationData.cs.

Locate the UserName property declaration. The RegularExpression attribute for the UserName property declaration currently reads:

Lab Answer Key: Advanced Data Management

"^[a-zA-Z0-9_]*$"

3.

Edit the expression above so that it reads:

[Visual Basic] "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[09]{1,3})(\]?)$"

[Visual C#] @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[09]{1,3})(\]?)$"

Replace the following text:


"^[a-zA-Z0-9_]*$"

with the following expression:


[Visual Basic] "^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zAZ]{2,4}|[0-9]{1,3})(\]?)$"

[Visual C#] @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zAZ]{2,4}|[0-9]{1,3})(\]?)$"

You should type this expression all on a single line. It represents a pattern match for a valid email address. Note You can copy the expression from the Email property, which is located just below the UserName property. 4. In the GreetingCardConsumer.Web project, open the Resource Designer for the Resources\ValidationErrorResources.resx resource file. In Solution Explorer, in the GreetingCardConsumer.Web project, folder, expand Resources, and then double-click ValidationErrorResources.resx.

The Resource Designer opens displaying a three-column grid containing the resource strings in the ValidationErrorResources.resx resource file. 5. In the row with a Name column value of ValidationErrorInvalidUserName, replace the content of the Value column with Invalid user name. You must use a valid email address. 6. 7. In the Value column, replace the current content with Invalid user name. You must use a valid email address., and then press Enter.

Save the changes. Close the Resource Designer.

Lab Answer Key: Advanced Data Management

Task 4: Add an existing ADO.NET Entity Data Model to GreetingCardConsumer.Web.


1. Add the existing ADO.NET Entity Data Model, GreetingCardModel, located in the D:\Labfiles\Mod03 folder, to GreetingCardConsumer.Web project. a. b. 2. In Solution Explorer, right-click GreetingCardConsumer.Web, point to Add, and then click Existing Item. In the Add Existing Item GreetingCardConsumer.Web dialog box, in the File name box, type D:\Labfiles\Mod03\GreetingCardModel.edmx, and then click Add.

Build the GreetingCardConsumer.Web project. On the Build menu, click Build GreetingCardConsumer.Web.

Task 5: Update Entity Data Model.


1. In the GreetingCardConsumer.Web project, open the GreetingCardModel entity data model. 2. In Solution Explorer, in the GreetingCardConsumer.Web project, double-click GreetingCardModel.edmx.

Update the data model from database. In the Entity Designer, right-click a blank area and then click Update Model from Database.

The Update Wizard appears. 3. Create a new connection to the 10554A-SEA-DEV\SQLEXPRESS SQL Server instance and the GreetingCard database. a. b. c. d. 4. In the Update Wizard, on the Choose Your Data Connection page, click New Connection. In the Choose Data Source dialog box, click Microsoft SQL Server, and then click Continue. In the Connection Properties dialog box, in the Server name box, type 10554A-SEADEV\SQLEXPRESS. In the Select or enter a database name list, click GreetingCard, and then click OK.

In the Update Wizard, on the Choose Your Data Connection page, click Next. The connection string will now be saved to the Web.config file.

5.

Finish the Update Wizard. In the Update Wizard, on the Choose Your Database Objects page, click Finish.

6. 7.

Save and close the GreetingCardModel entity data model. Build the solution. On the Build menu, click Build Solution.

Task 6: Add a Domain Service Class to GreetingCardConsumer.Web.


1. To the GreetingCardConsumer.Web project, add a Domain Service Class named GreetingCardConsumerDomainService. a. In Solution Explorer, right-click the GreetingCardConsumer.Web project, point to Add, and then click New Item.

Lab Answer Key: Advanced Data Management

b.

In the Add New Item - GreetingCardConsumer.Web dialog box, in the Installed Templates section, click Web, in the templates list, click Domain Service Class, in the Name box, type GreetingCardConsumerDomainService, and then click Add.

The Add New Domain Service Class wizard appears. 2. For the GreetingCardConsumerDomainService class, have the Add New Domain Service Class wizard generate associated metadata for the Card and Sender entities in the GreetingCardEntities collection, and enable editing of these entities. In the Add New Domain Service Class wizard, in the list, select the Card and Sender check boxes, select the corresponding Enable editing check boxes, and then click OK.

Task 7: Edit the GetSenders Query in the Domain Service Class to Restrict Data to the Current User.
1. In the GreetingCardConsumerDomainService code file, modify the code in the GetSenders method so that it reads:

[Visual Basic] Dim userName As String = System.Web.HttpContext.Current.User.Identity.Name Return Me.ObjectContext.Senders.Include("Cards") _ .Where(Function(sndr) sndr.Email = userName)

[Visual C#] string userName = System.Web.HttpContext.Current.User.Identity.Name; return this.ObjectContext.Senders.Include("Cards") .Where(sndr =>sndr.Email == userName);

2.

Save the changes.

Task 8: Edit the SenderMetadata Class.


1. In the GreetingCardConsumer.Web project, open the GreetingCardConsumerDomainService.metadata code file. In Solution Explorer, in the GreetingCardConsumer.Web project, double-click GreetingCardConsumerDomainService.metadata.vb, or GreetingCardConsumerDomainService.metadata.cs.

2. 3.

Locate the Cards property declaration in the SenderMetadata class. Add the Include attribute to the Cards property declaration. In the GreetingCardConsumerDomainService. metadata.vb, or GreetingCardConsumerDomainService. metadata.cs file, in the SenderMetadata class, add the following code attribute immediately above the Cards property declaration.
[Visual Basic] <Include()>

Lab Answer Key: Advanced Data Management

[Visual C#] [Include]

4.

Save the changes.

Task 9: Add Data Controls for Senders Data to the Silverlight Application.
1. To the GreetingCardConsumer project, add a new Silverlight Page named Details, to the Views folder. a. b. In Solution Explorer, in the GreetingCardConsumer project, right-click the Views folder, point to Add, and then click New Item. In the Add New Item - GreetingCardConsumer dialog box, in the Installed Templates section, click Silverlight, in the templates list, click Silverlight Page, in the Name box, type Details, and then click Add.

2.

In the GreetingCardConsumer project, open MainPage.xaml. In Solution Explorer, in the GreetingCardConsumer project, double-click MainPage.xaml.

3. 4.

In MainPage.xaml, in the XAML view, locate the markup that begins <HyperlinkButton x:Name="Link2". Immediately above the located markup, add a new self-closing HyperlinkButton control element named Details. Set the following properties: Property Value Your Details /Details {StaticResource LinkStyle} ContentFrame

Property Name Content NavigateUri Style TargetName

Immediately above the located markup, add the following markup:


<HyperlinkButton x:Name="Details" Content="Your Details" NavigateUri="/Details" Style="{StaticResource LinkStyle}" TargetName="ContentFrame"/>

The NavigateUri property specifies that when a user clicks the HyperlinkButton control, it should navigate to the Details.xaml page, by using a relative uri (/Details). The TargetFrame property specifies that the content available at the NavigateUri should be displayed in the ContentFrame navigation frame. This is part of the navigation automatically provided when creating a Silverlight Business Application. 5. Immediately below the DetailsHyperlinkButton control, add a new self-closing Rectangle control element named DetailsDivider. Set the following property: Property Value {StaticResource DividerStyle}

Property Name Style

Lab Answer Key: Advanced Data Management

Immediately below the DetailsHyperlinkButton control, add the following markup:


<Rectangle x:Name="DetailsDivider" Style="{StaticResource DividerStyle}"/>

6. 7.

Switch back to Details.xaml. Build the solution. On the Build menu, click Build Solution.

8.

In Details.xaml, in the XAML view, select all the markup, and then type in the following markup or copy from the D:\Labfiles\Mod03\VB\DetailsMarkup.txt or D:\Labfiles\Mod03\CS\DetailsMarkup.txt file, and paste it in:

[Visual Basic] <navigation:Page x:Class="GreetingCardConsumer.Details" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Details Page" xmlns:riaControls="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:GreetingCardConsumer" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <sdk:Page.Resources> <CollectionViewSource x:Key="SenderCardsViewSource" Source="{Binding Path=Data.Cards, ElementName=SenderDomainDataSource}" /> </sdk:Page.Resources> <Grid x:Name="LayoutRoot"> <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Sender, CreateList=true}" Height="0" Name="SenderDomainDataSource" QueryName="GetSendersQuery" Width="0"> <riaControls:DomainDataSource.DomainContext> <my:GreetingCardConsumerDomainContext /> </riaControls:DomainDataSource.DomainContext> </riaControls:DomainDataSource> <Grid DataContext="{Binding ElementName=SenderDomainDataSource, Path=Data}" HorizontalAlignment="Left" Margin="12,12,0,0" Name="Grid1" VerticalAlignment="Top" Height="66" Width="220"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <sdk:Label Content="Display Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="DisplayNameTextBox" Text="{Binding Path=DisplayName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> <sdk:Label Content="Email:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="EmailTextBox" Text="{Binding Path=Email, Mode=TwoWay,

Lab Answer Key: Advanced Data Management

NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> </Grid> <sdk:DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource SenderCardsViewSource}}" Margin="12,84,0,0" Name="CardsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="600"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="RecipientEmailColumn" Binding="{Binding Path=RecipientEmail}" Header="Recipient Email" Width="300" /> <sdk:DataGridTextColumn x:Name="CardDataColumn" Binding="{Binding Path=CardData}" Header="Card Data" Width="295" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </Grid> </navigation:Page>

[Visual C#] <navigation:Page x:Class="GreetingCardConsumer.Details" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Details Page" xmlns:riaControls="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices" xmlns:my="clr-namespace:GreetingCardConsumer.Web" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"> <sdk:Page.Resources> <CollectionViewSource x:Key="SenderCardsViewSource" Source="{Binding Path=Data.Cards, ElementName=SenderDomainDataSource}" /> </sdk:Page.Resources> <Grid x:Name="LayoutRoot"> <riaControls:DomainDataSource AutoLoad="True" d:DesignData="{d:DesignInstance my:Sender, CreateList=true}" Height="0" Name="SenderDomainDataSource" QueryName="GetSendersQuery" Width="0"> <riaControls:DomainDataSource.DomainContext> <my:GreetingCardConsumerDomainContext /> </riaControls:DomainDataSource.DomainContext> </riaControls:DomainDataSource> <Grid DataContext="{Binding ElementName=SenderDomainDataSource, Path=Data}" HorizontalAlignment="Left" Margin="12,12,0,0" Name="Grid1" VerticalAlignment="Top" Height="66" Width="220"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <sdk:Label Content="Display Name:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" /> <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="DisplayNameTextBox" Text="{Binding Path=DisplayName, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> <sdk:Label Content="Email:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />

Lab Answer Key: Advanced Data Management

<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="EmailTextBox" Text="{Binding Path=Email, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true, TargetNullValue=''}" VerticalAlignment="Center" Width="120" /> </Grid> <sdk:DataGrid AutoGenerateColumns="False" Height="200" HorizontalAlignment="Left" ItemsSource="{Binding Source={StaticResource SenderCardsViewSource}}" Margin="12,84,0,0" Name="CardsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="600"> <sdk:DataGrid.Columns> <sdk:DataGridTextColumn x:Name="RecipientEmailColumn" Binding="{Binding Path=RecipientEmail}" Header="Recipient Email" Width="300" /> <sdk:DataGridTextColumn x:Name="CardDataColumn" Binding="{Binding Path=CardData}" Header="Card Data" Width="295" /> </sdk:DataGrid.Columns> </sdk:DataGrid> </Grid> </navigation:Page>

9.

In the GreetingCardConsumer project, add a reference to the System.Windows.Controls.Data and System.Windows.Controls.DomainServices assemblies. a. b. In the Solution Explorer window, right-click GreetingCardConsumer, and then click Add Reference. In the Add Reference dialog box, in the list, select System.Windows.Controls.DomainServices and System.Windows.Controls.Data, and then click OK.

10. Build the solution. On the Build menu, click Build Solution.

Task 10: Develop Code to Add Newly Registered Users to the GreetingCard Database.
1. In the GreetingCardConsumer project, open Views\Login\RegistrationForm.xaml in Code view. 2. 3. In Solution Explorer, in the GreetingCardConsumer project, expand Views, expand Login, rightclick RegistrationForm.xaml, and then click View Code.

In the RegistrationForm class, locate the RegisterButton_Click event handler. Append code to the If/if block in the event handler to create and instantiate an instance of the GreetingCardConsumerDomainContext class, create and instantiate an instance of the Sender class. Set the Email property of the sender instance to the value of the local registrationData.UserName, set the DisplayName property of the sender instance to the value of the local registrationData.FriendlyName and add the sender instance to the Senders collection property of the GreetingCardConsumerDomainContext instance. Finally, use the GreetingCardConsumerDomainContext instance, to submit the changes. Append the following code to the existing code in the event handler, in the If/if block:
[Visual Basic] Dim context As New GreetingCardConsumerDomainContext() Dim sndr As New Sender() sndr.Email = Me.registrationData.UserName sndr.DisplayName = Me.registrationData.FriendlyName context.Senders.Add(sndr) context.SubmitChanges()

10

Lab Answer Key: Advanced Data Management

[Visual C#] GreetingCardConsumerDomainContext context = new GreetingCardConsumerDomainContext(); Sender sndr = new Sender(); sndr.Email = this.registrationData.UserName; sndr.DisplayName = this.registrationData.FriendlyName; context.Senders.Add(sndr); context.SubmitChanges();

4.

Save the changes.

Task 11: Implement Edit-and-Save Operations for Database Data.


1. In the GreetingCardConsumer project, add a new folder named Images to the Assets folder. 2. In Solution Explorer, in the GreetingCardConsumer project, right-click the Assets folder, point to Add, and then click New Folder. Type Images and then press Enter.

Add the existing D:\Labfiles\Mod03\HeadPhoto.png image file to the Images folder. a. b. In Solution Explorer, in the GreetingCardConsumer project, right-click the Images folder, point to Add, and then click Existing Item. In the Add Existing Item- GreetingCardConsumer dialog box, in the File name box, type D:\Labfiles\Mod03\HeadPhoto.png, and then click Add.

3. 4.

Switch back to Details.xaml. Disable the two TextBox controls. a. b. Select the TextBox next to the DisplayNameLabel control, press and hold Ctrl, and then select the TextBox next to the EmailLabel control. In the Properties window, clear the IsEnabled check box.

5.

In the XAML view of Details.xaml, locate the markup that begins as follows:

<sdk:DataGrid

6. 7.

Insert an empty line above the markup that you located. Add the following markup to the space you have just created. You can type in the markup manually, or you can copy from the D:\Labfiles\Mod03\EditDetailsMarkup.txt file, and paste it in.

<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <Border BorderBrush="Silver" BorderThickness="2" Height="70" Margin="10" Name="editDetails" Width="50" CornerRadius="10" VerticalAlignment="Top" Cursor="Hand"> <StackPanel Orientation="Vertical"> <Border CornerRadius="10,10,0,0" Height="50"> <Border.Background> <ImageBrush ImageSource="/GreetingCardConsumer;component/Assets/Images/HeadPhoto.png"/> </Border.Background> </Border> <ContentControl Height="20" Content="Edit" HorizontalAlignment="Center" Background="Silver"/> </StackPanel> </Border> <StackPanel Orientation="Vertical" VerticalAlignment="Top"

Lab Answer Key: Advanced Data Management

11

Margin="10" HorizontalAlignment="Left" x:Name="editControls" Visibility="Collapsed"> <Button x:Name="saveChanges" Content="Save" Width="50" Margin="5" Cursor="Hand"/> <Button x:Name="cancelChanges" Content="Cancel" Width="50" Margin="5" Cursor="Hand"/> </StackPanel> </StackPanel>

The markup adds controls for editing the details, wrapped a StackPanel control, which contains controls for displaying the image you added previously, and controls for saving or cancelling the changes. 8. 9. Save the changes. Add an event handler for the MouseLeftButtonDown event of the editDetailsBorder control. a. b. Place the insertion point in the opening tag of the Border element named editDetails. In the Properties window, click Events, and then double-click MouseLeftButtonDown.

Visual Studio creates an event handler stub for you. 10. Add code to the event handler to check whether the name of the current user, WebContext.Current.User.Name, is null or empty. If so, create and display a new error window using the ErrorWindow.CreateNew method, displaying the message, You must log in to edit your data, but never show the stack trace. In addition, exit the method, if the name of the current user is null or empty. Otherwise, enable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Collapsed, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Visible. Add the following code to event handler:
[Visual Basic] If String.IsNullOrEmpty(WebContext.Current.User.Name) Then ErrorWindow.CreateNew("You must log in to edit your data", StackTracePolicy.Never) Return End If EmailTextBox.IsEnabled = True DisplayNameTextBox.IsEnabled = True editDetails.Visibility = System.Windows.Visibility.Collapsed editControls.Visibility = System.Windows.Visibility.Visible

[Visual C#] if (string.IsNullOrEmpty(WebContext.Current.User.Name)) { ErrorWindow.CreateNew("You must log in to edit your data", StackTracePolicy.Never); } return;

emailTextBox.IsEnabled = true; displayNameTextBox.IsEnabled = true; editDetails.Visibility = System.Windows.Visibility.Collapsed;

12

Lab Answer Key: Advanced Data Management

editControls.Visibility = System.Windows.Visibility.Visible;

11. Switch back to the XAML view of Details.xaml. 12. Add an event handler for the Click event of the saveChangesButton control. a. b. Place the insertion point in the opening tag of the Button element named saveChanges. In the Properties window, click Events, and then double-click Click.

Visual Studio creates an event handler stub for you. 13. Add code to the event handler to use the SenderDomainDataSource or senderDomainDataSource object to submit the changes. Wrap the code in a Try...Catch...Finally or try...catch...finally construct, with just one general Catch or catch (Exception). If an exception is thrown, use the SenderDomainDataSource or senderDomainDataSource object to reject the changes, create and display a new error window, using the ErrorWindow.CreateNew method, displaying the message, The following problem occurred when attempting to save your changes, but never show the stack trace. To the error message, append content of the Message property of the caught exception. In the Finally or finally part, disable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Visible, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Collapsed. Add the following code to the event handler:
[Visual Basic] Try SenderDomainDataSource.SubmitChanges() Catch ex As Exception SenderDomainDataSource.RejectChanges() ErrorWindow.CreateNew("The following problem occurred " _ & "when attempting to save your changes:" _ & ex.Message, StackTracePolicy.Never) Finally EmailTextBox.IsEnabled = False DisplayNameTextBox.IsEnabled = False editDetails.Visibility = System.Windows.Visibility.Visible editControls.Visibility = System.Windows.Visibility.Collapsed End Try

[Visual C#] try { senderDomainDataSource.SubmitChanges(); } catch (Exception ex) { senderDomainDataSource.RejectChanges(); ErrorWindow.CreateNew("The following problem occurred when attempting to save your changes:" + ex.Message, StackTracePolicy.Never); } finally { emailTextBox.IsEnabled = false; displayNameTextBox.IsEnabled = false; editDetails.Visibility = System.Windows.Visibility.Visible; editControls.Visibility = System.Windows.Visibility.Collapsed;

Lab Answer Key: Advanced Data Management

13

14. Switch back to the XAML view of Details.xaml. 15. Add an event handler for the Click event of the cancelChangesButton control. a. b. Place the insertion point in the opening tag of the Button element named cancelChanges. In the Properties window, click Events, and then double-click Click.

Visual Studio creates an event handler stub for you. 16. Add code to the event handler to disable the EmailTextBox or emailTextBox, and DisplayNameTextBox or displayNameTextBox controls, set the Visibility property of the editDetails control to a value of System.Windows.Visibility.Visible, and set the Visibility property of the editControls control to a value of System.Windows.Visibility.Collapsed. Finally, use the SenderDomainDataSource or senderDomainDataSource object to reject the changes. Add the following code to the event handler:
[Visual Basic] EmailTextBox.IsEnabled = False DisplayNameTextBox.IsEnabled = False editDetails.Visibility = System.Windows.Visibility.Visible editControls.Visibility = System.Windows.Visibility.Collapsed SenderDomainDataSource.RejectChanges()

[Visual C#] emailTextBox.IsEnabled = false; displayNameTextBox.IsEnabled = false; editDetails.Visibility = System.Windows.Visibility.Visible; editControls.Visibility = System.Windows.Visibility.Collapsed; senderDomainDataSource.RejectChanges();

17. Save the changes.

Task 12: Test Data Operations in the Silverlight Application.


1. Open Microsoft SQL Server Management Studio as administrator. a. b. 2. On the Start menu, click All Programs, click Microsoft SQL Server 2008 R2, right-click SQL Server Management Studio, and then click Run as administrator. In the User Account Control dialog box, in the text box, type Pa$$w0rd, and then click Yes.

Connect to the 10554A-SEA-DEV\SQLEXPRESS SQL Server Instance. In the Connect to Server dialog box, click Connect.

3.

Locate the GreetingCard database. In Object Explorer, expand Databases.

4.

Show the tables for the GreetingCard database. In Object Explorer, under GreetingCard, expand Tables.

5.

View the first 1000 rows of the Sender table. Right-click dbo.Sender, and then click Select Top 1000 Rows.

14

Lab Answer Key: Advanced Data Management

Notice the 10 rows of users or senders in the Results window. Leave Microsoft SQL Server Management Studio running 6. 7. Switch back to Visual Studio. Start the application. 8. 9. Press Ctrl+F5.

Click Your Details. Click Edit. Note box. The error message, for which you wrote the validation for, is displayed in a dialog

10. Close the dialog box. 11. Go to Home page. Click Home.

12. Log on by registering as a new user with the following information. a. b. c. d. e. f. g. h. i. j. User name: GregG Friendly name: Greg Guzik Email: GregG@contoso.com Password: Pa$$w0rd Confirm password: Pa$$w0rd Security question: What is your pets name? Security answer: Lily Click Login. In the Login dialog box, click Register now. In the User name box, type GregG. In the Friendly name box, type Greg Guzik. In the Email box, type GregG@contoso.com. In the Password box, type Pa$$w0rd. In the Confirm password box, type Pa$$w0rd. In the Security question list, click What is your pets name? In the Security answer box, type Lily. Click OK.

Note that you cannot register because the user name must be a valid email address. You set this validation earlier.

Lab Answer Key: Advanced Data Management

15

13. Change the user name to GregG@contoso.com, and register In the User name text box, type GregG@contoso.com, and then click OK.

You are registered through the built-in authentication services provided by the application, and you are logged on to the application. Leave Internet Explorer running. 14. Switch back to Microsoft SQL Server Management Studio. 15. On the Query menu, click Execute. The data refreshes and shows a new sender for the user you just registered in the Silverlight application. 16. Switch back to Internet Explorer. 17. Go to Home page Click Home.

18. Edit the details for the current user. a. b. Click Your Details. Click Edit.

19. Change the display name to Gregory, and save the change. a. b. In the Display Name box, type Gregory. Click Save.

20. Switch back to Microsoft SQL Server Management Studio. 21. Rerun the top 1000 query. On the Query menu, click Execute.

The data refreshes and shows the updated DisplayName for Gregory. 22. Close all applications. You have now completed this lab.

Lab Answer Key: Implementing User Controls and Navigation

Module 4
Lab Answer Key: Implementing User Controls and Navigation
Contents:
Exercise 1: Adding a Navigation User Control Exercise 2: Updating the Number of Cards Periodically 2 8

Lab Answer Key: Implementing User Controls and Navigation

Lab: Implementing User Controls and Navigation


Exercise 1: Adding a Navigation User Control
Task 1: Open the GreetingCardManagement starter solution.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardManagement solution from the D:\Labfiles\Mod04\VB\Starter or D:\Labfiles\Mod04\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod04\VB\Starter\ GreetingCardManagement.sln or D:\Labfiles\Mod04\CS\Starter\ GreetingCardManagement.sln, and then click Open.

The solution consists of a simple Silverlight project and an ASP.NET web application for hosting the Silverlight application and for providing Windows Communication Foundation (WCF) Rich Internet Applications (RIA) services. This is the solution code from Module 2.

Task 2: Create a new user control.


1. Add a new user control named NavigationSidebar to the GreetingCardManagement project, in the Views folder. a. b. 2. In Solution Explorer, in the GreetingCardManagement project, right-click Views, point to Add, and then click New Item. In the Add New Item GreetingCardManagement dialog box, in the templates list, click Silverlight User Control, in the Name box, type NavigationSidebar, and then click Add.

Remove the standard white background from the Grid control. In the NavigationSidebar.xaml window, in the XAML view, remove the Background attribute and value Background="White".

3.

Save the changes.

Task 3: Move navigation controls.


1. In the GreetingCardManagement project, open the MainPage XAML file. 2. In Solution Explorer, in the GreetingCardManagement project, double-click MainPage.xaml.

Locate the Border control named LinksBorder. In the MainPage.xaml window, in the XAML view, locate the Border control with the following opening tag.
<Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}">

3.

Select and cut the LinksBorder control, including the content.

Lab Answer Key: Implementing User Controls and Navigation

In the MainPage.xaml window, in the XAML view, select the following markup, and then press Ctrl+X.
<Border x:Name="LinksBorder" Style="{StaticResource LinksBorderStyle}"> <StackPanel x:Name="LinksStackPanel" Style="{StaticResource LinksStackPanelStyle}"> <HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}" NavigateUri="/Home" TargetName="ContentFrame" Content="{Binding Path=ApplicationStrings.HomePageTitle, Source={StaticResource ResourceWrapper}}"/> <Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}" NavigateUri="/About" TargetName="ContentFrame" Content="{Binding Path=ApplicationStrings.AboutPageTitle, Source={StaticResource ResourceWrapper}}"/> <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="closeLink" Style="{StaticResource LinkStyle}" Content="Exit" Visibility="Collapsed"/> </StackPanel> </Border>

4.

Format the MainPage.xaml document. Press Ctrl+K, D.

5.

Switch to the NavigationSidebar.xaml file. In the GreetingCardManagement Microsoft Visual Studio window, click NavigationSidebar.xaml.

6.

Locate the Grid control named LayoutRoot. In the NavigationSidebar.xaml window, in the XAML view, locate the Grid control with the following opening tag.
<Grid x:Name="LayoutRoot">

7.

Insert the cut markup between the opening and closing tags of the Grid control. In the NavigationSidebar.xaml window, place the cursor between the following markup,
<Grid x:Name="LayoutRoot">

and the following markup, and then press Ctrl+V.


</Grid>

8.

Format the NavigationSidebar.xaml document. Press Ctrl+K, D.

9.

Save the changes.

10. Open the NavigationSidebar.xaml code-behind file.

Lab Answer Key: Implementing User Controls and Navigation

In Solution Explorer, in the GreetingCardManagement project, in the Views folder, right-click NavigationSidebar.xaml, and then click View Code.

11. Open the MainPage.xaml code-behind file. In Solution Explorer, in the GreetingCardManagement project, right-click MainPage.xaml, and then click View Code.

12. Locate the closeLink_Click event handler. In the MainPage.xaml.vb or MainPage.xaml.cs window, locate the following code.
[Visual Basic] Private Sub closeLink_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles closeLink.Click

[Visual C#] private void closeLink_Click(object sender, RoutedEventArgs e)

The closeLink_Click event handler must be moved to the same file as the closeLink control. 13. Select and cut the closeLink_Click event handler definition and code. In the MainPage.xaml.vb or MainPage.xaml.cs window, select the following code, and then press Ctrl+X.
[Visual Basic] Private Sub closeLink_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles closeLink.Click App.Current.MainWindow.Close() End Sub

[Visual C#] private void closeLink_Click(object sender, RoutedEventArgs e) { App.Current.MainWindow.Close(); }

14. Switch to the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs file. In the GreetingCardManagement Microsoft Visual Studio window, click NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs.

15. Append the cut code at the end of NavigationSidebar class. In the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs window, paste the cut code at the end of the NavigationSidebar class.

16. Switch to the MainPage.xaml.vb or MainPage.xaml.cs file. In the GreetingCardManagement Microsoft Visual Studio window, click MainPage.xaml.vb or MainPage.xaml.cs.

17. Locate the constructor. In the MainPage.xaml.vb or MainPage.xaml.cs window, locate the following code.

Lab Answer Key: Implementing User Controls and Navigation

[Visual Basic] Public Sub New()

[Visual C#] public MainPage()

18. Select and cut the constructor code that accesses the closeLink control. In the MainPage.xaml.vb or MainPage.xaml.cs window, select the following code, and then press Ctrl+X.
[Visual Basic] If App.Current.IsRunningOutOfBrowser And App.Current.HasElevatedPermissions Then closeLink.Visibility = Visibility.Visible End If

[Visual C#] if (App.Current.IsRunningOutOfBrowser && App.Current.HasElevatedPermissions) { closeLink.Visibility = Visibility.Visible; }

The code that accesses the closeLink control must be moved to the same file as the closeLink control. 19. Switch to the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs file. In the GreetingCardManagement Microsoft Visual Studio window, click NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs.

20. Locate the constructor. In the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs window, locate the following code.
[Visual Basic] Public Sub New

[Visual C#] public NavigationSidebar()

21. Append the cut code. In the NavigationSidebar.xaml.vb or NavigationSidebar.xaml.cs window, paste the cut code at the end of the constructor.

22. Save the changes.

Task 4: Insert NavigationSidebar user control in MainPage.


1. Switch to the MainPage.xaml file.

Lab Answer Key: Implementing User Controls and Navigation

2.

In the GreetingCardManagement Microsoft Visual Studio window, click MainPage.xaml.

Add the XML namespace named local for the GreetingCardManagement or GreetingCardManagement.Views CLR namespace to the GreetingCardManagement.MainPage UserControl.

[Visual Basic] xmlns:local="clr-namespace:GreetingCardManagement"

[Visual C#] xmlns:local="clr-namespace:GreetingCardManagement.Views"

In the MainPage.xaml window, in the opening UserControl tag, after the xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" namespace, add the following markup.
[Visual Basic] xmlns:local="clr-namespace:GreetingCardManagement"

[Visual C#] xmlns:local="clr-namespace:GreetingCardManagement.Views"

3.

Append the NavigationSidebar user control with default values to the NavigationGrid Grid control. Name the control NavigationSidebar.

<local:NavigationSidebar x:Name="NavigationSidebar" />

In the MainPage.xaml window, between the opening and closing tag of the NavigationGrid Grid control tag, append the following markup.
<local:NavigationSidebar x:Name="NavigationSidebar" />

4.

Switch to the MainPage.xaml.vb or MainPage.xaml.cs file. In the GreetingCardManagement Microsoft Visual Studio window, click MainPage.xaml.vb or MainPage.xaml.cs.

5.

If you are developing in Visual C#, bring the GreetingCardManagement.Views namespace into scope. In the MainPage.xaml.cs window, add the following code at the top of file, within the namespace block.
using GreetingCardManagement.Views;

6.

Locate the ContentFrame_Navigated event handler. In the MainPage.xaml.vb or MainPage.xaml.cs window, locate the following code.
[Visual Basic] Private Sub ContentFrame_Navigated(ByVal sender As Object, ByVal e As NavigationEventArgs)

Lab Answer Key: Implementing User Controls and Navigation

[Visual C#] private void ContentFrame_Navigated(object sender, NavigationEventArgs e)

7.

In the ContentFrame_Navigated event handler, add code to create a new StackPanel control named linkStackPanel, and assign the value of the LinksStackPanel control in the NavigationSidebar user control. You can use the FindName method of the UIElement class. In the MainPage.xaml.vb or MainPage.xaml.cs window, at the top of the ContentFrame_Navigated event handler, add the following code.
[Visual Basic] Dim linkStackPanel As StackPanel = (Me.FindName("NavigationSidebar")).FindName("LinksStackPanel")

[Visual C#] StackPanel linkStackPanel = ((StackPanel) ((NavigationSidebar) this.FindName("NavigationSidebar")).FindName("LinksStackPanel"));

8.

In the ContentFrame_Navigated event handler, in the For Each/foreach loop, change the name of the control being iterated from LinksStackPanel to linkStackPanel. In the MainPage.xaml.vb or MainPage.xaml.cs window, at the top of the ContentFrame_Navigated event handler, modify the For Each/foreach loop declaration to resemble the following code.
[Visual Basic] For Each child As UIElement In linkStackPanel.Children

[Visual C#] foreach (UIElement child in linkStackPanel.Children)

The code in the top-level user control correctly changes the visual state of the HyperlinkButton controls, now contained in the child NavigationSidebar user control. 9. Build the solution. On the Build menu, click Build Solution.

10. Run the application. Press Ctrl+F5.

11. Check that the navigation controls are still displayed in the upper-right corner. 12. Close Internet Explorer.

Lab Answer Key: Implementing User Controls and Navigation

Exercise 2: Updating the Number of Cards Periodically


Task 1: Create a domain service method.
1. In the GreetingCardManagement.Web project, open the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs code file. In Solution Explorer, in the GreetingCardManagement.Web project, double-click GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs.

2.

Add a public method named GetCardCount that returns an Integer/int. Add the method after the existing GetCards method. In the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs window, add the following code after the GetCards method.
[Visual Basic] ''' <summary> ''' Returns the no of cards ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Function GetCardCount() As Integer End Function

[Visual C#] /// <summary> /// Returns the no of cards /// </summary> /// <returns></returns> public int GetCardCount() { }

3.

To the public GetCardCount method, add code to return the number of rows in the Cards entity by using a LINQ query selecting on the CardID column. In the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs window, add the following code to the GetCardCount method.
[Visual Basic] Dim count = (From cards In Me.ObjectContext.Cards Select cards.CardID).Count() Return count

[Visual C#] var count = (from cards in this.ObjectContext.Cards select cards.CardID).Count(); return count;

Lab Answer Key: Implementing User Controls and Navigation

4.

Save and close the GreetingCardManagementDomainService.vb or GreetingCardManagementDomainService.cs file.

Task 2: Add a display control to the Home page.


1. In the GreetingCardManagement project, in the Views folder, open the Home.xaml file. 2. In Solution Explorer, in the GreetingCardManagement project, expand Views, and then doubleclick Home.xaml.

Add a TextBlock control named NoCardsTextBlock below the DataGrid control. It should display the text Number of cards in database:, as shown in the following image.

In the Home.xaml window, in the XAML view, below the </sdk:DataGrid> closing tag, add the following markup.
<TextBlock x:Name="NoCardsTextBlock" Text="Number of cards in database: " />

3.

In the GreetingCardManagement project, in the Views folder, open the Home.xaml code file. In Solution Explorer, in the GreetingCardManagement project, right-click Home.xaml, and then click View Code.

4.

Locate the constructor. In the Home.xaml.vb or Home.xaml.cs window, locate the following code.
[Visual Basic] Public Sub New()

[Visual C#] public Home()

5.

Append code to the constructor to create a new instance of the System.Windows.Threading.DispatcherTimer class. a. Bring the System.Windows.Threading namespace into scope by adding the following code at the top of the code file.
[Visual Basic]

10

Lab Answer Key: Implementing User Controls and Navigation

Imports System.Windows.Threading

[Visual C#] using System.Windows.Threading;

b.

In the Home.xaml.vb or Home.xaml.cs window, in the constructor, append the following code.
[Visual Basic] ' Used to retrieve the no of cards in the database ' at a specified interval Dim countTimer As New DispatcherTimer()

[Visual C#] // Used to retrieve the no of cards in the database // at a specified interval DispatcherTimer countTimer = new DispatcherTimer();

The timer will be used to regularly update the TextBlock control. 6. Append code to the constructor to create an anonymous event handler for the Tick event of the countTimer DispatcherTimer object. The event handler, which does not return a value, should create an instance of the GreetingCardManagementDomainContext domain context class. Name the instance gcmContext. Call the GetCardCount method on gcmContext, passing a callback method named OnGetCardCountCompleted and a null value as the only parameters. Finally, destroy the gcmContext object. a. [Visual C# only] Bring the GreetingCardManagement.Web namespace into scope by adding the following code at the top of the code file.
[Visual C#] using GreetingCardManagement.Web;

b.

In the Home.xaml.vb or Home.xaml.cs window, in the constructor, append the following code.
[Visual Basic] ' Create event handler for the Tick event AddHandler countTimer.Tick, Sub(s As Object, e As EventArgs) ' Create instance of domain service Dim gcmContext As New GreetingCardManagementDomainContext() ' Start asynchronous get card count method, passing in callback method gcmContext.GetCardCount(AddressOf Me.OnGetCardCountCompleted, Nothing) ' Destroy domain service instance gcmContext = Nothing End Sub

[Visual C#] // Create event handler for the Tick event countTimer.Tick += delegate(object s, EventArgs e) { // Create instance of domain service GreetingCardManagementDomainContext gcmContext = new GreetingCardManagementDomainContext();

Lab Answer Key: Implementing User Controls and Navigation

11

};

// Start asynchronous get card count method, passing in callback method gcmContext.GetCardCount(this.OnGetCardCountCompleted, null); // Destroy domain service instance gcmContext = null;

7.

Append code to the constructor to set the timer interval to 15 seconds and start the timer. a. [Visual C# only] Bring the System namespace into scope by adding the following code at the top of the code file.
[Visual C#] using System;

b.

In the Home.xaml.vb or Home.xaml.cs window, in the constructor, append the following code.
[Visual Basic] ' Set the timer interval to 15 seconds ' and start the timer countTimer.Interval = New TimeSpan(0, 0, 15) countTimer.Start()

[Visual C#] // Set the timer interval to 15 seconds // and start the timer countTimer.Interval = new TimeSpan(0, 0, 15); countTimer.Start();

8.

Append a new callback method named OnGetCardCountCompleted to the Home class. The method should accept a single parameter named op, of the generic type System.ServiceModel.DomainServices.Client.InvokeOperation, restricted to integers only. a. Bring the System.ServiceModel.DomainServices.Client namespace into scope by adding the following code at the top of the code file.
[Visual Basic] Imports System.ServiceModel.DomainServices.Client

[Visual C#] using System.ServiceModel.DomainServices.Client;

b.

In the Home.xaml.vb or Home.xaml.cs window, append the following code to the Home class.
[Visual Basic] Private Sub OnGetCardCountCompleted(ByVal op As InvokeOperation(Of Integer)) End Sub

[Visual C#] private void OnGetCardCountCompleted(InvokeOperation<int> op) { }

12

Lab Answer Key: Implementing User Controls and Navigation

9.

Add code to the callback method OnGetCardCountCompleted to call the SetCardCount method, which accepts an integer parameter. The method should check if the currently executing code is running on the UI thread by using the Dispatcher object, and subsequently call the SetCardCount method directly, or by using a new delegate named CardCountDelegate, which accepts a single integer parameter. a. Add a new private delegate named CardCountDelegate to the Home class. It must accept a single integer parameter named cardCount.
[Visual Basic] Private Delegate Sub CardCountDelegate(ByVal cardCount As Integer)

[Visual C#] private delegate void CardCountDelegate(int cardCount);

b.

In the Home.xaml.vb or Home.xaml.cs window, in the OnGetCardCountCompleted method, add the following code.
[Visual Basic] ' Get dispatcher Dim disp As Dispatcher = Me.Dispatcher ' Check if we're on the UI-thread If (disp.CheckAccess()) Then ' Call directly SetCardCount(op.Value) Else ' Call by using delegate disp.BeginInvoke( New CardCountDelegate(AddressOf SetCardCount), op.Value) End If

[Visual C#] // Get dispatcher Dispatcher disp = this.Dispatcher; // Check if we're on the UI-thread if (disp.CheckAccess()) // Call directly SetCardCount(op.Value); else // Call by using delegate disp.BeginInvoke( new CardCountDelegate(SetCardCount), op.Value);

Because the DispatcherTimer class is used, it is not necessary to check if the code is running on the current thread. However, you will now be able to use a different approach, such as using the System.Threading.Timer class instead by making simple adjustments to your code. The System.Threading.Timer class runs on a non-UI thread. 10. Append a new method named SetCardCount to the Home class. The method should accept a single integer parameter named cardCount. The Text property of the NoCardsTextBlock control should be updated with the text, Number of cards in database:, followed by the number of cards in the database, passed in the cardCount parameter.

Lab Answer Key: Implementing User Controls and Navigation

13

In the Home.xaml.vb or Home.xaml.cs window, append the following code to the Home class.
[Visual Basic] ''' <summary> ''' Displays the current number of cards in the database ''' </summary> ''' <param name="cardCount"></param> ''' <remarks></remarks> Private Sub SetCardCount(ByVal cardCount As Integer) ' Display the current number of cards in the database NoCardsTextBlock.Text = String.Format("Number of cards in database: {0}", cardCount.ToString()) End Sub

[Visual C#] /// <summary> /// Displays the current number of cards in the database /// </summary> /// <param name="cardCount"></param> private void SetCardCount(int cardCount) { // Display the current number of cards in the database NoCardsTextBlock.Text = string.Format("Number of cards in database: {0}", cardCount.ToString()); }

11. Build the solution. On the Build menu, click Build Solution.

12. Run the application. Press Ctrl+F5.

13. Check that the number of cards, 501, is displayed after 15 seconds. 14. Close Internet Explorer. 15. Close all applications. You have now completed this lab.

Lab Answer Key: Creating Advanced User Interfaces

Module 5
Lab Answer Key: Creating Advanced User Interfaces
Contents:
Exercise 1: Creating ItemsControl Objects Exercise 2: Configuring Content Classes for use in the ItemsControl Class Exercise 3: Using the Custom ItemsControl object in a User Control 2 6 11

Lab Answer Key: Creating Advanced User Interfaces

Lab: Presenting Items, Classes, and Dependency Properties


Exercise 1: Creating ItemsControl Objects
Task 1: Create the EventArgs class for the ItemsControl object.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod05\VB\Starter or D:\Labfiles\Mod05\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod05\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod05\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

To the GreetingCardConsumer project, add a new class named CoverFlowEventArgs. a. b. In Solution Explorer, right-click GreetingCardConsumer, point to Add, and then click Class. In the Add New Item GreetingCardConsumer dialog box, in the Name box, type CoverFlowEventArgs, and then click Add.

4.

Modify the class declaration so that it reads as follows.

[Visual Basic] Public Class CoverFlowEventArgs Inherits EventArgs

[Visual C#] public class CoverFlowEventArgs : EventArgs

5.

Add the following property declarations to the CoverFlowEventArgs class.

[Visual Basic] Public Property Index As Integer Public Property Item As Object Public Property MouseClick As Boolean

[Visual C#] public int Index { get; set; } public object Item { get; set;

Lab Answer Key: Creating Advanced User Interfaces

} public bool MouseClick { get; set; }

6.

Save the changes.

Task 2: Configure a class to inherit from the ItemsControl base class.


1. Open the CoverFlowControl class. 2. In the Solution Explorer window, double-click CoverFlowControl.vb or CoverFlowControl.cs.

Modify the class declaration so that it inherits from the ItemsControl base class and implements the INotifyPropertyChanged interface. a. If you are working in Visual Basic, modify the class declaration so that it reads as follows.

Public Class CoverFlowControl Inherits ItemsControl Implements INotifyPropertyChanged

b.

If you are working in Visual C#, modify the class declaration so that it reads as follows.

public class CoverFlowControl : ItemsControl, INotifyPropertyChanged

3.

Add an event delegate named SelectedItemChangedEvent immediately above the class declaration you have just modified. Ensure that the delegate accepts a parameter type of CoverFlowEventArgs. a. If you are working in Visual Basic, add the following event delegate immediately above the class declaration you have just modified.

Public Delegate Sub SelectedItemChangedEvent(ByVal e As CoverFlowEventArgs)

b.

If you are working in Visual C#, add the following event delegate immediately above the class declaration you have just modified.

public delegate void SelectedItemChangedEvent(CoverFlowEventArgs e);

4.

In the CoverFlowControl class, declare a public event of type SelectedItemChangedEvent and name it SelectedItemChanged. a. If you are working in Visual Basic, add the following event declaration immediately above the SelectedIndex public property procedure.

Public Event SelectedItemChanged As SelectedItemChangedEvent

b.

If you are working in Visual C#, add the following event declaration immediately above the SelectedIndex public property procedure.

public event SelectedItemChangedEvent SelectedItemChanged;

5.

Declare a class-level variable of type ItemsPresenter and name it ItemsPresenter. Declare a generic class-level variable of type List restricted to CoverFlowItemControl objects and name it cfItems.

Lab Answer Key: Creating Advanced User Interfaces

a.

If you are working in Visual Basic, add the following variable declarations immediately below the event declaration you have just added.

Private itmsPresenter As ItemsPresenter Private cfItems As List(Of CoverFlowItemControl)

b.

If you are working in Visual C#, add the following variable declarations immediately below the event declaration you have just added.

private ItemsPresenter ItemsPresenter; private List<CoverFlowItemControl> cfItems;

6.

Add the following procedure to manage changes when an item is selected.

[Visual Basic] Private Sub IndexSelected(ByVal index As Integer, ByVal mouseclick As Boolean, ByVal layoutChild As Boolean) If Items.Count > 0 AndAlso Items.Count > index Then selIndex = index If layoutChild Then LayoutChildren() End If Dim e As CoverFlowEventArgs = New CoverFlowEventArgs() With { .Index = index, .Item = cfItems(index).Content, .MouseClick = mouseclick } RaiseEvent SelectedItemChanged(e) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SelectedIndex")) RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SelectedItem")) End If End Sub

[Visual C#] private void IndexSelected(int index, bool mouseclick, bool layoutChildren) { if ((Items.Count > 0) && (Items.Count>index)) { selectedIndex = index; if(layoutChildren) { LayoutChildren(); } CoverFlowEventArgs e = new CoverFlowEventArgs() { Index = index, Item = cfItems[index].Content, MouseClick = mouseclick }; if (SelectedItemChanged != null) { SelectedItemChanged(e); }

Lab Answer Key: Creating Advanced User Interfaces

if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("SelectedIndex")); PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem")); }

7.

Add the following property procedure.

[Visual Basic] Public Property RotationAngle() As Double Get Return CType(GetValue(RotationAngleProperty), Double) End Get Set(ByVal value As Double) SetValue(RotationAngleProperty, value) End Set End Property

[Visual C#] public double RotationAngle { get { return (double)GetValue(RotationAngleProperty); } set { SetValue(RotationAngleProperty, value); } }

8.

Add the following code to create and register a dependency property.

[Visual Basic] Public Shared ReadOnly RotationAngleProperty As DependencyProperty _ = DependencyProperty.Register("RotationAngle", GetType(Double), GetType(CoverFlowControl), New PropertyMetadata(60R, New PropertyChangedCallback(AddressOf CoverFlowControl.OnValuesChanged)))

[Visual C#] public static readonly DependencyProperty RotationAngleProperty = DependencyProperty.Register("RotationAngle", typeof(double), typeof(CoverFlowControl), new PropertyMetadata(60d, new PropertyChangedCallback (CoverFlowControl.OnValuesChanged)));

9.

Save the changes.

Lab Answer Key: Creating Advanced User Interfaces

Exercise 2: Configuring Content Classes for use in the ItemsControl Class


Task 1: Configure a class as a ContentControl Template.
1. Open the CoverFlowItemControl class. 2. In the Solution Explorer window double-click CoverFlowItemControl.vb or CoverFlowItemControl.cs.

Modify the class declaration so that it inherits from ContentControl. Modify the class declaration so that it resembles the following.
[Visual Basic] Public Class CoverFlowItemControl Inherits ContentControl

[Visual C#] public class CoverFlowItemControl : ContentControl

3.

Declare a class-level variable called ContentPresenter type of ContentControl. Add the following class-level variable declaration to the CoverFlowItemControl class.
[Visual Basic] Private ContentPresenter as ContentControl

[Visual C#] private ContentControl ContentPresenter;

4.

Add the following public event to the CoverFlowItemControl class.

[Visual Basic] Public Event ItemSelected As EventHandler

[Visual C#] public event EventHandler ItemSelected;

5.

In the OnApplyTemplate procedure, locate the following comment.

TODO: Wire-up Mouse Event from Content Presenter

6.

Add the following code directly beneath the comment you have just identified.

[Visual Basic] If Not IsNothing(ContentPresenter) Then AddHandler ContentPresenter.MouseLeftButtonUp, New MouseButtonEventHandler(AddressOf ContentPresenter_MouseLeftButtonUp) End If

Lab Answer Key: Creating Advanced User Interfaces

[Visual C#] if (ContentPresenter != null) { ContentPresenter.MouseLeftButtonUp += new MouseButtonEventHandler(ContentPresenter_MouseLeftButtonUp); }

7.

Add the following event handler directly beneath the OnApplyTemplate procedure.

[Visual Basic] Sub ContentPresenter_MouseLeftButtonUp(ByVal sender As Object, ByVal e As MouseButtonEventArgs) RaiseEvent ItemSelected(Me, Nothing) End Sub

[Visual C#] void ContentPresenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (ItemSelected != null) { ItemSelected(this, null); } }

8.

Save the changes.

Task 2: Develop a class for use in the ItemsControl object.


1. To the GreetingCardConsumer project, add a new class called CardCategory to the Silverlight project, and configure it so that it imports the System.Xml.Linq and System.Collections.Generic namespaces. a. b. c. In the Solution Explorer window, right-click the GreetingCardConsumer project, point to Add, and then click Class. In the Add New Item GreetingCardConsumer dialog box, in the Name text box, type CardCategory, and then click Add. Add the following Imports or using statements at the top of the file.

[Visual Basic] Imports System.Xml.Linq Imports System.Collections.Generic

[Visual C#] using System.Xml.Linq; using System.Collections.Generic;

2.

Add the following public properties to the CardCategory class.


modTitle As String modToolTip As String modImageUrl As String modMediaFileTitles As List(Of String) modMediaFileUrls As List(Of String)

[Visual Basic] Public Property Public Property Public Property Public Property Public Property

Lab Answer Key: Creating Advanced User Interfaces

Public Property modMediaFileThumbnailPaths As List(Of String) Public Property modMediaFileTooltips As List(Of String)

[Visual C#] public string modTitle { get; set; } public string modToolTip { get; set; } public string modImageUrl { get; set; } public List<string> modMediaFileTitles { get; set; } public List<string> modMediaFileUrls { get; set; } public List<string> modMediaFileThumbnailPaths { get; set; } public List<string> modMediaFileTooltips { get; set; }

3.

Add the following constructor to the CardCategory class.

[Visual Basic] Public Sub New(ByVal xModule As XElement) modMediaFileTitles = New List(Of String) modMediaFileUrls = New List(Of String) modMediaFileThumbnailPaths = New List(Of String) modMediaFileTooltips = New List(Of String) parseXML(xModule) End Sub

[Visual C#] public CardCategory(XElement xModule) { modMediaFileTitles = new List<string>(); modMediaFileUrls = new List<string>(); modMediaFileThumbnailPaths = new List<string>(); modMediaFileTooltips = new List<string>();

Lab Answer Key: Creating Advanced User Interfaces

parseXML(xModule);

4.

Add the following procedure directly beneath the constructor you have just added.

[Visual Basic] Sub parseXML(ByVal xModule As XElement) If Not IsNothing(xModule.Element("THUMBNAIL")) Then Dim thumbNail As XElement = xModule.Element("THUMBNAIL") If Not IsNothing(thumbNail.Attribute("path")) Then modImageUrl = thumbNail.Attribute("path").Value End If If Not IsNothing(thumbNail.Attribute("tooltip")) Then modToolTip = thumbNail.Attribute("tooltip").Value End If End If If Not IsNothing(xModule.Element("CARDS")) Then Dim xMediaFile As XElement For Each xMediaFile In _ xModule.Element("CARDS").Descendants("CARD") If Not IsNothing(xMediaFile.Attribute("previewUrl")) Then modMediaFileUrls.Add _ (xMediaFile.Attribute("previewUrl").Value) Else modMediaFileUrls.Add(String.Empty) End If If Not IsNothing(xMediaFile.Attribute("previewThumb")) Then modMediaFileThumbnailPaths.Add _ (xMediaFile.Attribute("previewThumb").Value) Else modMediaFileThumbnailPaths.Add(String.Empty) End If If Not IsNothing(xMediaFile.Attribute("tooltip")) Then modMediaFileTooltips.Add _ (xMediaFile.Attribute("tooltip").Value) Else modMediaFileTooltips.Add _ ("Tooltip has not been set in XML file") End If Next End If End Sub

[Visual C#] private void parseXML(XElement xModule) { if (xModule.Element("THUMBNAIL") != null) { XElement thumbNail = xModule.Element("THUMBNAIL"); if (thumbNail.Attribute("path") != null) { modImageUrl = thumbNail.Attribute("path").Value; } if (thumbNail.Attribute("tooltip") != null)

10

Lab Answer Key: Creating Advanced User Interfaces

{ }

modToolTip = thumbNail.Attribute("tooltip").Value;

} if (xModule.Element("CARDS") != null) { foreach (XElement xMediaFile in xModule.Element("CARDS").Descendants("CARD")) { if (xMediaFile.Attribute("previewUrl") != null) { modMediaFileUrls.Add (xMediaFile.Attribute("previewUrl").Value); } else { modMediaFileUrls.Add(string.Empty); } if (xMediaFile.Attribute("previewThumb") != null) { modMediaFileThumbnailPaths.Add (xMediaFile.Attribute("previewThumb").Value); } else { modMediaFileThumbnailPaths.Add(string.Empty); } if (xMediaFile.Attribute("tooltip") != null) { modMediaFileTooltips.Add (xMediaFile.Attribute("tooltip").Value); } else { modMediaFileTooltips.Add ("Tooltip has not been set in XML file"); } } }

5.

Save the changes.

Lab Answer Key: Creating Advanced User Interfaces

11

Exercise 3: Using the Custom ItemsControl object in a User Control


Task 1: Configure XAML to use the custom ItemsControl object.
1. Open Home.xaml and add the following namespace declaration to the XAML.
xmlns:local="clr-namespace:GreetingCardConsumer"

a. b.

In the Solution Explorer window, expand the Views folder, and then double-click Home.xaml. Near the top of the XAML pane, locate the namespace declaration that reads as follows.

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

c. d.

Place the cursor at the end of the line you have just located and press Enter. Add the following namespace declaration to the empty line you have just created.

xmlns:local="clr-namespace:GreetingCardConsumer"

2.

Between the opening and closing tags of the Grid element with a name of MainGrid, add the following markup.

<local:CoverFlowControl x:Name="flowControl" Margin="0,0,0,0" Width="600"> <local:CoverFlowControl.ItemTemplate> <DataTemplate> <Border CornerRadius="1"> <Image Source="{Binding modImageUrl}" CacheMode="BitmapCache" Grid.Row="0" Height="130" ToolTipService.ToolTip="{Binding modToolTip}"/> </Border> </DataTemplate> </local:CoverFlowControl.ItemTemplate> </local:CoverFlowControl>

3.

Save the changes.

Task 2: Populate the CoverFlowControl from external XML data.


1. Review the contents of the GreetingCardConfig.xml in the ClientBin folder of the GreetingCardConsumer.Web project. You have already consumed parts of this file in the lab for a previous module. Now, you will use the rest of the XML to populate and configure the CoverFlowControl contents. a. b. 2. In the GreetingCardConsumer.Web project, expand the ClientBin folder Double-click GreetingCardConfig.xml.

In the GreetingCardConsumer project, open the Views\Home.xaml file in code view. In the Solution Explorer window, in the GreetingCardConsumer project, expand Views, rightclick Home.xaml, and then click View Code.

3.

In the webClient_DownloadStringCompleted event handler, locate the following comment.

TODO: Create card categories

4.

Add the following code directly below the comment you have just located.

12

Lab Answer Key: Creating Advanced User Interfaces

[Visual Basic] For Each xModule As XElement in xDoc.Descendants("CATEGORY") Dim cardCat As New CardCategory(xModule) categories.Add(cardCat) Next

[Visual C#] foreach (XElement xModule in xDoc.Descendants("CATEGORY")) { CardCategory cardCategory = new CardCategory(xModule); categories.Add(cardCategory); }

5.

Build the solution. On the Build menu, click Build Solution.

6.

Press Ctrl+F5 to run and test the application. The application loads categories of cards in the CoverFlowControl that you created in this lab. Each category displays a number of different cards, as specified by the GreetingCardConfig.xml file.

7.

Click each of the card categories in the CoverFlowControl to see how the contents of each category are updated. The contents of each category are represented by the XML file, and you exposed the relevant data as properties of the CardCategory class to update the other components in the user interface.

8.

Close all applications. You have now completed this lab.

Lab Answer Key: Using Local Assets

Module 6
Lab Answer Key: Using Local Assets
Contents:
Exercise 1: Printing from Silverlight Applications Exercise 2: Accessing the Clipboard in Silverlight Applications Exercise 3: Accessing Isolated Storage in Silverlight Applications Exercise 4: Accessing the File System in Silverlight Applications 2 5 7 9

Lab Answer Key: Using Local Assets

Lab: Using Local Assets


Exercise 1: Printing from Silverlight Applications
Task 1: Add code for printing in a Silverlight application.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod06\VB\Starter or D:\Labfiles\Mod06\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod06\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod06\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

Build the solution. Press Ctrl+Shift+B.

4.

In the GreetingCardConsumer project, in the Views folder, open Home.xaml. In the Solution Explorer window, in the GreetingCardConsumer project, expand the Views folder, and then double-click Home.xaml.

5.

Create an event handler for the Print button. In the Design pane of the Home.xaml window, double-click the Print button.

Visual Studio creates an event handler for the Click event of the button. 6. In the Home.xaml code file, bring the System.Windows.Printing namespace into scope. Add the following statement at the top of the Home.xaml.vb or Home.xaml.cs file.

[Visual Basic] Imports System.Windows.Printing

[Visual C#] using System.Windows.Printing;

7.

Add the following class-level variable declaration directly below the declaration of the viewThumbs class-level variable declaration.

[Visual Basic] Private currentPage As Integer = 0

[Visual C#] int currentPage = 0;

8.

Locate the print_Click event handler that Visual Studio created for you.

Lab Answer Key: Using Local Assets

9.

Add code to create and instantiate a new PrintDocument class named docToPrint. Create a new generic EventHandler, constrained to PrintPageEventArgs objects, and assign it to the PrintPage event of the PrintDocument object, passing the docToPrint_PrintPage method (not yet created). Finally, call the Print method of the PrintDocument object, passing the text, Silverlight Document. Add the following code to the print_Click event handler.
[Visual Basic] Dim docToPrint As New PrintDocument() AddHandler docToPrint.PrintPage, New EventHandler(Of PrintPageEventArgs)(AddressOf docToPrint_PrintPage) docToPrint.Print("Silverlight Document")

[Visual C#] PrintDocument docToPrint = new PrintDocument(); docToPrint.PrintPage += new EventHandler<PrintPageEventArgs>(docToPrint_PrintPage); docToPrint.Print("Silverlight Document");

10. Save the changes.

Task 2: Add an event handler to deal with multi-page printing.


1. Create a new method named docToPrint_PrintPage, which returns no value, accepting the standard event handler parameters, sender of type Object/object, and e of type PrintPageEventArgs. Add the following procedure directly beneath the print_Click event handler.
[Visual Basic] Sub docToPrint_PrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs) End Sub

[Visual C#] void docToPrint_PrintPage(object sender, PrintPageEventArgs e) { }

2.

To the docToPrint_PrintPage method, add code to perform the following operations: a. b. c. d. Increment the currentPage class-level variable by one. Check if the value of the currentPage variable is less than flowControl.Items.Count, and set the value of e.HasMorePages accordingly. Assign the value of currentPage - 1 to flowControl.SelectedIndex. Assign the LayoutRootUIElement to e.PageVisual. Add the following code to the docToPrint_PrintPage method.
[Visual Basic] currentPage += 1 If currentPage < flowControl.Items.Count Then e.HasMorePages = True Else e.HasMorePages = False End If

Lab Answer Key: Using Local Assets

flowControl.SelectedIndex = currentPage - 1 e.PageVisual = LayoutRoot

[Visual C#] currentPage++; if (currentPage < flowControl.Items.Count) { e.HasMorePages = true; } else { e.HasMorePages = false; } flowControl.SelectedIndex = currentPage 1; e.PageVisual = LayoutRoot;

3. 4.

Save the changes. Run the application. Press Ctrl+F5.

5. 6.

In Internet Explorer, click Print. Print to OneNote 2010. In the Print dialog box, click Send to OneNote 2010, and then click Print.

After a few seconds, OneNote appears. 7. In the Select Location in OneNote dialog box, click OK. OneNote displays a page for each card category in the Silverlight application. 8. Close OneNote, and then close Internet Explorer.

Lab Answer Key: Using Local Assets

Exercise 2: Accessing the Clipboard in Silverlight Applications


Task 1: Copy text to the clipboard programmatically.
1. 2. In the Home.xaml code file, locate the webClient_DownloadStringCompleted event handler. Add a class-level variable named contentsToCopy immediately above the webClient_DownloadStringCompleted event handler. The variable must be of type String/string and be assigned an empty string. Add the following class-level variable declaration immediately above the webClient_DownloadStringCompleted event handler.
[Visual Basic] Private contentsToCopy As String = String.Empty

[Visual C#] String contentsToCopy = string.Empty;

3. 4.

In the webClient_DownloadStringCompleted event handler, locate the TODO comment, Populate contentsToCopy variable. Immediately below the comment, assign the e.Result property to the contentsToCopy class-level variable. Immediately below the comment, add the following code.
[Visual Basic] contentsToCopy = e.Result

[Visual C#] contentsToCopy = e.Result;

5.

Create an event handler for the Copy button by using the Design view of Home.xaml. In the Home.xaml window, double-click the Copy button.

Visual Studio creates an event handler for the Click event of the button. 6. In the Click event handler for the Copy button, copy the value of the contentsToCopy class-level variable to the clipboard. Add the following code to copy_Click event handler.
[Visual Basic] Clipboard.SetText(contentsToCopy)

[Visual C#] Clipboard.SetText(contentsToCopy);

7.

Save the changes.

Lab Answer Key: Using Local Assets

Task 2: Paste text from the clipboard programmatically.


1. In the GreetingCardConsumer project, in the Views folder, open About.xaml. 2. In the Solution Explorer window, in the GreetingCardConsumer project, expand the Views folder, and then double-click About.xaml.

Create an event handler for the Paste button by using the Design view of About.xaml. In the About.xaml window, double-click the Paste button.

Visual Studio creates an event handler for the Click event of the button. 3. In the Click event handler for the Paste button, assign current text content of the clipboard to the Text property of the imContent control. Add the following code to paste_Click event handler.
[Visual Basic] imContent.Text = Clipboard.GetText() [Visual C#] imContent.Text = Clipboard.GetText();

4.

Save the changes.

Task 3: Test copy and paste actions.


1. Run the application. 2. 3. 4. Press Ctrl+F5.

In Internet Explorer, click Copy. In the Microsoft Silverlight dialog box, click Yes. Navigate to the About page. Internet Explorer, click About.

5.

In Internet Explorer, click Paste. The contents of the clipboard are pasted into the instant messaging text box.

6.

Open Notepad. On the Start menu, click All Programs, click Accessories, and then click Notepad.

7.

Paste the copied content into Notepad. On the Edit menu, click Paste.

The contents of the clipboard are pasted into Notepad. 8. Close Notepad, not saving the changes, and then close Internet Explorer.

Lab Answer Key: Using Local Assets

Exercise 3: Accessing Isolated Storage in Silverlight Applications


Task 1: Store persistent data in isolated storage.
1. 2. Switch to the Home.xaml code file. Bring the System.IO.IsolatedStorage namespace into scope. Add the following statement at the top of the file.
[Visual Basic] Imports System.IO.IsolatedStorage

[Visual C#] using System.IO.IsolatedStorage;

3.

Create a class-level variable named storage, of type IsolatedStorageSettings, and instantiate it to the value of the IsolatedStorageSettings. ApplicationSettings property. Add the following class-level variable declaration immediately below the currentPage variable.
[Visual Basic] Dim storage As IsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings

[Visual C#] IsolatedStorageSettings storage = IsolatedStorageSettings.ApplicationSettings;

4. 5.

Switch to the Home.xaml markup file. Create an event handler for the Set Default button by using the Design view of Home.xaml. In the Home.xaml window, double-click the Set Default button.

Visual Studio creates the snapshot_Click event handler for the Click event of the button. 6. Add code to the snapshot_Click event handler to check if the storage variable contains a setting named currentCategory. If it does, set the currentCategory setting to the value of flowControl.SelectedIndex; otherwise, add the currentCategory setting with a value of flowControl.SelectedIndex. Add the following code to the snapshot_Click event handler.
[Visual Basic] If storage.Contains("currentCategory") Then storage("currentCategory") = flowControl.SelectedIndex Else storage.Add("currentCategory", flowControl.SelectedIndex) End If

[Visual C#] if (storage.Contains("currentCategory"))

Lab Answer Key: Using Local Assets

storage["currentCategory"] = flowControl.SelectedIndex; } else { storage.Add("currentCategory", flowControl.SelectedIndex); }

7.

Save the changes.

Task 2: Retrieve persistent data from isolated storage.


1. 2. In the Home.xaml code file, locate the webClient_DownloadStringCompleted event handler. Append code to the webClient_DownloadStringCompleted event handler to check if the storage variable contains a setting named currentCategory. If it does, set the flowControl.SelectedIndex property to the value of currentCategory setting. Append the following code to the webClient_DownloadStringCompleted event handler.
[Visual Basic] If storage.Contains("currentCategory") Then flowControl.SelectedIndex = CInt(storage("currentCategory")) End If

[Visual C#] if (storage.Contains("currentCategory")) { flowControl.SelectedIndex = (int)storage["currentCategory"]; }

3.

Save the changes.

Task 3: Test persistent data storage and retrieval.


1. Run the application. 2. 3. 4. 5. Press Ctrl+F5.

Use the coverflow control to navigate to the Greeting Cards for General Occasions category. Click Set Default. Close Internet Explorer. Run the application again. Press Ctrl+F5. Note that the Greeting Cards for General Occasions category is selected by default.

6.

Close Internet Explorer, and then close Visual Studio.

Lab Answer Key: Using Local Assets

Exercise 4: Accessing the File System in Silverlight Applications


Task 1: Save a file to the file system programmatically.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardManagement solution from the D:\Labfiles\Mod06\VB\Starter or D:\Labfiles\Mod06\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod06\VB\Starter\ GreetingCardManagement.sln or D:\Labfiles\Mod06\CS\Starter\ GreetingCardManagement.sln, and then click Open.

3.

Build the solution. Press Ctrl+Shift+B.

4.

In the GreetingCardManagement project, in the Views folder, open Home.xaml. In the Solution Explorer window, in the GreetingCardManagement project, expand the Views folder, and then double-click Home.xaml.

5.

Create an event handler for the Save Diagnostic File button. In the Design pane of the Home.xaml window, double-click the Save Diagnostic File button.

Visual Studio creates an event handler for the Click event of the button. 6. Add the following code to the save_Click event handler.

[Visual Basic] Try Dim filePathName As String = _ System.IO.Path.Combine(Environment.GetFolderPath( _ Environment.SpecialFolder.MyDocuments), _ "GreetingCardDiagnostics.txt") If (File.Exists(filePathName)) Then File.Delete(filePathName) End If Dim fileContents As StreamWriter = File.CreateText(filePathName) Dim displayName As String = "Your Display Name is: " & _ displayNameTextBox.Text Dim email As String = "Your Email Address is: " & _ emailTextBox.Text fileContents.WriteLine(displayName) fileContents.WriteLine(email) fileContents.Close() Catch secEx As System.Security.SecurityException ErrorWindow.CreateNew(New Exception( _ "Only out-of-browser applications can save files")) Catch ex As Exception ErrorWindow.CreateNew(ex) End Try

10

Lab Answer Key: Using Local Assets

[Visual C#] try { string filePathName = System.IO.Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "GreetingCardDiagnostics.txt"); if (File.Exists(filePathName)) File.Delete(filePathName); StreamWriter fileContents = File.CreateText(filePathName); string displayName = "Your Display Name is: " + displayNameTextBox.Text; string email = "Your Email Address is: " + emailTextBox.Text; fileContents.WriteLine(displayName); fileContents.WriteLine(email); fileContents.Close();

} catch (System.Security.SecurityException secEx) { ErrorWindow.CreateNew(new Exception ("Only out-of-browser applications can save files")); } catch (Exception ex) { ErrorWindow.CreateNew(ex); }

7.

Save the changes.

Task 2: Read a file from the file system programmatically.


1. In the GreetingCardManagement project, in the Views folder, open About.xaml. 2. In the Solution Explorer window, in the GreetingCardManagement project, expand the Views folder, and then double-click About.xaml.

Create an event handler for the Open Diagnostic File button. In the Design pane of the About.xaml window, double-click the Open Diagnostic File button.

Visual Studio creates an event handler for the Click event of the button. 3. Add the following code to the open_Click event handler.

[Visual Basic] Try Dim filePathName As String = System.IO.Path.Combine( _ Environment.GetFolderPath( _ Environment.SpecialFolder.MyDocuments), _ "GreetingCardDiagnostics.txt") If Not File.Exists(filePathName) Then ErrorWindow.CreateNew(New Exception("Diagnostic file does not exist")) Return End If Dim fileContents As StreamReader = New StreamReader(filePathName) imContent.Text = fileContents.ReadToEnd() fileContents.Close()

Lab Answer Key: Using Local Assets

11

Catch secEx As System.Security.SecurityException ErrorWindow.CreateNew(New Exception( _ "Only out-of-browser applications can open files ")) Catch ex As Exception ErrorWindow.CreateNew(ex) End Try

[Visual C#] try { string filePathName = System.IO.Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "GreetingCardDiagnostics.txt"); if (!File.Exists(filePathName)) { ErrorWindow.CreateNew(new Exception ("Diagnostic file does not exist")); } return;

} catch (System.Security.SecurityException secEx) { ErrorWindow.CreateNew(new Exception ("Only out-of-browser applications can open files")); }

StreamReader fileContents = new StreamReader(filePathName); imContent.Text = fileContents.ReadToEnd(); fileContents.Close();

4.

Save the changes.

Task 3: Test file access in Silverlight.


1. Open the Project Designer. 2. In the Solution Explorer window, right-click the GreetingCardManagement project, and then click Properties.

Ensure the application can be run out of the browser. Ensure the Enable running application out of the browser check box is selected.

3.

Open the Out-of-Browser Settings dialog box. In the Project Designer, click Out-of-Browser Settings.

4.

Ensure the application has elevated permissions when running outside the browser, and close the Out-of-Browser Settings dialog box. Ensure the Require elevated trust when running outside the browser check box is selected, and then click OK.

5.

Run the application. Press Ctrl+F5.

6.

Save the diagnostic file.

12

Lab Answer Key: Using Local Assets

In Internet Explorer, click Save Diagnostic File.

Note The error window displays your error message because you are not running the application outside the browser. 7. Close the error window. 8. In the error window, click OK.

Install the GreetingCardManagement application locally. Right-click the background of the Silverlight application, click Install GreetingCard Desktop Management onto this computer.

The Security Warning dialog box appears. 9. Accept the security warning and continue with the installation. In the Security Warning dialog box, click Install.

The application opens in its own window. 10. Close Internet Explorer. 11. In the GreetingCard management application, save the diagnostic file. Click Save Diagnostic File.

12. Open the GreetingCardDiagnostics.txt file saved to the Documents folder, in Notepad, and review the contents. a. b. c. On the Start menu, click Documents. Double-click GreetingCardDiagnostics.txt. Review the contents of the file, which should contain the user details for Hatim Aiad.

13. Close Notepad. 14. Switch back to the GreetingCardManagement application. 15. Navigate to the About page. In the GreetingCardManagement application, click About.

16. Open the diagnostic file. Click Open Diagnostic File.

17. Review the content that is added to the instant messaging text box. It should be the same content you saw in the diagnostic file. 18. Close all open applications, including Visual Studio. You have now completed this lab.

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

Module 7
Lab Answer Key: Implementing Advanced Media Techniques in Silverlight
Contents:
Exercise 1: Adding a Deep Zoom Image Exercise 2: Adding a Media Player 2 6

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

Lab: Implementing Advanced Media Techniques in Silverlight


Exercise 1: Adding a Deep Zoom Image
Task 1: Create a new project.
1. Open Microsoft Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Create a new Silverlight application named GreetingCardGreenfield in the D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter folder, by using the Silverlight Business Application template. a. b. c. d. e. f. On the File menu, point to New, and then click Project. In the Installed Templates section, expand Visual Basic or Visual C#, and then click Silverlight. In the list of project types, click Silverlight Business Application. In the Name box, type GreetingCardGreenfield. In the Location box, type D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter. Click OK.

A Silverlight project named GreetingCardGreenfield is created. A website named GreetingCardGreenfield.Web for hosting the Silverlight application and its services is also created.

Task 2: Create the Deep Zoom images.


1. Open Deep Zoom Composer. 2. On the Start menu, click All Programs, click Microsoft Expression, and then click Deep Zoom Composer.

Create a new project named DeepZoomImage in the D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter folder. a. b. In the dialog box, on the Projects tab, click New Project. In the New Project dialog box, in the Name box, type DeepZoomImage, in the Location box, type D:\Labfiles\Mod07\VB\Starter or D:\Labfiles\Mod07\CS\Starter, and then click OK.

3.

Add the images from the C:\Users\Public\Pictures\Sample Pictures folder to the solution. a. b. c. d. Click Add image. Navigate to the C:\Users\Public\Pictures\Sample Pictures folder. Select the first image. Press and hold down Shift, click the last image, and then click Open.

Task 3: Compose the Deep Zoom images.


1. Compose the Deep Zoom images. Click Compose.

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

2. 3.

Drag all of the images from the Images pane onto the work space. Align the 8 images in two rows of 4 equally sized images.

Task 4: Export the Deep Zoom images.


1. Export the composed Deep Zoom images. 2. Click Export.

Set the following settings. Output type: Silverlight Deep Zoom Name: DeepZoomImage Export options: Export as a collection (multiple images) Templates: Deep Zoom Navigation (Default)

3. 4.

Click Export. Close Deep Zoom Composer, saving the project. a. b. c. In the Export Completed dialog box, click Close. In the Deep Zoom Composer window, click the Close button. In the Deep Zoom Composer dialog box, click Yes.

Task 5: Load the Deep Zoom images.


1. Add the generated image file folder, GeneratedImages, in the D:\Labfiles\Mod07\VB\Starter\DeepZoomImage \Exported Data\deepzoomimage or D:\Labfiles\Mod07\CS\Starter\DeepZoomImage\ Exported Data\deepzoomimage folder, to the GreetingCardGreenfield.Web project, by using Windows Explorer. a. b. Open Windows Explorer. Navigate to the D:\Labfiles\Mod07\VB\Starter\DeepZoomImage\Exported Data\deepzoomimage or D:\Labfiles\Mod07\CS\Starter\DeepZoomImage\Exported Data\deepzoomimage folder, and then select the GeneratedImages folder. Press and hold down Ctrl, and then drag the D:\Labfiles\Mod07\VB\Starter\DeepZoomImage \Exported Data\deepzoomimage\GeneratedImages or D:\Labfiles\Mod07\CS\Starter\DeepZoomImage\ Exported Data\deepzoomimage\GeneratedImages folder into the D:\Labfiles\Mod07\VB\Starter\GreetingCardGreenfield\GreetingCardGreenfield.Web or D:\Labfiles\Mod07\CS\Starter\GreetingCardGreenfield\GreetingCardGreenfield.Web folder. This will copy the deep zoom images into your project.

c.

2. 3.

Close Windows Explorer and switch to Visual Studio. In the MainPage.xaml window, change the Grid control to a StackPanel control with no property values set explicitly. Change the following markup:
<Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}"> </Grid>

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

to the following markup:


<StackPanel> </StackPanel>

4.

Add a MultiScaleImage control named, dzMultiScaleImage, to the StackPanel control. Set the Source property to http://localhost:26982/GeneratedImages/dzc_output.xml. Add the following markup to the StackPanel control.
<MultiScaleImage Name="dzMultiScaleImage" Source="http://localhost:26982/GeneratedImages/dzc_output.xml" />

5.

The port number is most likely different on your setup, so use the Project Designer for the GreetingCardGreenfield.Web project to find the actual port number. a. b. c. d. In the Solution Explorer window, right-click GreetingCardGreenfield.Web, and then click Properties. In the Project Designer, click Web. On the Web page, in the Servers section, note the number displayed in the disabled Specific port box. Close the Project Designer.

6. 7.

If the port number is different than 26982, change the number in markup after localhost:. Build the solution. On the Build menu, click Build Solution.

The deep zoom image will display in the Design view. 8. Run the application to see the results. 9. Press Ctrl+F5.

Close Internet Explorer.

Task 6: Add zoom functionality.


1. Add two Button controls to the StackPanel control, named zoomIn and zoomOut. Add the controls before the MultiScaleImage control, and set the Content property to a value of + or -, respectively. Add the following markup at the uppermost part of the MultiScaleImage control.
<Button Name="zoomIn" Content="+" /> <Button Name="zoomOut" Content="-" />

2.

Create an event handler for the Click event for each of the two Button controls. a. b. c. In the Design view, double-click the zoomIn control. Switch back to the MainPage.xaml window. In the Design view, double-click the zoomOut control.

3.

Add code to the zoomIn_Click event handler, to zoom in on the image, by using the ZoomAboutLogicalPoint method, with a zoom parameter value of 3, a logicalPoint.X value of 0.5, and a logicalPoint.Y value of 0.5.

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

Add the following code to the zoomIn_Click event handler.


[Visual Basic] dzMultiScaleImage.ZoomAboutLogicalPoint(3, 0.5, 0.5)

[Visual C#] dzMultiScaleImage.ZoomAboutLogicalPoint(3, 0.5, 0.5);

4.

Add code to the zoomOut_Click event handler, to zoom out of the image, by using the ZoomAboutLogicalPoint method, with a zoom parameter value of 0.3, a logicalPoint.X value of 0.5, and a logicalPoint.Y value of 0.5. Add the following code to the zoomOut_Click event handler.
[Visual Basic] dzMultiScaleImage.ZoomAboutLogicalPoint(0.3, 0.5, 0.5)

[Visual C#] dzMultiScaleImage.ZoomAboutLogicalPoint(0.3, 0.5, 0.5);

5.

Run the application to see the results, by pressing both buttons several times. Press Ctrl+F5.

6.

Close Internet Explorer.

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

Exercise 2: Adding a Media Player


Task 1: Add a video file.
1. Add the video, C:\Users\Public\Videos\Sample Videos\Wildlife.wmv, to the root of the GreetingCardGreenfield.Web project. a. b. c. d. Open Windows Explorer. Navigate to the C:\Users\Public\Videos\Sample Videos folder. Select and copy the Wildlife.wmv file. Navigate to the type D:\Labfiles\Mod07\VB\Starter\GreetingCardGreenfield\ GreetingCardGreenfield.Web or D:\Labfiles\Mod07\CS\Starter\GreetingCardGreenfield\ GreetingCardGreenfield.Web folder. Paste the copied file. Close Windows Explorer.

e. f.

Task 2: Add a new user control.


1. Add a new UserControl named, Media, to the GreetingCardGreenfield project. a. b. c. d. 2. In Solution Explorer, right-click the GreetingCardGreenfield project, point to Add, and then click New Item. In the Add New Item GreetingCardGreenfield dialog box, in the list of project items, click Silverlight User Control. In the Name box, type Media. Click Add.

In the Media.xaml window, add the following markup written with bold formatting.

<UserControl x:Class="Media.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <MediaElement Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Source="http://localhost:26982/Wildlife.wmv" Name="videoMediaElement" /> </Grid> </UserControl>

3.

If the port number is different than 26982, change the number in markup after localhost:. You checked the port number in the previous exercise.

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

Task 3: Change the startup XAML file.


1. Open the App.xaml code file. 2. In the Solution Explorer window, right-click App.xaml, and then click View Code.

In the App class constructor, set the VisualRoot property of the App class to a new instance of the MediaUserControl. Set the App.VisualRoot property to the following value.
[Visual Basic] Me.RootVisual = New Media()

[Visual C#] this.RootVisual = new Media();

3.

Run the application to see the results, and notice that the playback starts automatically (after the page and video has been loaded). Press Ctrl+F5.

4. 5.

Close Internet Explorer. Close the App.xaml.vb or App.xaml.cs window.

Task 4: Create media buttons for user interaction.


1. To the Media.xaml file, add three Button controls to the Grid control, named stopButton, pauseButton, and playButton. Add the controls after the MediaElement control, and set the Grid.Row property to a value of 1, and the Grid.Column property to a value of 0, 1, or 2, respectively. Set the Content property to a value of Stop, Pause, and Play, respectively. Add the following markup after the MediaElement control.
<Button Content="Stop" Grid.Row="1" Grid.Column="0" Name="stopButton" /> <Button Content="Pause" Grid.Row="1" Grid.Column="1" Name="pauseButton" /> <Button Content="Play" Grid.Row="1" Grid.Column="2" Name="playButton" />

2.

Create an event handler for the Click event for each of the three Button controls. a. b. c. d. e. In the Design view, double-click the stopButton control. Switch back to the Media.xaml window. In the Design view, double-click the pauseButton control. Switch back to the Media.xaml window. In the Design view, double-click the playButton control.

3.

Add code to the stopButton_Click event handler to call the Stop method of the MediaElement control. Add the following code to the stopButton_Click event handler.
[Visual Basic] videoMediaElement.Stop()

Lab Answer Key: Implementing Advanced Media Techniques in Silverlight

[Visual C#] videoMediaElement.Stop();

4.

Add code to the pauseButton_Click event handler to call the Pause method of the MediaElement control. Add the following code to the pauseButton_Click event handler.
[Visual Basic] videoMediaElement.Pause()

[Visual C#] videoMediaElement.Pause();

5.

Add code to the playButton_Click event handler to call the Play method of the MediaElement control. Add the following code to the playButton_Click event handler.
[Visual Basic] videoMediaElement.Play()

[Visual C#] videoMediaElement.Play();

6.

Run the application and demonstrate the video controls. a. b. c. d. e. Press Ctrl+F5. After the video has loaded and started playing, click Pause. Click Play to resume the playback. Click Stop to stop playback. Click Play to start playback from the beginning.

7. 8.

Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Answer Key: Developing Silverlight Media Framework Solutions

Module 8
Lab Answer Key: Developing Silverlight Media Framework Solutions
Contents:
Exercise 1: Adding Support for the Silverlight Media Framework Exercise 2: Configuring the Silverlight Media Framework Player 2 4

Lab Answer Key: Developing Silverlight Media Framework Solutions

Lab: Developing Silverlight Media Framework Solutions


Exercise 1: Adding Support for the Silverlight Media Framework
Task 1: Add references to the Silverlight Media Framework DLLs.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod08\VB\Starter or D:\Labfiles\Mod08\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod08\VB\Starter\GreetingCardConsumer.sln or D:\Labfiles\Mod08\CS\Starter\GreetingCardConsumer.sln, and then click Open.

3.

To access the SMF functionality, add a reference to the following assemblies, all located in the D:\microsoft-smf-bin-2.2010.1221.1 folder: a. b. c. d. e. Microsoft.SilverlightMediaFramework.Core.dll Microsoft.SilverlightMediaFramework.Plugins. ClearTextCaptions.dll Microsoft.SilverlightMediaFramework.Plugins.dll Microsoft.SilverlightMediaFramework.Plugins. Heuristics.dll Microsoft.SilverlightMediaFramework.Plugins. Progressive.dll Microsoft.SilverlightMediaFramework.Plugins. SmoothStreaming.dll Microsoft.SilverlightMediaFramework.Plugins. TimedText.dll Microsoft.SilverlightMediaFramework.Utilities.dll In Solution Explorer, right-click the GreetingCardConsumer project, and then click Add Reference. In the Add Reference dialog box, click Browse. Navigate to the D:\microsoft-smf-bin-2.2010.1221.1 folder. SelectMicrosoft.SilverlightMediaFramework.Core.dll. Press and hold down Ctrl, and then select the following files: Microsoft.SilverlightMediaFramework.Plugins. ClearTextCaptions.dll

Lab Answer Key: Developing Silverlight Media Framework Solutions

f. 4.

Microsoft.SilverlightMediaFramework.Plugins.dll Microsoft.SilverlightMediaFramework.Plugins. Heuristics.dll Microsoft.SilverlightMediaFramework.Plugins. Progressive.dll Microsoft.SilverlightMediaFramework.Plugins. SmoothStreaming.dll Microsoft.SilverlightMediaFramework.Plugins. TimedText.dll Microsoft.SilverlightMediaFramework.Utilities.dll

Click OK.

Build the solution. On the Build menu, click Build Solution.

Task 2: Add Silverlight Media Framework namespaces.


1. Open About.xaml from the Views folder in GreetingCardConsumer project. 2. In Solution Explorer, in the GreetingCardConsumer project, expand the Views folder, and then double-click About.xaml.

In the XAML pane, locate the namespace declaration that reads as follows.

xmlns:navigation="clrnamespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

3. 4.

Place the cursor at the end of the line you have just located, and then press Enter. On the empty line you have just created, add the following namespace declaration.

xmlns:SMF="clr-namespace:Microsoft.SilverlightMediaFramework.Core; assembly=Microsoft.SilverlightMediaFramework.Core"

Note 5.

Ensure you add the above namespace declaration all on a single line.

Switch to Code view. On the View menu, click Code.

6.

Import the following namespaces in the code file: Microsoft.SilverlightMediaFramework.Core Microsoft.SilverlightMediaFramework.Core.Media Microsoft.SilverlightMediaFramework.Plugins. Primitives

7.

Save the changes.

Lab Answer Key: Developing Silverlight Media Framework Solutions

Exercise 2: Configuring the Silverlight Media Framework Player


Task 1: Review the XML and configuration data for videos.
1. In the GreetingCardApplication.Web project, open the GreetingCardConsumerTestPage.aspx page. 2. In Solution Explorer, in the GreetingCardApplication.Web project, double-click GreetingCardConsumerTestPage.aspx.

In the body section of the page, locate the object tag and review the initParams data. Note Note how the path to a video and a path to transcript file are provided as initiation parameters, in addition to the configXmlFileUri parameter that you have already worked with in previous labs.

3.

Open VideoTranscript.xml in the ClientBin folder, and review the transcript markup. a. b. Expand the ClientBin folder. Double-click VideoTranscript.xml.

Task 2: Add the Silverlight Media Framework Player XAML.


1. 2. Switch to About.xaml. In the XAML pane, locate the following comment.

TODO: Add the SMF Player Here

3.

To add a media player to the About page, wrapped in a Canvas element, add the following markup directly beneath the comment that you have just located.

<Canvas x:Name="videoPlayer" Canvas.ZIndex="0" Width="350" Height="310"> <Canvas.RenderTransform> <TranslateTransform x:Name="videoPlayerPosition" X="10" Y="10"></TranslateTransform> </Canvas.RenderTransform> <SMF:SMFPlayer x:Name="xVideoPlayer" AutoLoad="False" AutoPlay="False" PlaylistVisibility="Disabled" ScriptableName="VideoPlayer" CaptionsVisibility="Visible" ChaptersVisibility="Disabled" LoggingConsoleVisibility="Disabled" PlayerGraphVisibility="Disabled" VersionInformationVisibility="Disabled" AllowFullScreenPinning="True" Width="350" Height="310"/> </Canvas>

4.

Save the changes.

Task 3: Add code to manage Full Screen view.


1. 2. In Solution Explorer, right-click App.xaml, and then click View Code. Locate the following comment.

Lab Answer Key: Developing Silverlight Media Framework Solutions

TODO: Add Full Screen Management Code

3.

Add the following code directly beneath the comment you have just located.

[Visual Basic] Public Shared vidToResize As SMFPlayer Public Shared vidToMove As TranslateTransform Public Shared vidContainer As Canvas Public Shared Sub PositionVideo() Dim thisVid As SMFPlayer = App.vidToResize Dim thisVidPos As TranslateTransform = App.vidToMove Dim thisVidContainer As Canvas = App.vidContainer If Application.Current.Host.Content.IsFullScreen = False Then ' Reset to default position thisVidContainer.Height = 310 thisVid.Height = 310 thisVidContainer.Width = 350 thisVid.Width = 350 thisVidPos.X = 10 thisVidPos.Y = 10 Return End If ' Make the video fill the screen thisVid.Height = _ Application.Current.Host.Content.ActualHeight - 100 thisVid.Width = _ Application.Current.Host.Content.ActualWidth - 5 thisVidContainer.Height = _ Application.Current.Host.Content.ActualHeight - 100 thisVidContainer.Width = _ Application.Current.Host.Content.ActualWidth - 5 thisVidPos.X = 0 thisVidPos.Y = 0 End Sub

[Visual C#] public static SMFPlayer vidToResize; public static TranslateTransform vidToMove; public static Canvas vidContainer; public static void PositionVideo() { SMFPlayer thisVid = App.vidToResize; TranslateTransform thisVidPos = App.vidToMove; Canvas thisVidContainer = App.vidContainer; if (!Application.Current.Host.Content.IsFullScreen) { // Reset to default position thisVidContainer.Height = 310; thisVid.Height = 310; thisVidContainer.Width = 350; thisVid.Width = 350; thisVidPos.X = 10; thisVidPos.Y = 10; return;

Lab Answer Key: Developing Silverlight Media Framework Solutions

} // Make the video fill the screen thisVid.Height = Application.Current.Host.Content.ActualHeight - 100; thisVid.Width = Application.Current.Host.Content.ActualWidth - 5; thisVidContainer.Height = Application.Current.Host.Content.ActualHeight - 100; thisVidContainer.Width = Application.Current.Host.Content.ActualWidth - 5; thisVidPos.X = 0; thisVidPos.Y = 0;

4. 5.

Open About.xaml in Code view. Add the following code to the Page_Loaded or About_Loaded event handler.

[Visual Basic] App.vidToResize = xVideoPlayer App.vidContainer = videoPlayer App.vidToMove = videoPlayerPosition App.PositionVideo() AddHandler xVideoPlayer.FullScreenChanged, _ AddressOf xVideoPlayer_FullScreenChanged

[Visual C#] App.vidToResize = xVideoPlayer; App.vidContainer = videoPlayer; App.vidToMove = videoPlayerPosition; App.PositionVideo(); xVideoPlayer.FullScreenChanged += new EventHandler(xVideoPlayer_FullScreenChanged);

6.

Add the following code to the xVideoPlayer_FullScreenChanged procedure.

[Visual Basic] App.PositionVideo()

[Visual C#] App.PositionVideo();

7.

Save the changes.

Task 4: Add code to set the MediaSource for a video.


1. Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] Dim videoUri As String = _ App.Current.Resources("videoPath").ToString() xVideoPlayer.CurrentPlaylistItem = Nothing xVideoPlayer.Playlist.Clear() Dim currentVid As PlaylistItem = New PlaylistItem() currentVid.MediaSource = New Uri(videoUri, UriKind.Absolute)

Lab Answer Key: Developing Silverlight Media Framework Solutions

currentVid.DeliveryMethod = DeliveryMethods.ProgressiveDownload

[Visual C#] string videoUri = App.Current.Resources["videoPath"].ToString(); xVideoPlayer.CurrentPlaylistItem = null; xVideoPlayer.Playlist.Clear(); PlaylistItem currentVid = new PlaylistItem(); currentVid.MediaSource = new Uri(videoUri, UriKind.Absolute); currentVid.DeliveryMethod = DeliveryMethods.ProgressiveDownload;

2.

Save the changes.

Task 5: Add code to set captions for the video.


1. Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] Dim captionUri As String = _ App.Current.Resources("transcriptPath").ToString() Try Dim vidMarkerResource As MarkerResource = New MarkerResource() vidMarkerResource.Format = "TTAF1-DFXP" vidMarkerResource.Source = New Uri(captionUri, UriKind.Absolute) currentVid.MarkerResource = vidMarkerResource Catch ' Silent failure if captions are missing ' Video will play without captions. End Try

[Visual C#] string captionUri = App.Current.Resources["transcriptPath"].ToString(); try {

} catch { // Silent failure if captions are missing // Video will play without captions. }

MarkerResource vidMarkerResource = new MarkerResource(); vidMarkerResource.Format = "TTAF1-DFXP"; vidMarkerResource.Source = new Uri(captionUri, UriKind.Absolute); currentVid.MarkerResource = vidMarkerResource;

2.

Save the changes.

Task 6: Add code to play a video.


1. Add the following code after the existing code in the Page_Loaded or About_Loaded event handler.
[Visual Basic] xVideoPlayer.Playlist.Add(currentVid)

Lab Answer Key: Developing Silverlight Media Framework Solutions

xVideoPlayer.Play()

[Visual C#] xVideoPlayer.Playlist.Add(currentVid); xVideoPlayer.Play();

2. 3.

Save the changes. Start the application. Press Ctrl+F5.

4.

Click About. Note The video plays and displays the captions from the caption file.

5.

Near the lower part of the video player, click CC. Note The captions are hidden.

6. 7. 8.

Click CC to turn the captions back on. Near the lower-right of the video player, click the full screen button. In the Microsoft Silverlight dialog box, click Yes. Note The application switches to full screen view and the video is resized and positioned to occupy most of the screen. You wrote the code to position and resize the video in this lab.

9.

Switch back to non-full screen view. Press Esc.

Note The application switches out of full screen view and the video is resized and positioned to occupy its original location. You wrote the code to position and resize the video in this lab. 10. Close all applications.

Lab Answer Key: Accessing Hardware in Silverlight Applications

Module 9
Lab Answer Key: Accessing Hardware in Silverlight Applications
Contents:
Exercise 1: Interacting with the Mouse Wheel Exercise 2: Interacting with the Keyboard 2 6

Lab Answer Key: Accessing Hardware in Silverlight Applications

Lab: Interacting with Hardware Programmatically


Exercise 1: Interacting with the Mouse Wheel
Task 1: Attach to HTML mouse wheel events.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod09\VB\Starter or D:\Labfiles\Mod09\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod09\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod09\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

In the GreetingCardConsumer project, in the Views folder, open Home.xaml in Code view. In the Solution Explorer window, expand Views, right-click Home.xaml, and then click View Code.

4.

Locate the following comment in the Page_Load or Home_Loaded event handler.

TODO: Attach HTML Events

5.

Add code directly beneath the comment you have just located, to attach the following event handlers to the corresponding event of the specified object, by using the AttachEvent method. This will help ensure the mouse wheel works on different platforms than Windows, and different browsers than Internet Explorer. Event Name DOMMouseScroll onmousewheel onmousewheel Event Handler OnMouseWheel OnMouseWheel OnMouseWheel

Object Window Window Document

Add the following code directly beneath the comment you have just located.
[Visual Basic] HtmlPage.Window.AttachEvent("DOMMouseScroll", AddressOf OnMouseWheel) HtmlPage.Window.AttachEvent("onmousewheel", AddressOf OnMouseWheel) HtmlPage.Document.AttachEvent("onmousewheel", AddressOf OnMouseWheel)

[Visual C#] HtmlPage.Window.AttachEvent("DOMMouseScroll", OnMouseWheel); HtmlPage.Window.AttachEvent("onmousewheel", OnMouseWheel); HtmlPage.Document.AttachEvent("onmousewheel", OnMouseWheel);

Lab Answer Key: Accessing Hardware in Silverlight Applications

6.

Overload the private event handler named, OnMouseWheel, with the usual event handler signature, accepting the sender argument of type Object/object, and args argument of type HtmlEventArgs. Add code to suppress the events by calling the PreventDefault method of the args argument. This will help ensure the mouse wheel works on different platforms than Windows, and different browsers than Internet Explorer. Add the following code directly beneath the Page_Loaded or Home_Loaded event handler.
[Visual Basic] Private Overloads Sub OnMouseWheel(ByVal sender As object, ByVal args As HtmlEventArgs) args.PreventDefault() End Sub

[Visual C#] private void OnMouseWheel(object sender, HtmlEventArgs args) { args.PreventDefault(); }

7.

Save the changes.

Task 2: Create and configure the mouse wheel event handler.


1. [Visual C# only] Bring the System.Windows.Input namespaces into scope. Add the following code at the beginning of the namespace declaration.
[Visual C#] using System.Windows.Input;

2.

Append code to the Page_Loaded or Home_Loaded event handler, to add an event handler for the MouseWheel event of the flowControl object. Append the following code to the Page_Loaded or Home_Loaded event handler.
[Visual Basic] AddHandler flowControl.MouseWheel, AddressOf flowControl_MouseWheel

[Visual C#] flowControl.MouseWheel += new MouseWheelEventHandler(flowControl_MouseWheel);

3.

Add an event handler named, flowControl_MouseWheel, with the usual event handler signature, accepting the sender argument of type Object/object, and e argument of type MouseWheelEventArgs. Add the event handler directly beneath the Page_Loaded or Home_Loaded event handler. Add the following code directly beneath the Page_Loaded or Home_Loaded event handler.
[Visual Basic] Sub flowControl_MouseWheel(ByVal sender As object, ByVal e As MouseWheelEventArgs) End Sub

Lab Answer Key: Accessing Hardware in Silverlight Applications

[Visual C#] void flowControl_MouseWheel(object sender, MouseWheelEventArgs e) { }

4.

Add code to the flowControl_MouseWheel event handler to perform the following operations: a. Create a variable named, i, of type Integer/int, and assign the value of the Delta property of the MouseWheelEventArgs parameter, divided by 120. Negate the result before assigning. This means the control will navigate one cover for each mouse scroll. Create a variable named, index, of type Integer/int, and assign the value of the flowControl.SelectedIndex property, plus the value of the variable i. This means the control will navigate one cover for each mouse scroll. Check if the value of index is less than 0, and if it is, call the First method of the flowControl object. If not, check if index is larger than the value of the flowControl.Items.Count property, minus 1. If it is, call the Last method of the flowControl object. If not, set the flowControl.SelectedIndex property to the value of the index variable. This ensures the selected cover will never be less than 0 or higher than the last cover. Add the following code to the flowControl_MouseWheel event handler.
[Visual Basic] Dim i As Integer = -(e.Delta \ 120) Dim index As Integer = flowControl.SelectedIndex + i If index < 0 Then flowControl.First() ElseIf index > flowControl.Items.Count 1 Then flowControl.Last() Else flowControl.SelectedIndex = index End If

b.

c.

[Visual C#] int i = -(e.Delta / 120); int index = flowControl.SelectedIndex + i; if (index < 0) { flowControl.First(); } else if (index > flowControl.Items.Count - 1) { flowControl.Last(); } else { flowControl.SelectedIndex = index; }

5.

Save the changes.

Task 3: Test the mouse wheel interaction.


1. Run the application.

Lab Answer Key: Accessing Hardware in Silverlight Applications

2. 3.

Press Ctrl+F5.

Click the flow control, point to the categories it contains, and then use the mouse wheel to navigate back and forth through the categories. Close Internet Explorer.

Lab Answer Key: Accessing Hardware in Silverlight Applications

Exercise 2: Interacting with the Keyboard


Task 1: Configure the keyboard event handler.
1. Append code to the Page_Loaded or Home_Loaded event handler to add an event handler for the KeyDown event of the current object. Append the following code to the Page_Loaded or Home_Loaded event handler.
[Visual Basic] AddHandler Me.KeyDown, AddressOf flowControl.OnKeyDown

[Visual C#] this.KeyDown += flowControl.OnKeyDown;

2.

In the GreetingCardConsumer project, open the CoverFlowControl code file. In the Solution Explorer window, double-click CoverFlowControl.vb or CoverFlowControl.cs.

3.

Locate the OnKeyDown event handler. Notice the code in the OnKeyDown event handler, which handles the cursor keys for navigating through the covers.

[Visual Basic] Public Shadows Sub OnKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) If e.Key = Key.Right OrElse e.Key = Key.Down OrElse e.Key = Key.PageDown Then NextItem() e.Handled = True ElseIf e.Key = Key.Left OrElse e.Key = Key.Up OrElse e.Key = Key.PageUp Then PreviousItem() e.Handled = True ElseIf e.Key = Key.Home OrElse e.Key = Key.Q Then First() e.Handled = True ElseIf e.Key = Key.End OrElse e.Key = Key.E Then Last() e.Handled = True End If End Sub

[Visual C#] public void OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Right || e.Key == Key.Down || e.Key == Key.PageDown) { NextItem(); e.Handled = true; } else if (e.Key == Key.Left || e.Key == Key.Up || e.Key == Key.PageUp) { PreviousItem(); e.Handled = true; } else if (e.Key == Key.Home || e.Key == Key.Q) { First(); e.Handled = true; } else if (e.Key == Key.End || e.Key == Key.E)

Lab Answer Key: Accessing Hardware in Silverlight Applications

{ }

Last(); e.Handled = true;

4.

Locate the IndexSelected method that accepts three arguments, and add code at the top of the method to set focus to the current object. Add the following code at the top of the IndexSelected method.
[Visual Basic] ' Set focus so it receives key events Me.Focus()

[Visual C#] // Set focus so it receives key events this.Focus();

5.

Save the changes.

Task 2: Test the keyboard interaction.


1. Run the application. 2. Press Ctrl+F5.

Use the Down, Up, Right, and Left cursor keys to navigate through the card categories in the coverflow control. The Page control cannot receive focus, so it does not receive the keyboard input. The Home control is of type Page.

3.

Click the coverflow control. The coverflow control can receive focus, so it receives the keyboard input.

4. 5.

Use the Down, Up, Right, and Left cursor keys to navigate through the card categories in the coverflow control. Click the Set Default button. The Button control can receive focus, so it receives the keyboard input.

6. 7. 8. 9.

Use the Page Up and Page Down keys to navigate through the card categories in the coverflow control. Use the Home and End keys to navigate through the card categories in the coverflow control. Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Answer Key: Globalization and Localization

Module 10
Lab Answer Key: Globalization and Localization
Contents:
Exercise 1: Globalizing an Application Exercise 2: Localizing an Application 2 6

Lab Answer Key: Globalization and Localization

Lab: Globalizing and Localizing Applications


Exercise 1: Globalizing an Application
Task 1: Internationalize GreetingCardConsumer Application.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod10\VB\Starter or D:\Labfiles\Mod10\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod10\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod10\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

Build the solution. On the Build menu, click Build Solution.

4.

In the GreetingCardConsumer project, open App.xaml. In the Solution Explorer window, double-click App.xaml.

5.

Notice the markup with ResourceWrapper defined:

<app:ResourceWrapper x:Key="ResourceWrapper" />

The sealed ResourceWrapper class is defined in the ResourceWrapper.vb or ResourceWrapper.cs file, located in the Helpers folder. The file is automatically generated when you create a Silverlight by using the Silverlight Business Application project template. 6. In the GreetingCardConsumer project, in the Helpers folder, open ResourceWrapper.vb or ResourceWrapper.cs. 7. In the Solution Explorer window, expand Helpers, and then double-click ResourceWrapper.vb or ResourceWrapper.cs.

In the ResourceWrapper.vb or ResourceWrapper.cs file, notice that two read-only properties exist, ApplicationStrings and SecurityQuestions. These two properties return the following shared/static member fields: _applicationStrings or applicationStrings, and _securityQuestions or securityQuestions. They are of type ApplicationStrings and SecurityQuestions. In the GreetingCardConsumer project, in the Assets\Resources folder, open ApplicationStrings.resx. In the Solution Explorer window, expand Assets, expand Resources, and then double-click ApplicationStrings.resx.

8.

The Resource Designer opens. 9. In the Resource Designer, notice the Name column, which holds the resource key, used for looking up a specific value, which is shown in the Value column. One example is the ApplicationName key, which has a current value of Greeting Card Consumer.

Lab Answer Key: Globalization and Localization

10. In the GreetingCardConsumer project, open MainPage.xaml. In the Solution Explorer window, double-click MainPage.xaml.

11. In the MainPage.xaml window, in the XAML view, locate the TextBlock control named ApplicationNameTextBlock.
<TextBlock x:Name="ApplicationNameTextBlock" Style="{StaticResource ApplicationNameStyle}" Text="{Binding ApplicationStrings.ApplicationName, Source={StaticResource ResourceWrapper}}"/>

12. Notice that the Text property is bound to the ApplicationStrings.ApplicationName property, found in the ResourceWrapper resource. When you build the application, the ApplicationStrings class is automatically generated by the resource compiler, from the resource files, .resx, making it accessible from within your application. 13. The two HyperlinkButton controls have also been bound to properties in the ApplicationStrings class, so at this stage, MainPage.xaml needs no further attention. 14. Close MainPage.xaml.

Task 2: Internationalize Home Page.


1. In the GreetingCardConsumer project, in the Views folder, open Home.xaml. 2. In the Solution Explorer window, expand Views, and then double-click Home.xaml.

Locate the StackPanel control.

<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center">

3.

In the StackPanel control, locate the copyButton control, and notice the Content property holds a static or hardcoded string, Copy. The same is true for the print and snapshotButton controls.

<Button Grid.Row="1" Grid.Column="1" Content="Copy" Height="23" HorizontalAlignment="Left" Name="copy" VerticalAlignment="Top" Width="75" />

4.

Add a resource file named HomeStrings.resx to the Assets/Resources folder. In the Solution Explorer window, right-click Resources, point to Add, and then click New Item. In the Add New Item GreetingCardConsumer dialog box, in the Installed Templates section, click General. In the middle pane, click Resources File. In the Name box, type HomeStrings.resx, and then click Add.

5.

Make the resources publicly available. In the Resource Designer, in the Access Modifier list, click Public.

6.

Set the custom tool namespace for the HomeStrings.resx file to an empty string (Visual Basic) or GreetingCardConsumer (Visual C#), by using the Properties window. In the Solution Explorer window, click HomeStrings.resx. In the Properties window, in the Custom Tool Namespace box, type an empty string or GreetingCardConsumer, and then press Enter.

7.

Build the solution.

Lab Answer Key: Globalization and Localization

8. 9.

On the Build menu, click Build Solution.

Switch back to the Resource Designer. Add a new resource string named CopyButton with a value of Copy. In the Resource Designer, in the Name column for the first and only row, type CopyButton, and in the Value column, type Copy.

10. Add a new resource string named PrintButton with a value of Print. In the Resource Designer, in the Name column for the second row, type PrintButton, and in the Value column, type Print.

11. Add a new resource string named SnapShotButton with a value of Set Default. In the Resource Designer, in the Name column for the third row, type SnapShotButton, and in the Value column, type Set Default.

12. Build the solution. On the Build menu, click Build Solution.

13. Switch to ResourceWrapper.vb or ResourceWrapper.cs. 14. Create a new shared/static member level field named _homeStrings or homeStrings of type HomeStrings. In the ResourceWrapper class, add the following code, immediately after the _securityQuestions or securityQuestions definition.
[Visual Basic] Private Shared _homeStrings = New HomeStrings()

[Visual C#] private static HomeStrings homeStrings = new HomeStrings();

15. Create a new read-only property named HomeStrings of type HomeStrings. The property must return the shared/static member variable _homeStrings or homeStrings. In the ResourceWrapper class, add the following code, immediately after the _securityQuestions or securityQuestions definition.
[Visual Basic] Public ReadOnly Property HomeStrings() As HomeStrings Get Return _homeStrings End Get End Property

[Visual C#] Public HomeStrings HomeStrings { get { return homeStrings; }

Lab Answer Key: Globalization and Localization

16. Switch to Home.xaml. 17. In the XAML view, modify the Content property of the copyButton control, so it contains the following value:
{Binding HomeStrings.CopyButton, Source={StaticResource ResourceWrapper}}

18. In the XAML view, modify the Content property of the printButton control, so it contains the following value:
{Binding HomeStrings.PrintButton, Source={StaticResource ResourceWrapper}}

19. In the XAML view, modify the Content property of the snapshotButton control, so it contains the following value:
{Binding HomeStrings.SnapShotButton, Source={StaticResource ResourceWrapper}}

20. Run the application. Press Ctrl+F5.

21. Check to see if the button captions contain the text from the resource files. 22. Close Internet Explorer.

Lab Answer Key: Globalization and Localization

Exercise 2: Localizing an Application


Task 1: Localize Home.xaml.
1. Add a resource file named HomeStrings.de-DE.resx to the Assets/Resources folder. a. b. c. d. 2. In the Solution Explorer window, right-click Resources, point to Add, and then click New Item. In the Add New Item GreetingCardConsumer dialog box, in the Installed Templates section, click General. In the middle pane, click Resources File. In the Name box, typeHomeStrings.de-DE.resx, and then click Add.

Make the resources publicly available. In the Resource Designer, in the Access Modifier list, click Public.

3.

Set the custom tool namespace for the HomeStrings.de-DE.resx file to an empty string (Visual Basic) or GreetingCardConsumer (Visual C#) by using the Properties window. In the Solution Explorer window, click HomeStrings.de-DE.resx. In the Properties window, in the Custom Tool Namespace box, type an empty string or GreetingCardConsumer, and then press Enter.

4.

Build the solution. On the Build menu, click Build Solution.

5. 6.

Switch back to the Resource Designer. Add a new resource string named CopyButton with a value of Kopieren. In the Resource Designer, in the Name column for the first and only row, type CopyButton, and in the Value column, type Kopieren.

7.

Add a new resource string named PrintButton with a value of Ausdrucken. In the Resource Designer, in the Name column for the second row, type PrintButton, and in the Value column, type Ausdrucken.

8.

Add a new resource string named SnapShotButton with a value of Standard. In the Resource Designer, in the Name column for the third row, type SnapShotButton, and in the Value column, type Standard.

9.

Build the solution. On the Build menu, click Build Solution.

Task 2: Set the default culture.


1. Open the Project Designer for the GreetingCardConsumer project. 2. In the Solution Explorer window, right-click GreetingCardConsumer, and then click Properties.

Set the default or neutral culture to English. a. b. On the Silverlight page, click Assembly Information. In the Assembly Information dialog box, in the Neutral Language list, click English, and then click OK.

Lab Answer Key: Globalization and Localization

3.

Save the changes.

Task 3: Force the culture to German.


1. In the GreetingCardConsumer project, open MainPage.xaml in Code view. 2. In the Solution Explorer window, right-click MainPage.xaml, and then click View Code.

In the constructor for the MainPage class, after the call to the InitializeComponent method add code to set the CurrentUICulture property of the current thread to a new CultureInfo object, based on the de-DE culture. In the MainPage.xaml.vb or MainPage.xaml.cs window, to the constructor, add the following code after the call to the InitializeComponent method.
[Visual Basic] System.Threading.Thread.CurrentThread.CurrentUICulture = New System.Globalization.CultureInfo("de-DE")

[Visual C#] System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de-DE");

3.

Run the application and notice that the resource values displayed in the Button controls have been localized. Press Ctrl+F5.

4. 5.

Close Internet Explorer. Close Visual Studio. You have now completed this lab.

Lab Answer Key: Implementing Network Communications

Module 11
Lab Answer Key: Implementing Network Communications
Contents:
Exercise 1: Consuming Initiation Parameters Exercise 2: Consuming Data by Using HTTPWebRequest Objects Exercise 3: Consuming Data by Using WebClient Objects Exercise 4: Sending and Receiving Data by Using Local Connections 2 5 8 10

Lab Answer Key: Implementing Network Communications

Lab: Building Dynamic Silverlight Applications


Exercise 1: Consuming Initiation Parameters
Task 1: Add initiation parameters to the hosting control for the GreetingCardConsumer application.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod11\VB\Starter or D:\Labfiles\Mod11\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod11\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod11\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

In the GreetingCardConsumer.Web project, open GreetingCardConsumerTestPage.aspx. In the Solution Explorer window, in the GreetingCardConsumer.Web project, double-click GreetingCardConsumerTestPage.aspx.

4.

Locate the following line of markup.

<param name="autoUpgrade" value="true" />

5.

Add a new line immediately after the located markup. Place the cursor at the end of the line you have just located, and then press Enter.

6.

Add the following markup to the empty line you have just created.

<param name="initParams" value="configXmlFileUri=http://localhost:2234/ClientBin/GreetingCardConfig.xml,colorXmlF ileUri=http://localhost:2234/ClientBin/GreetingCardColors.xml" />

Note 7. 8.

Add the markup in a single line.

Save the changes. In the GreetingCardConsumer.Web project, in the ClientBin folder, open GreetingCardColors.xml. a. b. In the GreetingCardConsumer.Web project, expand ClientBin. Double-click GreetingCardColors.xml and briefly review the contents of the file.

You will consume this data in Exercise 2. 9. In the GreetingCardConsumer.Web project, in the ClientBin folder, open GreetingCardConfig.xml. Double-click GreetingCardConfig.xml and briefly review the contents of the file.

Lab Answer Key: Implementing Network Communications

You will consume this data in Exercise 3.

Task 2: Retrieve the initiation parameters at run time and add them to the application Resources collection.
1. In the GreetingCardConsumer project, open App.xaml in Code view. 2. In the GreetingCardConsumer project, right-click App.xaml, and then click View Code.

Locate the following comment.

TODO: Read Init Params and add them to the Resources Collection

3.

Add code directly beneath the comment that checks if e.InitParams is not null, and if so, creates a new local variable name item of type Object/object. Subsequently, loop through the items in the e.InitParams collection and add them to the Resources collection by using the Add method, passing the Key and Value properties of the current item. Add the following code directly beneath the comment.

[Visual Basic] If Not IsNothing(e.InitParams) Then Dim item As Object For Each item In e.InitParams Me.Resources.Add(item.Key, item.Value) Next End If

[Visual C#] if (e.InitParams != null) { foreach (var item in e.InitParams) { this.Resources.Add(item.Key, item.Value); } }

4.

Save the changes.

Task 3: Retrieve the initiation parameters in a user control.


1. In the GreetingCardConsumer project, in the Views folder, open Home.xaml in Code view. 2. In the Solution Explorer window, expand Views, right-click Home.xaml, and then click View Code.

Locate the following comment in the Home_Loaded or Page_Loaded event handler.

TODO: Retrieve Init Params from the Resources Collection

3.

Directly beneath the comment you have just located, add code to create the following local variables, assigned specific initial values. Variable Type String/string Initial Value App.Current.Resources("colorXmlFileUri").

Variable Name colorSettingsUri

Lab Answer Key: Implementing Network Communications

Variable Name

Variable Type

Initial Value ToString() / App.Current.Resources["colorXmlFileUri"]. ToString()

categorySettingsUri

String/string

App.Current.Resources("configXmlFileUri"). ToString() / App.Current.Resources["configXmlFileUri"]. ToString()

Add the following code directly beneath the comment.

[Visual Basic] Dim colorSettingsUri As String = _ App.Current.Resources("colorXmlFileUri").ToString() Dim categorySettingsUri As String = _ App.Current.Resources("configXmlFileUri").ToString()

[Visual C#] string colorSettingsUri = App.Current.Resources["colorXmlFileUri"].ToString(); string categorySettingsUri = App.Current.Resources["configXmlFileUri"].ToString();

4.

Add code immediately after the previously added code, to show the value of the colorSettingsUri and categorySettingsUri variables, each in a separate message box. Add the following code immediately after the previously added code.

[Visual Basic] MessageBox.Show(colorSettingsUri) MessageBox.Show(categorySettingsUri)

[Visual C#] MessageBox.Show(colorSettingsUri); MessageBox.Show(categorySettingsUri);

5. 6.

Save the changes. Run the application. Press Ctrl+F5.

Two message boxes should be displayed showing the URLs you will use later in the lab. Take a note of these URLs. 7. Close Internet Explorer and switch back to Visual Studio 2010.

Lab Answer Key: Implementing Network Communications

Exercise 2: Consuming Data by Using HTTPWebRequest Objects


Task 1: Call an asynchronous HTTP request to read XML data.
1. Add code to create a local variable named httpRequest of type HttpWebRequest and assign the value returned by the following method call. The code must replace the two calls to the MessageBox.Show method in the Home_Loaded or Page_Loaded event handler.

[Visual Basic] HttpWebRequest.Create( _ New Uri(colorSettingsUri, UriKind.Absolute))

[Visual C#] (HttpWebRequest) HttpWebRequest.Create(new Uri(colorSettingsUri, UriKind.Absolute));

In the Home_Loaded or Page_Loaded event handler, select the two calls to the MessageBox.Show method, and replace with the following code.

[Visual Basic] Dim httpRequest As HttpWebRequest = HttpWebRequest.Create( _ New Uri(colorSettingsUri, UriKind.Absolute))

[Visual C#] HttpWebRequest httpRequest = (HttpWebRequest) HttpWebRequest.Create(new Uri(colorSettingsUri, UriKind.Absolute));

2.

In the Home_Loaded or Page_Loaded event handler, append code to call the BeginGetResponse method of the httpRequest object. Pass in a new AsyncCallback object with the httpRequest_CallBack method and the httpRequest object. In the Home_Loaded or Page_Loaded event handler, append the following code.

[Visual Basic] httpRequest.BeginGetResponse(New AsyncCallback(AddressOf _ httpRequest_CallBack), httpRequest)

[Visual C#] httpRequest.BeginGetResponse(new AsyncCallback (httpRequest_CallBack), httpRequest);

Task 2: Create a callback method for the asynchronous HTTP request.


1. Create a new member variable named settings of type String/string and assign an empty string. Add the variable declaration after the Home_Loaded or Page_Loaded event handler. Add the following variable declaration after the Home_Loaded or Page_Loaded event handler.

[Visual Basic] Private settings As String = String.Empty

Lab Answer Key: Implementing Network Communications

[Visual C#] string settings = string.Empty;

2.

Add the following method after the variable declaration you have just added.

[Visual Basic] Sub httpRequest_CallBack(ByVal result As IAsyncResult) Dim httpRequest As HttpWebRequest = result.AsyncState Dim httpResponse As HttpWebResponse = _ httpRequest.EndGetResponse(result) Dim strmReader As StreamReader = _ New StreamReader(httpResponse.GetResponseStream()) Using (strmReader) settings = strmReader.ReadToEnd() End Using Dispatcher.BeginInvoke(AddressOf setColors) End Sub

[Visual C#] void httpRequest_CallBack(IAsyncResult result) { HttpWebRequest httpRequest = (HttpWebRequest) result.AsyncState; HttpWebResponse httpResponse = (HttpWebResponse) httpRequest.EndGetResponse(result); using (StreamReader strmReader = new StreamReader(httpResponse.GetResponseStream())) { settings = strmReader.ReadToEnd(); } } Dispatcher.BeginInvoke(setColors);

Task 3: Create a function that updates the user interface from the main UI thread.
1. Add the following method after the method you have just added.
[Visual Basic] Sub setColors() Dim xDoc As XDocument = XDocument.Parse(settings) Dim root As XElement = xDoc.Root Dim bannerColor As String = String.Empty Dim backgroundColor As String = String.Empty Dim playerSettings As XElement = root.Element("PLAYERSETTINGS") Dim colorSettings As XElement = _ playerSettings.Element("COLORSETTINGS") If Not IsNothing(colorSettings.Attribute("bannerColor")) Then bannerColor = colorSettings.Attribute("bannerColor").Value End If If Not IsNothing(colorSettings.Attribute("backgroundColor")) Then backgroundColor = _ colorSettings.Attribute("backgroundColor").Value End If Dim bannerCol As SolidColorBrush = _ New SolidColorBrush(makeColor(bannerColor))

Lab Answer Key: Implementing Network Communications

Dim backgroundCol As SolidColorBrush = _ New SolidColorBrush(makeColor(backgroundColor)) App.NavigationGrid.Background = bannerCol App.LayoutRoot.Background = backgroundCol End Sub

[Visual C#] void setColors() { XDocument xDoc = XDocument.Parse(settings); XElement root = xDoc.Root; string bannerColor = string.Empty; string backgroundColor = string.Empty; XElement playerSettings = root.Element("PLAYERSETTINGS"); XElement colorSettings = playerSettings.Element("COLORSETTINGS"); if (colorSettings.Attribute("bannerColor") != null) { bannerColor = colorSettings.Attribute("bannerColor").Value; } if (colorSettings.Attribute("backgroundColor") != null) { backgroundColor = colorSettings.Attribute("backgroundColor").Value; } SolidColorBrush bannerCol = new SolidColorBrush(makeColor(bannerColor)); SolidColorBrush backgroundCol = new SolidColorBrush(makeColor(backgroundColor)); App.NavigationGrid.Background = bannerCol; App.LayoutRoot.Background = backgroundCol;

2.

Review the function named makeColor that already exists in the class in which you have been working. Your code calls this function to convert the hexadecimal string data into a .NET color. Silverlight does not have methods for converting hexadecimal string data into a .NET color, so this function has been provided for you as part of the starter solution.

3. 4.

Save the changes. Run and test the application. Press Ctrl+F5.

The section at the top of the Silverlight application is now orange and the background of the main section is grey. 5. Close Internet Explorer and switch back to Visual Studio 2010.

Lab Answer Key: Implementing Network Communications

Exercise 3: Consuming Data by Using WebClient Objects


Task 1: Call an asynchronous WebClient request to read XML data.
1. After the existing code in the Home_Loaded or Page_Loaded event handler, perform the following tasks: a. b. c. d. Declare and instantiate a new instance of a WebClient object, named webClient. Add code to add a new event handler for the DownloadStringCompleted event for the WebClient object. Add code that creates a new absolute URI based on the GreetingCardConfig.xml file that you stored in a string variable in Task 3 of Exercise 1. Call the DownloadStringAsync method of the WebClient object to initiate communication with the URI you have just constructed. Append the following code in the Home_Loaded or Page_Loaded event handler.

[Visual Basic] Dim webClient As WebClient = New WebClient() AddHandler webClient.DownloadStringCompleted, _ AddressOf webClient_DownloadStringCompleted Dim xmlUri As Uri = New Uri(categorySettingsUri, UriKind.Absolute) webClient.DownloadStringAsync(xmlUri)

[Visual C#] WebClient webClient = new WebClient(); webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted); Uri xmlUri = new Uri(categorySettingsUri, UriKind.Absolute); webClient.DownloadStringAsync(xmlUri);

2.

Save the changes.

Task 2: Create the DownloadStringCompleted event handler for the WebClient.


1. Add the following code immediately after the Home_Loaded or Page_Loaded event handler.
[Visual Basic] Sub webClient_DownloadStringCompleted(ByVal sender As Object, _ ByVal e As DownloadStringCompletedEventArgs) If Not IsNothing(e.Error) Then MessageBox.Show("There was an error retrieving xml") Return End If Dim xDoc As XDocument = XDocument.Parse(e.Result) Dim root As XElement = xDoc.Root Dim appTitle As String = String.Empty If Not IsNothing(root.Attribute("title")) Then appTitle = root.Attribute("title").Value App.ApplicationNameTextBlock.Text = appTitle End If End Sub

Lab Answer Key: Implementing Network Communications

[Visual C#] void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("There was an error retrieving xml"); } return;

XDocument xDoc = XDocument.Parse(e.Result); XElement root = xDoc.Root; string appTitle = string.Empty; if (root.Attribute("title") != null) { appTitle = root.Attribute("title").Value; App.ApplicationNameTextBlock.Text = appTitle; }

2. 3.

Save the changes. Run and test the application. Press Ctrl+F5.

The application displays the text Greeting Card! This text was retrieved from the GreetingCardConfig.xml file. You will work with the rest of the XML data that was retrieved in subsequent labs. 4. Close Internet Explorer and switch back to Visual Studio 2010.

10

Lab Answer Key: Implementing Network Communications

Exercise 4: Sending and Receiving Data by Using Local Connections


Task 1: Add controls for sending and receiving messages to About.xaml.
1. In the GreetingCardConsumer project, in the Views folder, open About.xaml. 2. 3. In the GreetingCardConsumer project, expand Views, and then double-click About.xaml.

In the XAML pane, locate the StackPanel element. Add the following markup between the opening and closing tags of the StackPanel element.

<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Instant Communications"/> <TextBox x:Name="imContent" Width="400" Height="200" HorizontalAlignment="Left"></TextBox> <TextBlock x:Name="imReceived" Width="400" Height="200" HorizontalAlignment="Left"></TextBlock>

4.

Create an event handler for the KeyUp event of the imContent TextBox control. a. b. Place the cursor in the markup for the imContent TextBox element. In the Properties window, click Events, and then double-click KeyUp.

Visual Studio creates an event handler stub for the KeyUp event. 5. 6. Leave the current instance of Visual Studio running. Open a second instance of Visual Studio. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

A second instance of Visual Studio appears. 7. Open the GreetingCardManagement solution from the D:\Labfiles\Mod11\VB\Starter or D:\Labfiles\Mod11\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod11\VB\Starter\ GreetingCardManagement.sln or D:\Labfiles\Mod11\CS\Starter\ GreetingCardManagement.sln, and then click Open.

8.

In the GreetingCardManagement project, in the Views folder, open About.xaml. In the GreetingCardManagement project, expand Views, and then double-click About.xaml.

9.

In the XAML pane, locate the StackPanel element.

10. Add the following markup between the opening and closing tags of the StackPanel element, replacing the existing content.
<TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Instant Communications"/> <TextBox x:Name="imContent" Width="400" Height="200" HorizontalAlignment="Left" KeyUp="imContent_KeyUp"></TextBox> <TextBlock x:Name="imReceived" Width="400" Height="200" HorizontalAlignment="Left"></TextBlock>

11. Leave both instances of Visual Studio running.

Lab Answer Key: Implementing Network Communications

11

Task 2: Add code for sending and receiving messages to the GreetingCardConsumer application.
1. 2. Switch to the instance of Visual Studio that has the GreetingCardConsumer solution open. Ensure that you are viewing the code file for About.xaml. Bring the System.Windows.Messaging namespace into scope. Add the following code at the top of the About.xaml.vb or About.xaml.cs file.

[Visual Basic] Imports System.Windows.Messaging

[Visual C#] using System.Windows.Messaging;

3.

Above the imContent_KeyUp event handler, declare the following member variables and instantiate them by passing the constructor values indicated. Type LocalMessageSender LocalMessageReceiver Constructor Value GreetingCardConsumer GreetingCardManagement

Name msgSender msgReceiver

Add the following code immediately above the imContent_KeyUp event handler.

[Visual Basic] Private msgSender As LocalMessageSender = New LocalMessageSender("GreetingCardConsumer") Private msgReceiver As LocalMessageReceiver = New LocalMessageReceiver("GreetingCardManagement")

[Visual private new private new

C#] LocalMessageSender msgSender = LocalMessageSender("GreetingCardConsumer"); LocalMessageReceiver msgReceiver = LocalMessageReceiver("GreetingCardManagement");

4.

Create a new event handler named msgReceiver_MessageReceived, with the standard event handler signature, accepting an argument named sender of type Object/object, and an argument named e of type MessageReceivedEventArgs. Place the event handler immediately below the imContent_KeyUp event handler. Add the following code immediately below the imContent_KeyUp event handler.

[Visual Basic] Sub msgReceiver_MessageReceived(sender As Object, e As MessageReceivedEventArgs) imReceived.Text = e.Message End Sub

[Visual C#] void msgReceiver_MessageReceived(object sender, MessageReceivedEventArgs e)

12

Lab Answer Key: Implementing Network Communications

{ }

imReceived.Text = e.Message;

5.

Add code to the imContent_KeyUp event handler to call the SendAsync method of the msgSender object, passing the value of the imContent.Text property. Add the following code to the imContent_KeyUp event handler.

[Visual Basic] msgSender.SendAsync(imContent.Text)

[Visual C#] msgSender.SendAsync(imContent.Text);

6.

Add code to the OnNavigatedTo event handler to map an event handler named msgReceiver_MessageReceived to the MessageReceived method of the msgReceiver, and then call the Listen method of the msgReceiver object. Add the following code to the OnNavigatedTo event handler.

[Visual Basic] AddHandler msgReceiver.MessageReceived, AddressOf msgReceiver_MessageReceived msgReceiver.Listen()

[Visual C#] msgReceiver.MessageReceived += new System.EventHandler<MessageReceivedEventArgs>(msgReceiver_MessageReceived); msgReceiver.Listen();

7.

Save the changes.

Task 3: Add code for sending and receiving messages to the GreetingCardManagement application.
1. 2. Switch to the instance of Visual Studio that has the GreetingCardManagement solution open. Ensure that you are viewing the code file for About.xaml. Above the imContent_KeyUp event handler, declare the following member variables and instantiate them by passing the constructor values indicated. Type LocalMessageSender LocalMessageReceiver Constructor Value GreetingCardManagement GreetingCardConsumer

Name msgSender msgReceiver

Add the following code immediately above the imContent_KeyUp event handler.

[Visual Basic] Private msgSender As LocalMessageSender = New LocalMessageSender("GreetingCardManagement") Private msgReceiver As LocalMessageReceiver = New LocalMessageReceiver("GreetingCardConsumer")

Lab Answer Key: Implementing Network Communications

13

[Visual private new private new

C#] LocalMessageSender msgSender = LocalMessageSender("GreetingCardManagement"); LocalMessageReceiver msgReceiver = LocalMessageReceiver("GreetingCardConsumer");

Note that these names are the opposite of the messages you defined in Task 2. This enables the two applications to communicate with each other over two well-defined connections. 3. Build the solution. On the Build menu, click Build Solution.

Task 4: Test the communications over the local connections.


1. 2. Ensure that the current instance of Visual Studio has the GreetingCardManagement solution open. Run the application. Press Ctrl+F5.

Internet Explorer starts and displays the application. 3. 4. 5. 6. Click About. Leave Internet Explorer running. Switch to the instance of Visual Studio that has the GreetingCardConsumer solution open. Run the application. Press Ctrl+F5.

Internet Explorer starts and displays the application. 7. 8. 9. Click About. Arrange the two Internet Explorer windows so that they are side-by-side. In the instance of Internet Explorer that has the Greeting Card Consumer application running, in the text box, type Help! Note that the text Help! is displayed in the GreetingCard Management application. 10. In the GreetingCard Management application, in the text box, type OK! Note that the text OK! is displayed in the GreetingCard Consumer application. 11. Close all applications. You have now completed this lab.

Lab Answer Key: Deploying Silverlight Applications

Module 12
Lab Answer Key: Deploying Silverlight Applications
Contents:
Exercise 1: Adding Application Features Exercise 2: Loading Resources Dynamically 2 10

Lab Answer Key: Deploying Silverlight Applications

Lab: Deploying Silverlight Applications


Exercise 1: Adding Application Features
Task 1: Ensure that the application runs out-of-browser.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the GreetingCardConsumer solution from the D:\Labfiles\Mod12\VB\Starter or D:\Labfiles\Mod12\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod12\VB\Starter\ GreetingCardConsumer.sln or D:\Labfiles\Mod12\CS\Starter\ GreetingCardConsumer.sln, and then click Open.

3.

Open the Project Designer for the GreetingCardConsumer project. In the Solution Explorer window, right-click GreetingCardConsumer, and then click Properties.

4.

Enable the application to run outside the browser. In the Project Designer, on the Silverlight page, ensure that the Enable running application out of the browser check box is selected.

Task 2: Require elevated trust for the application.


1. Ensure that the application has elevated trust when running outside the browser. a. b. 2. In the Project Designer, on the Silverlight page, click Out-of-Browser Settings. In the Out-of-Browser Settings dialog box, select the Require elevated trust when running outside the browser check box, and then click OK.

Close the Project Designer.

Task 3: Add network check.


1. In the GreetingCardConsumer project, open MainPage.xaml in Code view. 2. In the GreetingCardConsumer project, right-click MainPage.xaml, and then click View Code.

To the MainPage class, add a private shared/static event handler named OnNetworkChange, with the standard .NET Framework event handler signature. To the MainPage class, add the following code.
[Visual Basic] Private Shared Sub OnNetworkChange(ByVal sender As Object, ByVal e As EventArgs) End Sub

[Visual C#] private static void OnNetworkChange(object sender, System.EventArgs e) {

Lab Answer Key: Deploying Silverlight Applications

3.

Bring the System.Net.NetworkInformation namespace into scope. To the MainPage.xaml.vb or MainPage.xaml.cs file, add the following code at the top of the file, below other Imports or using statements.
[Visual Basic] Imports System.Net.NetworkInformation

[Visual C#] using System.Net.NetworkInformation;

4.

To the MainPage class constructor, append code to map the event handler method named OnNetworkChange to the NetworkChange.NetworkAddressChanged event. To the MainPage class constructor, append the following code.
[Visual Basic] AddHandler NetworkChange.NetworkAddressChanged, AddressOf OnNetworkChange

[Visual C#] NetworkChange.NetworkAddressChanged += OnNetworkChange;

Task 4: Display toast notification on network change.


1. Add a private shared/static member variable named notificationWnd, of type NotificationWindow, to the MainPage class. To the MainPage class, add the following code.
[Visual Basic] ' Create notification window Private Shared notificationWnd As NotificationWindow

[Visual C#] // Create notification window private static NotificationWindow notificationWnd;

2.

Add code to the MainPage class constructor in an If...Then/if construct to check if the application is currently out-of-browser. If the application is currently running out-of-browser, add a check to see if the notificationWnd object is null, and if it is, instantiate it as a NotificationWindow object. Add the code before the event handler is added. To the MainPage class constructor, add the following code, before adding the event handler.

Lab Answer Key: Deploying Silverlight Applications

[Visual Basic] ' Are we running outside browser? If App.Current.IsRunningOutOfBrowser Then If notificationWnd Is Nothing Then notificationWnd = New NotificationWindow End If End If

[Visual C#] // Are we running outside browser? if (App.Current.IsRunningOutOfBrowser) { if (notificationWnd == null) notificationWnd = new NotificationWindow(); }

3.

To the OnNetworkChange method in an If...Then/if construct, add a local variable named message, of type String/string, and add a check to see if the application is currently running out-of-browser. To the OnNetworkChange method, add the following code.
[Visual Basic] Dim message As String ' Are we running outside browser? If App.Current.IsRunningOutOfBrowser Then End If

[Visual C#] string message = string.Empty; // Are we running outside browser? if (App.Current.IsRunningOutOfBrowser) { }

4.

To the OnNetworkChange method in the If...Then/if construct, add code to check if the notificationWnd object is currently visible by comparing the Visibility property with the System.Windows.Visibility.Visible enum member value. If it is visible, close the notificationWnd object to prevent an exception being thrown. To the OnNetworkChange method in the If...Then/if construct, add the following code.
[Visual Basic] ' Is the notification window visible? If notificationWnd.Visibility = Visibility.Visible Then ' Close notification window notificationWnd.Close() End If

Lab Answer Key: Deploying Silverlight Applications

[Visual C#] // Is the notification window visible? if (notificationWnd.Visibility == Visibility.Visible) { // Close notification window notificationWnd.Close(); }

5.

To the OnNetworkChange method in an If...Then...Else/if...else construct, add code to check if a network is available. Append the code to the existing If...Then/if construct that checks if the application is running out-of-browser. Set the value of the message variable to indicate if a network is available. To the OnNetworkChange method, append the following code to the existing If...Then/if construct that checks if the application is running out-of-browser.
[Visual Basic] If NetworkInterface.GetIsNetworkAvailable Then ' Set text to display message = "Network is available." Else ' Set text to display message = "Network is unavailable." End If

[Visual C#] if (NetworkInterface.GetIsNetworkAvailable()) { // Set text to display message = "Network is available."; } else { // Set text to display message = "Network is unavailable."; }

6.

Save the changes.

Task 5: Add new UserControl.


1. Add a new UserControl named NetworkChangeNotification to the GreetingCardConsumer project in the Views folder. a. b. c. 2. In the Solution Explorer window, under GreetingCardConsumer, right-click Views, point to Add, and then click New Item. In the Add New Item GreetingCardConsumer dialog box, in the list of project items, click Silverlight User Control. In the Name box, type NetworkChangeNotification, and then click Add.

In the NetworkChangeNotification.xaml window, set the Width property of the Grid control to 200, and the Height property to 50. To the opening Grid tag, add the following markup, to ensure that the size of the notification window is within the allowed maximum size.

Lab Answer Key: Deploying Silverlight Applications

Width="200" Height="50"

3.

In the NetworkChangeNotification.xaml window, to the Grid control, add a self-closing TextBlock element, which is centered both horizontally and vertically. Bind the Text property, without specifying the exact binding. In the Grid element, add the following markup.
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}" />

4. 5. 6.

Save the changes. Switch to MainPage.xaml in Code view. [Visual C# only] Bring the GreetingCardConsumer.Views namespace into scope. Add the following code at the beginning of the namespace declaration.
[Visual C#] using GreetingCardConsumer.Views;

7.

Build the solution. On the Build menu, click Build Solution.

8.

To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to instantiate a new object of type NetworkChangeNotification, named nwWindow. Set the Content property of the notificationWnd object to the nwWindow object. To the OnNetworkChange method, append the following code to the existing If...Then/if construct that checks if the application is running out-of-browser.
[Visual Basic] ' Create and instantiate new window Dim nwWindow As New NetworkChangeNotification() notificationWnd.Content = nwWindow

[Visual C#] // Create and instantiate new window NetworkChangeNotification nwWindow = new NetworkChangeNotification(); notificationWnd.Content = nwWindow;

9.

To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to set the Content.DataContext property of the notificationWnd object to the message variable. This way, you can programmatically set the correct message to appear, without using different windows/user controls. In addition, set the Height and Width properties to the corresponding values of the LayoutRoot object of the nwWindow object. This will ensure that your notification window has the same size as the UserControl you just created. Note that you need to use the Height and Width of the LayoutRoot, which in this case is the Grid control in the UserControl, because the Height and Width of the UserControl is not accessible at this stage because the UserControl is not displayed.

Lab Answer Key: Deploying Silverlight Applications

To the OnNetworkChange method, append the following code to the existing If...Then/if construct that checks if the application is running out-of-browser.
[Visual Basic] ' Set notification message notificationWnd.Content.DataContext = message ' Set notification window size notificationWnd.Height = nwWindow.LayoutRoot.Height notificationWnd.Width = nwWindow.LayoutRoot.Width

[Visual C#] // Set notification message notificationWnd.Content.DataContext = message; // Set notification window size notificationWnd.Height = nwWindow.LayoutRoot.Height; notificationWnd.Width = nwWindow.LayoutRoot.Width;

10. To the OnNetworkChange method, append code to the If...Then/if construct that checks if the application is running out-of-browser to show the notificationWnd object for 5 seconds, and then activate the MainWindow of the current application. To the OnNetworkChange method, append the following code to the existing If...Then/if construct that checks if the application is running out-of-browser.
[Visual Basic] ' Show for 5 seconds notificationWnd.Show(5000) ' Keep focus to the application window App.Current.MainWindow.Activate()

[Visual C#] // Show for 5 seconds notificationWnd.Show(5000); // Keep focus to the application window App.Current.MainWindow.Activate();

Task 6: Test the notification window.


1. Run the application. 2. Press Ctrl+F5.

Install the application with default settings. a. b. In Internet Explorer, right-click the application background, and then click Install GreetingCardConsumer Application onto this computer. In the Security Warning dialog box, click Install.

3. 4.

Close Internet Explorer. Open the Settings window for the Hyper-V guest. In the 10554A-SEA-DEV on localhost Virtual Machine Connection window, on the File menu, click Settings.

Lab Answer Key: Deploying Silverlight Applications

5.

Arrange the Hyper-V guest and the Settings windows so that you can see the system tray of Hyper-V guest in the right lower-most corner of your screen, and the Settings window in the left upper-most corner. If the windows overlap, arrange the Settings window on top of the Hyper-V guest window. In the Settings window, change the network adapter from Private Network to Not connected. a. b. In the Settings for 10554A-SEA-DEV window, in the Hardware list, click Network Adapter. In the Network Adapter area, in the Network list, click Not connected, and then click Apply.

6.

7. 8.

Notice the toast notification being displayed for 5 seconds as the network connection is now unavailable. In the Settings window, change the network adapter from Not connected to Private Network. a. b. In the Settings for 10554A-SEA-DEV window, in the Hardware list, click Network Adapter. In the Network Adapter area, in the Network list, click Private Network, and then click Apply.

9.

Notice the toast notification being displayed for 5 seconds as the network connection is available again.

Lab Answer Key: Deploying Silverlight Applications

10. Close the Settings window. In the Settings for 10554A-SEA-DEV window, click OK.

11. Uninstall the application. a. b. In the GreetingCardConsumer Application window, right-click the application background, and then click Remove this application. In the Remove this application dialog box, click Yes.

10

Lab Answer Key: Deploying Silverlight Applications

Exercise 2: Loading Resources Dynamically


Task 1: Enable assembly caching.
1. Open the Project Designer for the GreetingCardConsumer project. 2. In the Solution Explorer window, right-click GreetingCardConsumer, and then click Properties.

Disable the application to run outside the browser. In the Project Designer, on the Silverlight page, clear the Enable running application out of the browser check box.

3.

Enable assembly caching. In the Project Designer, on the Silverlight page, select the Reduce XAP size by using application library caching check box.

4. 5.

Save the changes. Close the Project Designer.

Task 2: Add external resources.


1. Add a new Silverlight Class Library project, named FabrikamLibrary, to the solution. The library will contain the external resources to be loaded on demand. a. b. c. d. 2. In the Solution Explorer window, right-click Solution 'GreetingCardConsumer' (2 projects), point to Add, and then click New Project. In the Add New Project dialog box, in the Installed Templates section, expand Visual Basic or Visual C#, and then click Silverlight. In the list of project templates, click Silverlight Class Library, in the Name box, type FabrikamLibrary, and then click OK. In the Add Silverlight Class Library dialog box, ensure that Silverlight 4 is selected in the Silverlight Version list, and then click OK.

Delete the default code file Class1. a. b. In the Solution Explorer window, under FabrikamLibrary, right-click Class1, and then click Delete. In the Microsoft Visual Studio message box, click OK.

3.

Add the existing DynamicPage.xaml file to the FabrikamLibrary project. The file is located in the Starter folder. a. b. In the Solution Explorer window, right-click FabrikamLibrary, point to Add, and then click Existing Item. In the Add Existing Item - FabrikamLibrary dialog box, in the File name box type D:\Labfiles\Mod12\VB\Starter\DynamicPage.xaml or D:\Labfiles\Mod12\CS\Starter\DynamicPage.xaml, and then click Add.

4.

In the FabrikamLibrary project, add a reference to the System.Windows.Controls.Navigation assembly. a. In the Solution Explorer window, right-click FabrikamLibrary, and then click Add Reference.

Lab Answer Key: Deploying Silverlight Applications

11

b. 5.

In the Add Reference dialog box, in the list, select System.Windows.Controls.Navigation, and then click OK.

Open the DynamicPage.xaml page. In the Solution Explorer window, under FabrikamLibrary, double-click DynamicPage.xaml.

6.

Examine the DynamicPage.xaml page content. Notice the value of the Text property of the TextBlock element named ContentText. Notice the use of various styles that do not exist in the current project. Build the FabrikamLibrary project. In the Solution Explorer window, right-click FabrikamLibrary, and then click Build.

7.

8.

Copy the output assembly, FabrikamLibrary.dll, from the D:\Labfiles\Mod12\VB\Starter\FabrikamLibrary\Bin\Debug or D:\Labfiles\Mod12\CS\Starter\FabrikamLibrary\Bin\Debug folder to the ClientBin folder in the root of the GreetingCardConsumer.Web project by using Windows Explorer. a. b. Open Windows Explorer. Navigate to the D:\Labfiles\Mod12\VB\Starter\FabrikamLibrary\Bin\Debug or D:\Labfiles\Mod12\CS\Starter\FabrikamLibrary\Bin\Debug folder, select FabrikamLibrary.dll, and then press Ctrl+C. Navigate to the D:\Labfiles\Mod12\VB\Starter\GreetingCardConsumer.Web\ClientBin or D:\Labfiles\Mod12\CS\Starter\GreetingCardConsumer.Web\ClientBin folder, and then press Ctrl+V.

c.

Task 3: Set up assembly on demand loading.


1. 2. In the GreetingCardConsumer project, open Views\Home.xaml in Code view. Bring the System.Reflection namespace into scope. To the Home.xaml.vb or Home.xaml.cs file, add the following code at the top of the file, below other Imports or using statements.
[Visual Basic] Imports System.Reflection

[Visual C#] using System.Reflection;

3.

To the Home class, append a private event handler named wClient_OpenReadCompleted, with the standard .NET Framework event handler signature; an argument named sender, of type Object/object, and an argument named e, of type OpenReadCompletedEventArgs. The event handler will handle the download of the assembly from the hosting web application. To the Home class, append the following code.
[Visual Basic] Private Sub wClient_OpenReadCompleted(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs) End Sub

12

Lab Answer Key: Deploying Silverlight Applications

[Visual C#] private void wClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { }

4.

To the wClient_OpenReadCompleted method in an If...Then/if construct, check if the user did not cancel the download by examining the e.Cancelled property. To the wClient_OpenReadCompleted method, add the following code.
[Visual Basic] If Not e.Cancelled Then End If

[Visual C#] if (!e.Cancelled) { }

5.

To the wClient_OpenReadCompleted method in the If...Then/if construct, add code to create and instantiate a variable named assmPart, of type AssemblyPart, and create a variable named assmbly, of type Assembly. Use the Load method of the assmPart object to assign the downloaded assembly to assmbly. Pass e.Result to the Load method. To the wClient_OpenReadCompleted method in the If...Then/if construct, add the following code.
[Visual Basic] ' Load assembly Dim assmPart As New AssemblyPart() Dim assmbly As Assembly = assmPart.Load(e.Result)

[Visual C#] // Load assembly AssemblyPart assmPart = new AssemblyPart(); Assembly assmbly = assmPart.Load(e.Result);

6.

To the wClient_OpenReadCompleted method in the If...Then/if construct, append code to load the DynamicPage.xaml file from the loaded assembly. Use the Application.LoadComponent method and pass the current object and a new System.Uri object with the following relative URI: /FabrikamLibrary;component/DynamicPage.xaml To the wClient_OpenReadCompleted method in the If...Then/if construct, append the following code.
[Visual Basic] ' Load component from assembly in current app domain Application.LoadComponent(Me, New System.Uri( "/FabrikamLibrary;component/DynamicPage.xaml", System.UriKind.Relative)) Me.LayoutRoot = CType(Me.FindName("LayoutRoot"), System.Windows.Controls.Grid)

Lab Answer Key: Deploying Silverlight Applications

13

[Visual C#] // Load component from assembly in current app domain Application.LoadComponent(this, new System.Uri( "/FabrikamLibrary;component/DynamicPage.xaml", System.UriKind.Relative)); this.LayoutRoot = ((System.Windows.Controls.Grid) (this.FindName("LayoutRoot")));

7. 8.

Locate the Home_Loaded or Page_Loaded event handler method. Append code to the Home_Loaded or Page_Loaded method, to create and instantiate a variable named wClient, of type WebClient. Append the code to the existing If...Then/if construct. To the Home_Loaded or Page_Laded method, append the following code. Append the code to the existing If...Then/if construct.

[Visual

Basic] ' Create and instantiate WebClient object Dim wClient As New WebClient()

[Visual C#] // Create and instantiate WebClient object WebClient wClient = new WebClient();

9.

Append code to the Home_Loaded or Page_Loaded method to map the OpenReadCompleted event of the existing wClient object to the wClient_OpenReadCompleted method. Append the code to the existing If...Then/if construct. To the Home_Loaded or Page_Loaded method, append the following code. Append the code to the existing If...Then/if construct.
[Visual Basic] ' Add event handler for download complete AddHandler wClient.OpenReadCompleted, AddressOf wClient_OpenReadCompleted

[Visual C#] // Add event handler for download complete wClient.OpenReadCompleted += wClient_OpenReadCompleted;

10. Append code to the Home_Loaded or Page_Loaded method to start the asynchronous download of the FabrikamLibrary.dll assembly by calling the OpenReadAsync method of the wClient object, passing a relative uri for the FabrikamLibrary.dll assembly. To the Home_Loaded or Page_Loaded method, append the following code. Append the code to the existing If...Then/if construct.
[Visual Basic] ' Start asynchronous download wClient.OpenReadAsync(New Uri("FabrikamLibrary.dll", UriKind.Relative))

14

Lab Answer Key: Deploying Silverlight Applications

[Visual C#] // Start asynchronous download wClient.OpenReadAsync(new Uri("FabrikamLibrary.dll", UriKind.Relative));

11. Run and test the application. Press Ctrl+F5.

Notice how the content of the Home page is replaced with the content loaded from the DynamicPage.xaml file, and how the styles are merged with the current project. 12. Close all applications. You have now completed this lab.

Lab Answer Key: Application Guidance

Module 13
Lab Answer Key: Application Guidance
Contents:
Exercise 1: Installing the Simple MVVM Toolkit Exercise 2: Examining a Silverlight MVVM project Exercise 3: Implementing MVVM Items 2 4 9

Lab Answer Key: Application Guidance

Lab: Implementing the MVVM Design Pattern


Exercise 1: Installing the Simple MVVM Toolkit
Task 1: Get the Simple MVVM Toolkit installer.
If you have an Internet connection on your virtual machine, 10554A-SEA-DEV, you can download the installer directly and save it to the desktop. Alternatively, you can get a copy from your instructor, who can supply an ISO file for you to attach to the virtual machine. 1. Get the Simple MVVM Toolkit installer from CodePlex, http://go.microsoft.com/fwlink/?LinkId=225227. Note In this lab, version 2.1.0.0 has been used. If a newer version is available, and you want to use 2.1.0.0, on the http://go.microsoft.com/fwlink/?LinkId=225227 page, click View all downloads in the upper right download box. On the Downloads page, in the Other Downloads box, click Simple MVVM Toolkit v2.1.0.0, and then, on the left of the page, click Simple MVVM Toolkit v2.1.0.0 to initiate the download. 1. 2. 3. 4. 5. 6. 2. Open Internet Explorer and then browse to this address, http://go.microsoft.com/fwlink/?LinkId=225227. On the CodePlex page, click Download, and then, in the To download the file you must agree to the following license. dialog box, click I Agree. In the File Download Security Warning dialog box, click Save. In the Save As dialog box, browse to the Desktop, and then click Save. In the Download Complete dialog box, click Close. Close Internet Explorer.

Get the Simple MVVM Toolkit installer from your instructor, located in an ISO file, and attach it to the virtual machine. 1. 2. 3. Ask your instructor for the installer, located in an ISO file. The instructor may have a USB stick, a CD/DVD, or on a network share. After you have access to the ISO file, in the 10554A-SEA-DEV on localhost Virtual Machine Connection window, on the Media menu, point to DVD Drive, and then click Insert Disk. In the Open dialog box, browse to the location of the ISO file, select it, and then click Open.

Task 2: Run the Simple MVVM Toolkit installer.


1. 2. 3. 4. 5. Double-click the executable installer file, SimpleMvvmInstaller.exe, to start the installation. In the Simple Mvvm Toolkit InstallShield Wizard box, on the Welcome to the InstallShield Wizard for Simple Mvvm Toolkit page, click Next. On the Readme Information page, click Next. On the Ready to install the Program page, click Install. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes.

Lab Answer Key: Application Guidance

6.

On the InstallShield Wizard Completed page, clear the Show the readme file check box, and then click Finish.

Task 3: Register the Simple MVVM Toolkit project and item templates.
1. 2. 3. 4. 5. 6. 7. On the Start menu, click All Programs, expand Accessories, right-click Command Prompt, and then click Run as administrator. In the User Account Control dialog box, in the Password box, type Pa$$w0rd, and then click Yes. In the Administrator: Command Prompt box, at the prompt, type cd C:\Program Files\SimpleMvvmToolkit, and then press Enter. At the prompt, type SimpleMvvm-32wp.reg, and then press Enter. In the Registry Editor dialog box, click Yes. In the Registry Editor dialog box, click OK. Close the Administrator: Command Prompt box.

Lab Answer Key: Application Guidance

Exercise 2: Examining a Silverlight MVVM project


Task 1: Open the MVVMGreetingCardManagement solution.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the MVVMGreetingCardManagement solution from the D:\Labfiles\Mod13\VB\Starter or D:\Labfiles\Mod13\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod13\VB\Starter\ MVVMGreetingCardManagement.sln or D:\Labfiles\Mod13\CS\Starter\ MVVMGreetingCardManagement.sln, and then click Open.

The Visual C# solution was created by using the SimpleMvvmRiaServices project template, and then customizing it slightly. The Visual Basic solution was created by using the Silverlight Business Application project template, and then adding the missing pieces, to make the two solutions as identical as possible. The two project templates are quite similar, with the SimpleMvvmRiaServices project template being a customization of the Silverlight Business Application project template. 3. Notice the hosting ASP.NET Web Application project named MVVMGreetingCardManagement.Web, which is the same type of hosting application you have been using throughout this course.

Task 2: Examine the model.


1. In the MVVMGreetingCardManagement project, expand the Models folder. 2. In Solution Explorer, under MVVMGreetingCardManagement, expand Models.

Notice how the Models folder only contains the standard client model files created by the Silverlight Business Application project template. Currently, no application specific data models have been created. In the MVVMGreetingCardManagement.Web project, expand the Models folder. In Solution Explorer, under MVVMGreetingCardManagement.Web, expand Models.

3.

4.

Notice how the Models folder contains the GreetingCardModel.edmx file, with which you have worked previously. The server data model has been created for you.

Task 3: Examine the view-models.


1. In the MVVMGreetingCardManagement project, open and examine the HomeViewModel viewmodel, located in the ViewModels folder. 2. In Solution Explorer, under MVVMGreetingCardManagement, expand ViewModels, and then double-click HomeViewModel.vb or HomeViewModel.cs.

Notice how the HomeViewModel inherits from the ViewModelBase class, which is one of two view-model base classes used with the Simple MVVM Toolkit. This one can be used for displaying a collection of objects, or used as a default view-model, if you have not planned which data will be displayed yet.

Lab Answer Key: Application Guidance

3.

Notice how the non-default constructor accepts an argument of type, IHomeServiceAgent, which is saved to the private serviceAgent member variable. The service agent is responsible for retrieving the data for the view-model to expose. Expand the collapsed regions. Press Ctrl+M, Ctrl+L.

4.

5. 6.

There is currently no code in the Properties, Methods, and Commands regions, because it is not needed for this view-model. Notice the ErrorNotice event declaration, located in the Notifications regions, which is used by the NotifyError method, located in the Helpers region to inform the view of an error. The NotifyError method calls the Notify method of the base class, ViewModelBase. Close the HomeViewModel view-model. Open and examine the MainPageViewModel view-model, located in the ViewModels folder. In Solution Explorer, under ViewModels, double-click MainPageViewModel.vb or MainPageViewModel.cs.

7. 8.

9.

Notice how the default constructor calls the RegisterToReceiveMessages method, inherited from the base class, to register or subscribe to messages that arrive on the MessageBus implementation. Only navigation token messages are subscribed to, by specifying the MessageTokens.Navigation constant value. This value is defined in the MessageTokens class, located in the Others folder. The Navigation value is currently the only value defined, but to extend the messaging system, you can add new constant values to this class.

10. Expand the collapsed regions. Press Ctrl+M, Ctrl+L.

11. Notice the SelectedPage property declaration, located in the Properties region. This property and the corresponding backing member field are used to keep track of the current page in the navigation system implemented, and the view can bind to this property. You will see more of how navigation is implemented by using an event handler, methods, and the MainPage view later. 12. Notice the Navigate and OnNavigationRequested methods, both located in the Methods region. The latter should be familiar because it is the same event handler method you have seen throughout the implementations of the Silverlight Business Application and Silverlight Navigation Application. However, unlike the previous implementations, the OnNavigationRequested method calls the Navigate method, passing the page name, stored in the Message property of the NotificationEventArgs argument. This class is custom to the Simple MVVM Toolkit, and part of the messaging implementation. 13. Notice the NavigateCommand property, located in the Commands region. This property is used by the HyperlinkButton controls, used as part of the menu and user exposed navigation implementation, by way of binding. The DelegateCommand is custom to the Simple MVVM Toolkit, and used as the type for the NavigateCommand property. 14. Close the MainPageViewModel view-model.

Task 4: Examine the views.


1. Open and examine the HomeView view, located in the Views folder. 2. In Solution Explorer, expand Views, and then double-click HomeView.xaml.

Notice how the designer and the XAML view look more or less the same as the Home.xaml page used in the previous implementations of the Silverlight Business Application project template. One

Lab Answer Key: Application Guidance

exception is how the DataContext property of the Page control is bound to the HomeViewModel by using a static resource that locates the view-model. This is bound the same way as you saw during the demonstrations. 3. 4. Close the HomeView view. Open and examine the MainPage view, located in the root folder. 5. In Solution Explorer, double-click MainPage.xaml.

Notice how the designer and the XAML view look similar to the MainPage.xaml UserControl used in the previous implementations of the Silverlight Business Application project template. There are a few differences though, as detailed in the next few steps. The DataContext property of the UserControl control is bound to the MainPageViewModel just like the HomeView view. The Source property of the Frame control used by the Silverlight navigation system is bound to the SelectedPage property of the MainPageViewModel. The HyperlinkButton control named, Link1, uses the Command and CommandParameter properties for navigation, instead of the NavigateUri property used by previous implementations of the MainPage.xaml view. The Command property binds to the NavigateCommand property of the MainPageViewModel property, passing the string Home, in the CommandParameter property. Close the MainPage view.

6. 7. 8.

9.

Task 5: Examine the services.


1. Examine the IHomeServiceAgent interface, located in the Services folder. 2. 3. 4. In Solution Explorer, expand Services, and then double-click IHomeServiceAgent.vb or IHomeServiceAgent.cs.

Notice how the interface is empty, and unlike the implementation you saw in the demonstration, does not define any methods. Close the IHomeServiceAgent code file. Examine the HomeServiceAgent class. In Solution Explorer, under Services, double-click HomeServiceAgent.vb or HomeServiceAgent.cs.

5.

Notice how the class is empty. The interface and the class are currently empty, awaiting any data methods to be added, if the view-model needs to expose properties and methods for the view to consume. Notice how there is no service agent for the MainPageViewModel in the Services folder; the MainPageViewModel does not need any because it really only serves the purpose of a master page or main page, enabling and facilitating navigation, and exposing the frame, in which Page controls can be shown. The HomeView currently does not need a service agent either, but it has been implemented with a service agent, to ensure it is easy to add at a later date. Close the HomeServiceAgent code file. In the MVVMGreetingCardManagement.Web project, expand the Services folder. In Solution Explorer, under MVVMGreetingCardManagement.Web, expand Services.

6.

7. 8.

9.

Notice how the Services folder contains the GreetingCardDomainService.vb or GreetingCardDomainService.cs and the GreetingCardDomainService.metadata.vb or

Lab Answer Key: Application Guidance

GreetingCardDomainService.metadata.cs files, with which you have worked previously. The server service layer has been created for you.

Task 6: Examine the App and View-Model locator.


1. In the MVVMGreetingCardManagement project, examine App.xaml. 2. In Solution Explorer, under MVVMGreetingCardManagement, double-click App.xaml.

In the XAML view, notice how an instance of the InjectedViewModelLocator class is added to the Application.Resources resource dictionary, ensuring its availability throughout the lifetime of the application. Close the App.xaml file. Examine the InjectedViewModelLocator class, located in the Locators folder. In Solution Explorer, expand Locators, and then double-click InjectedViewModelLocator.vb or InjectedViewModelLocator.cs.

3. 4.

5.

In the InjectedViewModelLocator class, notice the shared/static constructor that checks if the element or controls is currently running in the context of a designer, such as Visual Studio or Expression Blend. If not, then a new DeploymentCatalog object is created and passed to the CompositionHost.Initialize method. This is used with the Microsoft Extensibility Framework (MEF) for supporting dependency injection of the service agents. Without going into details beyond the scope of this course, it basically means that you can "inject" any type of service agent. Notice how a public property named, AgentType, and the corresponding backing member variable, get or set the type of service agents used. The property returns a member of the AgentType enumeration, which contains three members: Mock, Real, and Unspecified. You use the values to specify whether you want to use the Mock or the Real service agents, allowing you to dynamically select if mock data or real data should be used. In the InjectedViewModelLocator class, notice the default constructor that also checks if the element or controls is currently running in the context of a designer. If not, the CompositionInitializer.SatisfyImports MEF method is used inject the current service agent object. In addition, the Debug.Assert method is used to throw an exception, if the HomeViewModel is not created correctly, and thus, the corresponding service agent and the correct agent type. The actual instantiation of the both of these objects happens when the Debug.Assert method is called, or when the HomeViewModel property, covered later, is bound to from the view. Notice the public and read-only property named, HomeViewModel, which creates and returns an instance of the HomeViewModel. If a corresponding service agent is found, it is created, and passed to the HomeViewModel constructor. Notice the public and read-only property named, MainPageViewModel, which returns an instance of the MainPageViewModel. The MainPageViewModel does not need a service agent, so the property code is straight-forward.

6.

7.

8.

9.

10. Close the InjectedViewModelLocator code file.

Lab Answer Key: Application Guidance

Task 7: Test the application.


1. Run the application. 2. 3. Press Ctrl+F5.

Notice how the application looks like the GreetingCard applications you have created previously in this course. The logon functionality also works, using the Student user credentials. Close Internet Explorer.

Lab Answer Key: Application Guidance

Exercise 3: Implementing MVVM Items


Task 1: Add the SendersServiceAgent service agent.
1. In the MVVMGreetingCardManagement project, add a new service agent interface, named ISendersServiceAgent, to the Services folder. The service agent will help with the data management for the SendersViewModel view-model, which you will build later. a. b. 2. In Solution Explorer, under MVVMGreetingCardManagement, right-click Services, point to Add, and then click Class. In the Add New Item MVVMGreetingCardManagement dialog box, in the Name box, type ISendersServiceAgent, and then click Add.

Change the added project item from a class to an interface by modifying the generated code to resemble to following code.
[Visual Basic] Public Interface ISendersServiceAgent End Interface

[Visual C#] public interface ISendersServiceAgent { }

3.

[Visual C# only] Bring the System.Collections.Generic and MVVMGreetingCardManagement.Web.Models namespaces into scope in the ISendersServiceAgent.cs code file. These namespaces contain the argument types used in the method added next. Add a method named, GetSenders, to the interface. The method should not return a value, but accept one argument named, completed. The argument must be of delegate type, Action, which accepts a generic List of type, Sender, and an Exception. To the ISendersServiceAgent interface, add the following method.
[Visual Basic] Sub GetSenders(ByVal completed As Action(Of List(Of Sender), Exception))

4.

[Visual C#] void GetSenders(Action<List<Sender>, Exception> completed);

5. 6.

Save and close the ISendersServiceAgent code file. Implement the ISendersServiceAgent service agent interface in a new class named, SendersServiceAgent. a. b. c. In Solution Explorer, under MVVMGreetingCardManagement, right-click Services, point to Add, and then click Class. In the Add New Item MVVMGreetingCardManagement dialog box, in the Name box, type SendersServiceAgent, and then click Add. To the class declaration, add the following code in bold.

10

Lab Answer Key: Application Guidance

[Visual Basic] Public Class SendersServiceAgent Implements ISendersServiceAgent End Class

[Visual C#] public class SendersServiceAgent : ISendersServiceAgent { }

d.

Autogenerate the interface members. In Visual Basic, place the cursor after ISendersServiceAgent, and then press Enter. In Visual C#, right-click ISendersServiceAgent, point to Implement Interface, and then click Implement Interface.

7.

[Visual C# only] Bring the MVVMGreetingCardManagement.Web.Services namespace into scope in the SendersServiceAgent.cs code file. This namespace contains the argument types used in the variable added next. Bring the SimpleMvvmToolkit namespace into scope in the SendersServiceAgent code file. This namespace contains the attribute type applied to the class next. To the SendersServiceAgent class, apply the ServiceAgentExport attribute. This attribute is used to specify which type of service agents are exported, and the type of agent. The attribute should resemble the following code.
[Visual Basic] <ServiceAgentExport(GetType(ISendersServiceAgent), AgentType:=AgentType.Real)>

8. 9.

[Visual C#] [ServiceAgentExport(typeof(ISendersServiceAgent), AgentType = AgentType.Real)]

To the SendersServiceAgent class, add the following code in bold.


[Visual Basic] <ServiceAgentExport(GetType(ISendersServiceAgent), AgentType:=AgentType.Real)> Public Class SendersServiceAgent

[Visual C#] [ServiceAgentExport(typeof(ISendersServiceAgent), AgentType = AgentType.Real)] public class SendersServiceAgent : ISendersServiceAgent

10. In the SendersServiceAgent class, add and instantiate a new private member variable named, gcDomainContext, of type, GreetingCardDomainContext. This variable will be used for accessing the Entity Data Model on the hosting server, by using the generated RIA Service code, available on the client. To the SendersServiceAgent class, add the following code, after the class declaration.
[Visual Basic] Private gcDomainContext As New GreetingCardDomainContext

Lab Answer Key: Application Guidance

11

[Visual C#] private GreetingCardDomainContext gcDomainContext = new GreetingCardDomainContext();

11. Bring the System.ServiceModel.DomainServices.Client namespace into scope in the SendersServiceAgent code file. This namespace contains the argument types used in the method implemented next. 12. [Visual C# only] Bring the MVVMGreetingCardManagement.Web.Models, System.Linq, and System.Collections.Generic namespaces into scope in the SendersServiceAgent.cs code file. These namespaces contain the argument types used in the method implemented next. 13. In the SendersServiceAgent class, to the GetSenders method, add the following code (overwriting any existing code). The code creates a new entity query that calls the GetSenders query on the server (named GetSendersQuery on the client), by using the private gcDomainContext variable. Subsequently, the load operation is initiated and executed. If everything goes well, the retrieved collection of Sender objects is assigned to the completed argument callback.
[Visual Basic] Dim query As EntityQuery(Of Sender) = gcDomainContext.GetSendersQuery() ' Load GetSendersQuery gcDomainContext.Load(query, Sub(load) ' Declare error and result Dim err As Exception = Nothing Dim senders As IEnumerable(Of Sender) = Nothing ' Set error or result If load.HasError Then err = load.Error Else senders = load.Entities End If ' Invoke completion callback completed(senders.ToList, err) End Sub, Nothing)

[Visual C#] EntityQuery<Sender> query = gcDomainContext.GetSendersQuery(); // Load GetSendersQuery gcDomainContext.Load(query, load => { // Declare error and result Exception err = null; IEnumerable<Sender> senders = null; // Set error or result if (load.HasError) { err = load.Error; } else { senders = load.Entities; } // Invoke completion callback

12

Lab Answer Key: Application Guidance

completed(senders.ToList(), err); }, null);

14. Save and close the SendersServiceAgent code file.

Task 2: Add the SendersViewModel view-model.


1. In the MVVMGreetingCardManagement project, add a new view-model, named SendersViewModel, to the ViewModels folder. a. b. 2. In Solution Explorer, under MVVMGreetingCardManagement, right-click ViewModels, point to Add, and then click Class. In the Add New Item MVVMGreetingCardManagement dialog box, in the list of project item templates, click Class, in the Name box, type SendersViewModel, and then click Add.

[Visual C# only] Change the namespace for the SendersViewModel class from MVVMGreetingCardManagement.ViewModels to MVVMGreetingCardManagement. This will ensure the namespace is the same as the existing view-model classes. Bring the SimpleMvvmToolkit and System.ServiceModel.DomainServices.Client namespaces into scope in the SendersViewModel code file. These namespaces contain the argument types used in the class modification next. Derive the SendersViewModel class from the generic ViewModelBase class, of SendersViewModel. To the class declaration, add the following code in bold.
[Visual Basic] Public Class SendersViewModel Inherits ViewModelBase(Of SendersViewModel)

3.

4.

[Visual C#] public class SendersViewModel : ViewModelBase<SendersViewModel>

5.

In the SendersViewModel class, declare a new private member variable named, serviceAgent, of type, ISendersServiceAgent. This variable will be used for storing a reference to the service agent used for retrieving data from the model To the SendersViewModel class, add the following code, after the class declaration.
[Visual Basic] Private serviceAgent As ISendersServiceAgent

[Visual C#] private ISendersServiceAgent serviceAgent;

6.

Bring the System.Collections.ObjectModel namespace into scope in the SendersViewModel code file. This namespace contain the argument types used by the private member variables declared next. [Visual C# only] Bring the MVVMGreetingCardManagement.Web.Models namespace into scope in the SendersViewModel.cs code file. This namespace contain the argument types used by the private member variables declared next.

7.

Lab Answer Key: Application Guidance

13

8.

Add the following private member variables. The sndrs variable is used for storing an ObservableCollection of the retrieved Sender objects from the model. The selSender variable is used to point to the currently selected Sender in the UI. The two Boolean member variables are used to set and check if the view-model is busy with an operation, or if the senders can be loaded.
[Visual Private Private Private Private Basic] sndrs As ObservableCollection(Of Sender) selSender As Sender busy As Boolean ableToLoad As Boolean = True

[Visual private private private private

C#] ObservableCollection<Sender> sndrs; Sender selSender; bool busy; bool ableToLoad = true;

9.

Create an empty default constructor. To the SendersViewModel class, append the following code. It is used by the view-model locator.
[Visual Basic] Public Sub New() End Sub

[Visual C#] public SendersViewModel() { }

10. [Visual C# only] Bring the MVVMGreetingCardManagement.Services namespace into scope in the SendersViewModel.cs code file. This namespace contains the argument types used in the nondefault constructor implemented next. 11. Create a non-default constructor that accepts a single argument of type, ISendersServiceAgent. The constructor must assign the passed service agent argument to the private member variable, serviceAgent, and call the LoadSenders method to be created later. The constructor is used by the view-model locator. To the SendersViewModel class, append the following code.
[Visual Basic] Public Sub New(ByVal serviceAgnt As ISendersServiceAgent) Me.serviceAgent = serviceAgnt LoadSenders() End Sub

[Visual C#] public SendersViewModel(ISendersServiceAgent serviceAgnt) { this.serviceAgent = serviceAgnt; LoadSenders(); }

14

Lab Answer Key: Application Guidance

12. Append the following code to the SendersViewModel class. The Notifications region contains two public events, used to make the view aware of an error, or when the sender objects have been loaded from the model.
[Visual Basic] #Region "Notifications" Public Event ErrorNotice As EventHandler(Of NotificationEventArgs(Of Exception)) Public Event SendersLoadedNotice As EventHandler(Of NotificationEventArgs) #End Region

[Visual C#] #region Notifications public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice; public event EventHandler<NotificationEventArgs> SendersLoadedNotice; #endregion

13. Append the following code to the SendersViewModel class. The Properties region contains several public properties, all used by the view and the view-model for binding the two objects and managing when an operation can be performed. All properties ensure that any change to the property value is notified to those binding to the property, such as controls in the view.
[Visual Basic] #Region "Properties" Public Property Senders As ObservableCollection(Of Sender) Get Return Me.sndrs End Get Set(ByVal value As ObservableCollection(Of Sender)) Me.sndrs = value NotifyPropertyChanged(Function(m) m.Senders) End Set End Property Public Property SelectedSender As Sender Get Return Me.selSender End Get Set(ByVal value As Sender) Me.selSender = value Me.CanLoad = Not IsBusy NotifyPropertyChanged(Function(m) m.SelectedSender) End Set End Property Public Property IsBusy As Boolean Get Return Me.busy End Get Set(ByVal value As Boolean) Me.busy = value Me.CanLoad = Not IsBusy NotifyPropertyChanged(Function(m) m.IsBusy) End Set End Property

Lab Answer Key: Application Guidance

15

Public Property CanLoad As Boolean Get Return Me.ableToLoad End Get Set(ByVal value As Boolean) Me.ableToLoad = value NotifyPropertyChanged(Function(m) m.CanLoad) End Set End Property #End Region

[Visual C#] #region Notifications public event EventHandler<NotificationEventArgs<Exception>> ErrorNotice; public event EventHandler<NotificationEventArgs> SendersLoadedNotice; #endregion #region Properties public ObservableCollection<Sender> Senders { get { return this.sndrs; } set { this.sndrs = value; NotifyPropertyChanged(m => m.Senders); } } public Sender SelectedSender { get { return this.selSender; } set { this.selSender = value; this.CanLoad = !IsBusy; NotifyPropertyChanged(m => m.SelectedSender); } } public bool IsBusy { get { return this.busy; } set { this.busy = value; this.CanLoad = !IsBusy; NotifyPropertyChanged(m => m.IsBusy); } }

16

Lab Answer Key: Application Guidance

public bool CanLoad { get { return this.ableToLoad; } set { this.ableToLoad = value; NotifyPropertyChanged(m => m.CanLoad); } } #endregion

14. Append the following code to the SendersViewModel class. The Methods region contains a single method named, LoadSenders, which does as the name indicates; it uses the GetSenders method of the service agent to initiate and execute the loading of the senders from the model.
[Visual Basic] #Region "Methods" Public Sub LoadSenders() serviceAgent.GetSenders( _ Sub(entities, err) SendersLoaded(entities, err) End Sub ) ' Reset property Me.Senders = Nothing ' Flip busy flag Me.IsBusy = True End Sub #End Region

[Visual C#] #region Methods public void LoadSenders() { serviceAgent.GetSenders( (entities, err) => { SendersLoaded(entities, err); }); // Reset property this.Senders = null; // Flip busy flag this.IsBusy = true;

#endregion

Lab Answer Key: Application Guidance

17

15. [Visual C# only] Bring the System.Collections.Generic namespace into scope in the SendersViewModel.cs code file. This namespace contains the types used in the callback methods implemented next. 16. Append the following code to the SendersViewModel class. The Completion Callbacks region contains a single method named, SendersLoaded, which is asynchronously invoked from the LoadSenders method, described previously. The SendersLoaded method checks for errors, and notifies the view if an error occurred. If no error occurred, the Senders property is set, the SelectedSender is set to the first Sender object returned, and finally, the view is notified that the loading of the sender objects has completed.
[Visual Basic] #Region "Completion Callbacks" Private Sub SendersLoaded(ByVal entities As List(Of Sender), ByVal err As Exception) ' If no error is returned, set the model to entities If err Is Nothing Then Senders = New ObservableCollection(Of Sender)(entities) Else NotifyError("Unable to retrieve sender", err) End If ' Set SelectedSender to the first item If Senders.Count > 0 Then SelectedSender = Senders(0) End If ' Notify view Notify(SendersLoadedNoticeEvent, New NotificationEventArgs("Senders were successfully loaded")) ' Finished IsBusy = False End Sub #End Region

[Visual C#] #region Completion Callbacks private void SendersLoaded(List<Sender> entities, Exception err) { // If no error is returned, set the model to entities if (err == null) { Senders = new ObservableCollection<Sender>(entities); } else { NotifyError("Unable to retrieve sender", err); } // Set SelectedSender to the first item if (Senders.Count > 0) { SelectedSender = Senders[0]; } // Notify view

18

Lab Answer Key: Application Guidance

Notify(SendersLoadedNotice, new NotificationEventArgs("Senders were successfully loaded")); // Finished IsBusy = false; } #endregion

17. Append the following code to the SendersViewModel class. The Helpers region contains a single method, NotifyError, which was described previously in Task 3 of Exercise 2.
[Visual Basic] #Region "Helpers" ' Helper method to notify View of an error Private Sub NotifyError(ByVal message As String, ByVal err As Exception) ' Notify view of an error Notify(Of Exception)(ErrorNoticeEvent, New NotificationEventArgs(Of Exception)(message, err)) End Sub #End Region

[Visual C#] #region Helpers // Helper method to notify View of an error private void NotifyError(string message, Exception err) { // Notify view of an error Notify<Exception>(ErrorNotice, new NotificationEventArgs<Exception>(message, err)); } #endregion

18. Save and close the SendersViewModel code file.

Task 3: Add the SendersView view.


1. To the MVVMGreetingCardManagement project, add an existing Silverlight Page named, SendersView, to the Views folder. a. b. In Solution Explorer, under MVVMGreetingCardManagement, right-click Views, point to Add, and then click Existing Item. In the Add Existing Item - MVVMGreetingCardManagement dialog box, in the File name box, type D:\Labfiles\Mod13\VB\Starter\SendersView.xaml or D:\Labfiles\Mod13\CS\Starter\SendersView.xaml, and then click Add.

2.

Open the SendersView view. In Solution Explorer, under MVVMGreetingCardManagement, under Views, double-click SendersView.xaml.

3.

Notice how the designer and the XAML view look more or less the same as the Home.xaml page used in the lab exercises for Module 2. In the designer, you can see the Label and TextBox controls for displaying the display name and email fields for a Sender entity. Then, there is a DataPager

Lab Answer Key: Application Guidance

19

control for moving back and forth between the Sender entities, and below that, a DataGrid control for displaying the Card entities for the selected Sender entity, in true master-detail style. 4. In the XAML view, you can see how the DataContext property of the Page control is bound to the SendersViewModel by using a static resource that locates the view-model. The two TextBox controls are bound to the SelectedSender.DisplayName and SelectedSender.Email properties of the SendersViewModel view-model. The DataGrid control is bound to the SelectedSender.Cards property, whereas the DataPager control is not bound declaratively. Close the SendersView view. Open the SendersView view, in Code view. In the SendersView class, in the default constructor, you can see how the private model variable is bound to the SendersViewModel through the DataContext property. The ErrorNotice and SendersLoadedNotice events of the SendersViewModel view-model are handled by the corresponding event handlers, OnErrorNotice and OnSendersLoadedNotice. This way, the viewmodel can communicate with the view. Notice the OnErrorNotice event handler method, which shows an error message and outputs trace information. Notice the OnSendersLoadedNotice event handler method, which sets the Source property of the DataPager control to a new PagedCollectionView collection, which wraps the Senders collection from the view-model. It is wrapped in a PagedCollectionView collection to ensure the DataPager control can properly enumerate the items.

5. 6. 7.

8. 9.

10. Notice the SendersDataPager_PageIndexChanged event handler method, which sets the SelectedSender property of the view-model to the currently selected page index. The DataPager page index is set to 1, which means this index matches the order of the Senders collection of the view-model. 11. Close the SendersView code file. 12. Open MainPage.xaml. 13. In MainPage.xaml, in the XAML view, locate the following markup.
<Rectangle x:Name="Divider1" Style="{StaticResource DividerStyle}"/>

14. Immediately below the located markup, but above the closing StackPanel tag, add a new selfclosing HyperlinkButton control element named, SendersHyperlinkButton. The HyperlinkButton control is bound to the NavigateCommand property of the MainPageViewModel, which you examined in Exercise 2. The name of the view to which to navigate is passed to the NavigateCommand property by setting the CommandParameter property of the HyperlinkButton. Set the following properties.
Property Name Content Command CommandParameter Style TargetName Property Value {Binding Path=ApplicationStrings.SendersPageTitle, Source={StaticResource ResourceWrapper}} {Binding NavigateCommand} SendersView {StaticResource LinkStyle} ContentFrame

Immediately above the located markup, add the following markup.

20

Lab Answer Key: Application Guidance

<HyperlinkButton x:Name="SendersHyperlinkButton" Style="{StaticResource LinkStyle}" Command="{Binding NavigateCommand}" CommandParameter="SendersView" TargetName="ContentFrame" Content="{Binding Path=ApplicationStrings.SendersPageTitle, Source={StaticResource ResourceWrapper}}"/>

15. Save and close MainPage.xaml. 16. Build the solution. On the Build menu, click Build Solution.

Task 4: Configure the application resources.


1. In the MVVMGreetingCardManagement project, open the Resource Designer for the Assets\Resources\ApplicationStrings.resx resource file. In Solution Explorer, under MVVMGreetingCardManagement, expand Assets, expand Resources, and then double-click ApplicationStrings.resx.

The Resource Designer opens displaying a three-column grid containing the resource strings in the ApplicationStrings.resx resource file. 2. Add a new key named, SendersPageTitle, with a value, Senders. 3. 4. In the empty bottom row, in the Name column, type SendersPageTitle, in the Value column, type Senders, and then press Enter.

Save the changes. Close the Resource Designer.

Task 5: Modify the View-Model locator.


1. Open the InjectedViewModelLocator.vb or InjectedViewModelLocator.cs code file, located in the Locators folder. 2. In Solution Explorer, under Locators, double-click InjectedViewModelLocator.vb or InjectedViewModelLocator.cs.

In the default non-shared/non-static constructor, append the following code to the If/if construct.
[Visual Basic] Debug.Assert(Not Me.SendersViewModel Is Nothing, String.Format(ApplicationStrings.ServiceAgentNotFound, "ISendersServiceAgent", AgentType))

[Visual C#] Debug.Assert(this.SendersViewModel != null, string.Format(ApplicationStrings.ServiceAgentNotFound, "ISendersServiceAgent", agentType));

3.

[Visual C# only] Bring the MVVMGreetingCardManagement.Services namespace into scope in the InjectedViewModelLocator.cs code file. The namespace contain the types used in the properties added next. To the InjectedViewModelLocator class, append the following code.
[Visual Basic] <ImportMany()>

4.

Lab Answer Key: Application Guidance

21

Public Property SendersServiceAgents As Lazy(Of ISendersServiceAgent, IServiceAgentMetadata)() Public ReadOnly Property SendersViewModel As SendersViewModel Get Dim serviceAgent = SendersServiceAgents _ .Where(Function(sa) sa.Metadata.AgentType = AgentType).FirstOrDefault() Dim viewModel As SendersViewModel = Nothing If Not serviceAgent Is Nothing Then viewModel = New SendersViewModel(serviceAgent.Value) ElseIf DesignerProperties.IsInDesignTool Then viewModel = New SendersViewModel() End If Return viewModel End Get End Property

[Visual C#] [ImportMany] public Lazy<ISendersServiceAgent, IServiceAgentMetadata>[] SendersServiceAgents { get; set; } public SendersViewModel SendersViewModel { get { var serviceAgent = SendersServiceAgents .Where(sa => sa.Metadata.AgentType == agentType).FirstOrDefault(); SendersViewModel viewModel = null; if (serviceAgent != null) viewModel = new SendersViewModel(serviceAgent.Value); else if (DesignerProperties.IsInDesignTool) viewModel = new SendersViewModel(); } return viewModel;

22

Lab Answer Key: Application Guidance

Task 6: Test the application.


1. Run and test the application. 2. 3. 4. 5. Press Ctrl+F5.

In Internet Explorer, click Senders. Notice how the Sender data is displayed. Navigate back and forth with the DataPager control to see all the Sender entities. Close all applications. You have now completed this lab.

Lab Answer Key: Windows Phone DevelopmentFirst Look

Module 14
Lab Answer Key: Windows Phone DevelopmentFirst Look
Contents:
Exercise 1: Capturing User Input Exercise 2: Responding to Orientation Changes Exercise 3: Adding Page Navigation Exercise 4: Monitoring Game Status Exercise 5: Sharing Data Between Pages 2 6 9 10 13

Lab Answer Key: Windows Phone DevelopmentFirst Look

Lab: Creating a Windows Phone Application


Exercise 1: Capturing User Input
Task 1: Examine the standard input behavior.
1. Open Visual Studio 2010. 2. On the Start menu, click All Programs, click Microsoft Visual Studio 2010, and then click Microsoft Visual Studio 2010.

Open the TicTacToe solution from the D:\Labfiles\Mod14\VB\Starter or D:\Labfiles\Mod14\CS\Starter folder. a. b. On the File menu, point to Open, and then click Project/Solution. In the Open Project dialog box, in the File name box, type D:\Labfiles\Mod14\VB\Starter\ TicTacToe.sln or D:\Labfiles\Mod14\CS\Starter\ TicTacToe.sln, and then click Open.

3.

Set the Windows Phone 7 emulator as the target for Silverlight for Windows Phone projects by using the list on the Standard toolbar. In the TicTacToe Microsoft Visual Studio window, on the Standard toolbar, in the Select target for Silverlight for Windows Phone projects list, click Windows Phone 7 Emulator.

4.

Run the application. Press Ctrl+F5.

The Windows Phone emulator opens. It may take a while before your application is deployed, loaded, and displayed. 5. 6. 7. Click the Player 1 text box, and notice how the Software Input Panel (SIP) keyboard automatically slides open. In the Player 1 text box, type Student by using the SIP keyboard. In the Player 1 text box, click the text Student. Notice how the text is selected, and the copy icon is displayed above the selected text.

Lab Answer Key: Windows Phone DevelopmentFirst Look

8.

Copy the text by using the copy icon. Notice how the paste icon is displayed just above the SIP keyboard.

9.

Close the SIP keyboard by clicking the application background.

Task 2: Play the game.


1. In the game pad, click any of the square boxes, to start the game. Notice how the application automatically selects a box. You, as Player 1, use the X as the symbol for a selected box, whereas the application or computer as Player 2 uses the O symbol.

Lab Answer Key: Windows Phone DevelopmentFirst Look

2. 3. 4.

Keep playing till you win, or till you have three X symbols on a single line. This can be horizontal, vertical, or diagonal. Notice the message box that pops up with the winning message. Close the message box. Notice the new message box, prompting you to play another game. Cancel a new game. In the message box, click cancel.

5.

Close the Windows Phone 7 emulator. In the Windows Phone 7 emulator toolbar, click the Close button.

Task 3: Examine the MainPage.xaml page.


1. In the TicTacToe project, open MainPage.xaml. 2. 3. In the Solution Explorer window, in the TicTacToe project, double-click MainPage.xaml.

In the MainPage.xaml window, locate the control named player1TextBox. Examine the player1TextBox control, which is a TextBox control.

[Visual Basic] <TextBox Height="73" HorizontalAlignment="Left" Margin="26,60,0,0" Name="player1TextBox" Text="enter name to begin" VerticalAlignment="Top" Width="272" Grid.Row="1" />

[Visual C#] <TextBox Height="73" HorizontalAlignment="Left" Margin="26,60,0,0" Name="player1TextBox" Text="enter name to begin" VerticalAlignment="Top" Width="272" GotFocus="player1TextBox_GotFocus" Grid.Row="1" />

4. 5.

In the MainPage.xaml window, locate the control named textBlock1. Examine the textBlock1 control, which is a TextBlock control. In addition, notice the player2TextBox and textBlock2 controls, which are used for player display and user input.

[Visual Basic] <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,24,0,0" Name="textBlock1" Text="Player 1" VerticalAlignment="Top" Grid.Row="1" /> <TextBox Height="73" HorizontalAlignment="Left" Margin="26,172,0,0" Name="player2TextBox" Text="Computer" VerticalAlignment="Top" Width="269" Grid.Row="1" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,136,0,0" Name="textBlock2" Text="Player 2" VerticalAlignment="Top" Grid.Row="1" />

[Visual C#] <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,24,0,0" Name="textBlock1" Text="Player 1" VerticalAlignment="Top" Grid.Row="1" /> <TextBox Height="73" HorizontalAlignment="Left" Margin="26,172,0,0" Name="player2TextBox" Text="Computer" VerticalAlignment="Top" Width="269" Grid.Row="1" /> <TextBlock Height="30" HorizontalAlignment="Left" Margin="26,136,0,0" Name="textBlock2" Text="Player 2" VerticalAlignment="Top" Grid.Row="1" />

6.

Open the MainPage.xaml in Code view.

Lab Answer Key: Windows Phone DevelopmentFirst Look

7.

In the Solution Explorer window, in the TicTacToe project, right-click MainPage.xaml, and then click View Code.

Examine the GotFocus event handler for the player1TextBox control. Notice that the current text in the TextBox control is selected, when the TextBox control receives focus by calling the SelectAll method of the TextBox class.

[Visual Basic] ' select the text name of player 1 when the TextBox gets focus - makes a name change easier Private Sub player1TextBox_GotFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles player1TextBox.GotFocus player1TextBox.SelectAll() End Sub

[Visual C#] // select the text name of player 1 when the TextBox gets focus - makes a name change easier private void player1TextBox_GotFocus(object sender, RoutedEventArgs e) { player1TextBox.SelectAll(); }

Lab Answer Key: Windows Phone DevelopmentFirst Look

Exercise 2: Responding to Orientation Changes


Task 1: Modify MainPage.xaml to support all orientations.
1. Switch to MainPage.xaml. 2. In the TicTacToe Microsoft Visual Studio window, click MainPage.xaml.

Locate the opening tag for the main PhoneApplicationPage control or element.

<phone:PhoneApplicationPage x:Class="TicTacToe.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">

3.

Locate the markup for the SupportedOrientations property.

SupportedOrientations="Portrait"

4.

Modify the value for the SupportedOrientations property, to support both portrait and landscape orientations. In the MainPage.xaml window, modify the value of the SupportedOrientations property, to resemble the following markup.
SupportedOrientations="PortraitOrLandscape"

5.

Save the changes.

Task 2: Modify MainPage.xaml to handle the OrientationChanged event and support the Grid layout technique.
1. Switch to the MainPage.xaml code file. 2. In the TicTacToe Microsoft Visual Studio window, click MainPage.xaml.vb or MainPage.xaml.cs.

Locate the TODO comment, Call the PositionControls method, in the MainPage_OrientationChanged or OnOrientationChanged event handler.

[Visual Basic] ' this method responds to a phone orientation change Private Sub MainPage_OrientationChanged(ByVal sender As Object, ByVal e As Microsoft.Phone.Controls.OrientationChangedEventArgs) Handles MyBase.OrientationChanged MyBase.OnOrientationChanged(e) ' TODO: Call the PositionControls method End Sub

Lab Answer Key: Windows Phone DevelopmentFirst Look

[Visual C#] // this method responds to a phone orientation change protected override void OnOrientationChanged(OrientationChangedEventArgs args) { base.OnOrientationChanged(args); // TODO: Call the PositionControls method }

3.

To the MainPage_OrientationChanged or OnOrientationChanged event handler, append code to call the PositionControls method, passing the event arguments received. In the MainPage class, in the MainPage_OrientationChanged or OnOrientationChanged event handler method, append the following code.
[Visual Basic] PositionControls(e)

[Visual C#] PositionControls(args);

4.

Locate the TODO comment, Change the display location of controls, in the PositionControls method.

[Visual Basic] ... ' If not in portrait, move buttonList content to visible row and column. Else ' TODO: Change the display location of controls End If

[Visual C#] ... // If not in portrait, move buttonList content to visible row and column. else { // TODO: Change the display location of controls }

5.

In the PositionControls method, append code to the Else/else part of the If...Then...Else/if...else structure, to place the textBlock1, player1TextBox, textBlock2, player2TextBox, and textBlock3 controls, in row 1, column 2, by using the grid layout technique, and the Grid.SetRow and Grid.SetColumn methods. Remember that the row and column numbers are zero based. In the PositionControls method, in the Else/else part of the If...Then...Else/if...else structure, append the following code.
[Visual Basic] Grid.SetRow(textBlock1, 0) Grid.SetColumn(textBlock1, 1) Grid.SetRow(player1TextBox, 0)

Lab Answer Key: Windows Phone DevelopmentFirst Look

Grid.SetColumn(player1TextBox, 1) Grid.SetRow(textBlock2, 0) Grid.SetColumn(textBlock2, 1) Grid.SetRow(player2TextBox, 0) Grid.SetColumn(player2TextBox, 1) Grid.SetRow(textBlock3, 0) Grid.SetColumn(textBlock3, 1)

[Visual C#] Grid.SetRow(textBlock1, 0); Grid.SetColumn(textBlock1, 1); Grid.SetRow(player1TextBox, 0); Grid.SetColumn(player1TextBox, 1); Grid.SetRow(textBlock2, 0); Grid.SetColumn(textBlock2, 1); Grid.SetRow(player2TextBox, 0); Grid.SetColumn(player2TextBox, 1); Grid.SetRow(textBlock3, 0); Grid.SetColumn(textBlock3, 1);

6.

Save the changes.

Task 3: Test the orientation changes.


1. Run the application. 2. Press Ctrl+F5.

In the Windows Phone 7 emulator, change from portrait orientation to landscape left orientation, and notice the flow of the controls is exactly the same as in portrait orientation. In the Windows Phone 7 emulator toolbar, click the Rotate Right button.

3.

In the Windows Phone 7 emulator, change from landscape left orientation to portrait orientation, and notice the flow the controls is now exactly the same as when you started the application. In the Windows Phone 7 emulator toolbar, click the Rotate Left button.

4.

Close the Windows Phone 7 emulator. In the Windows Phone 7 emulator toolbar, click the Close button.

Lab Answer Key: Windows Phone DevelopmentFirst Look

Exercise 3: Adding Page Navigation


Task 1: Add code to navigate to the AdvancedGamePlay page.
1. In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment, Construct the code to navigate to the AdvancedGamePlay page, in the textBlock3_ManipulationStarted event handler. In the textBlock3_ManipulationStarted event handler method, append code to navigate to the page, which has the name stored in the local destinationPage string variable. Use the shared/static NavigationService.Navigate, passing in a new relative URI. In the textBlock3_ManipulationStarted method, append the following code.
[Visual Basic] Me.NavigationService.Navigate(New Uri(destinationPage, UriKind.Relative))

2.

[Visual C#] this.NavigationService.Navigate(new Uri(destinationPage, UriKind.Relative));

3.

In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, Construct the code to navigate back to the MainPage using the NavigationService, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: Construct the code to navigate back to the MainPage using the NavigationService.

Notice how the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file is opened, and the cursor placed at the TODO comment. 4. In the textBlock3_ManipulationStarted event handler method, append code to navigate back to the MainPage page. Use the shared/static NavigationService.Navigate, passing in a new relative URI. In the textBlock3_ManipulationStarted method, append the following code.

[Visual Basic] Me.NavigationService.GoBack()

[Visual C#] this.NavigationService.GoBack();

5.

Save the changes.

10

Lab Answer Key: Windows Phone DevelopmentFirst Look

Exercise 4: Monitoring Game Status


Task 1: Examine the AdvancedGamePlay.xaml page.
1. In the TicTacToe project, open AdvancedGamePlay.xaml. 2. 3. In the Solution Explorer window, in the TicTacToe project, double-click AdvancedGamePlay.xaml.

In the AdvancedGamePlay.xaml window, locate the Grid control named buttonFrameGrid. Examine the buttonFrameGrid control, which in addition to the Button controls in the MainPage.xaml page for selecting a square, also holds a number of Polyline controls.

<Polyline Stroke="White" StrokeThickness="5" Points="10,10,290,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineDiagonalRightAndDown" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,290,290,10" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineDiagonalRightAndUp" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="50,10,50,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalLeftColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="150,10,150,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalCenterColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="250,10,250,290" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineVerticalRightColumn" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,50,290,50" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalTopRow" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,150,290,150" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalCenterRow" Visibility="Collapsed" /> <Polyline Stroke="White" StrokeThickness="5" Points="10,250,290,250" Grid.ColumnSpan="3" Grid.RowSpan="3" Name="lineHorizontalBottomRow" Visibility="Collapsed" />

The Polyline control is generally used for drawing a series of connected straight lines. In the context of the Tic Tac Toe game, it is used to draw a straight line covering the three winning squares, when a game is won. 4. Open the AdvancedGamePlay.xaml in Code view. 5. In the Solution Explorer window, in the TicTacToe project, right-click AdvancedGamePlay.xaml and then click View Code.

Locate and examine the PrepareForWinnerLineDraw method. myPolyline is declared as a member variable at the top of the class as a Polyline object, and firstPoint and secondPoint are declared as member variables at the top of the class as Point objects. This method is used to initialize myPolyline with the data from winnerLine, which is also declared as a member variable at the top of the class as a Polyline object.

[Visual Basic] ' This method is used to initialize myPolyline with data from the winnerLine Public Sub PrepareForWinnerLineDraw() myPolyline = winnerLine ' get the first and last point of the winning path (polyline) firstPoint = winnerLine.Points.First() lastPoint = winnerLine.Points.Last() myPolyline.Points.Clear() ' add the first point of the winning path to the new polyline myPolyline.Points.Add(firstPoint) myPolyline.Visibility = System.Windows.Visibility.Visible

Lab Answer Key: Windows Phone DevelopmentFirst Look

11

' create a point that is the end of the line as it is constructed/drawn myEndPoint = myPolyline.Points.First() End Sub

[Visual C#] // This method is used to initialize myPolyline with data from the winnerLine public void PrepareForWinnerLineDraw() { myPolyline = winnerLine; // get the first and last point of the winning path (polyline) firstPoint = winnerLine.Points.First(); lastPoint = winnerLine.Points.Last(); myPolyline.Points.Clear(); // add the first point of the winning path to the new polyline myPolyline.Points.Add(firstPoint); myPolyline.Visibility = System.Windows.Visibility.Visible; // create a point that is the end of the line as it is constructed/drawn myEndPoint = myPolyline.Points.First();

6.

Locate and examine the DrawWinnerLine method, which is used to draw the actual winner line.

[Visual Basic] Public Sub DrawWinnerLine() ' construct the next point to add to the polyline Dim myNextPoint As New Point() myNextPoint.X = myEndPoint.X + ((lastPoint.X - firstPoint.X) / CType(numberOfLineSegments, Double)) myNextPoint.Y = myEndPoint.Y + ((lastPoint.Y - firstPoint.Y) / CType(numberOfLineSegments, Double)) ' add the point of the winning path to the new polyline myPolyline.Points.Add(myNextPoint) lineSegmentCounter += 1 If lineSegmentCounter>= numberOfLineSegments Then gameStatus = "game complete, announcing game result" Else myEndPoint = myNextPoint End If End Sub

[Visual C#] public void DrawWinnerLine() { // construct the next point to add to the polyline Point myNextPoint = new Point(); myNextPoint.X = myEndPoint.X + ((lastPoint.X - firstPoint.X) / (double) numberOfLineSegments); myNextPoint.Y = myEndPoint.Y + ((lastPoint.Y - firstPoint.Y) / (double) numberOfLineSegments); // add the point of the winning path to the new polyline

12

Lab Answer Key: Windows Phone DevelopmentFirst Look

myPolyline.Points.Add(myNextPoint); lineSegmentCounter++; if (lineSegmentCounter>= numberOfLineSegments) { gameStatus = "game complete, announcing game result"; } else { myEndPoint = myNextPoint; }

Lab Answer Key: Windows Phone DevelopmentFirst Look

13

Exercise 5: Sharing Data Between Pages


Task 1: Create a public property for sharing data between pages.
1. In the App.xaml.vb or App.xaml.cs file, locate the TODO comment, Create a public property that can be used to facilitate sharing data between pages, at the top of the App class. 2. In the Task List window, double-click the row with the text TODO: Create a public property that can be used to facilitate sharing data between pages.

In the App class, after the located comment, add code to create an auto-implemented property named, FirstPlayerTextString, of type, String/string. In the App class, after the located comment, add the following code.
[Visual Basic] Public Property FirstPlayerTextString As String

[Visual C#] public string FirstPlayerTextString { get; set; }

3.

In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, Construct code to share data between pages, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: Construct code to share data between pages.

4.

In the textBlock3_ManipulationStarted event handler method, after the located comment, assign the value of the Text property of the player1TextBox to the FirstPlayerTextString property in the App class. In the textBlock3_ManipulationStarted method, after the located comment, add the following code.
[Visual Basic] CType(Application.Current, App).FirstPlayerTextString = player1TextBox.Text.ToString

[Visual C#] (Application.Current as App).FirstPlayerTextString = player1TextBox.Text.ToString();

5.

In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment, Construct code in MainPage to share data between pages, in the textBlock3_ManipulationStarted event handler. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: Construct code in MainPage to share data between pages.

14

Lab Answer Key: Windows Phone DevelopmentFirst Look

6.

In the textBlock3_ManipulationStarted event handler method, after the located comment, assign the value of the Text property of the player1TextBox to the FirstPlayerTextString property in the App class. In the textBlock3_ManipulationStarted method, after the located comment, add the following code.
[Visual Basic] CType(Application.Current, App).FirstPlayerTextString = player1TextBox.Text.ToString

[Visual C#] (Application.Current as App).FirstPlayerTextString = player1TextBox.Text.ToString();

7.

In the MainPage.xaml.vb or MainPage.xaml.cs file, locate the TODO comment, In MainPage assign the value of the shared data (FirstPlayerTextString) to nameString below, in the OnNavigatedTo event handler. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: In MainPage assign the value of the shared data (FirstPlayerTextString) to nameString below.

8.

In the OnNavigatedTo event handler method, after the located comment, assign the value of the FirstPlayerTextString property in the App class to the Text property of the player1TextBox. In the OnNavigatedTo method, after the located comment, modify the line of code that assigns an empty string to the local nameString variable so it resembles the following code.
[Visual Basic] Dim nameString As String = CType(Application.Current, App).FirstPlayerTextString

[Visual C#] string nameString = (Application.Current as App).FirstPlayerTextString;

9.

In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, assign the value of the shared data (FirstPlayerTextString) to nameString below, in the OnNavigatedTo event handler. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: assign the value of the shared data (FirstPlayerTextString) to nameString below.

10. In the OnNavigatedTo event handler method, after the located comment, assign the value of the FirstPlayerTextString property in the App class to the Text property of the player1TextBox. In the OnNavigatedTo method, after the located comment, modify the line of code that assigns an empty string to the local nameString variable so it resembles the following code.
[Visual Basic] Dim nameString As String = CType(Application.Current, App).FirstPlayerTextString

[Visual C#] string nameString = (Application.Current as App).FirstPlayerTextString;

Lab Answer Key: Windows Phone DevelopmentFirst Look

15

11. In the AdvancedGamePlay.xaml.vb or AdvancedGamePlay.xaml.cs file, locate the TODO comment, Create a DispatcherTimer to monitor the game status, in the constructor. Use the Task List window to locate the comment. In the Task List window, double-click the row with the text, TODO: Create a DispatcherTimer to monitor the game status.

12. In the constructor, after the located comment, create the variable property of monitorGameStatusDispatcherTimer as a new instance of DispatcherTimer. Set the Interval property of property of monitorGameStatusDispatcherTimer to 34 milliseconds using a new TimeSpan object. Wire up the existing MonitorGameStatus method to the Tick event of monitorGameStatusDispatcherTimer. Start monitorGameStatusDispatcherTimer. In the constructor, after the located comment, add the following code.
[Visual Basic] monitorGameStatusDispatcherTimer = New DispatcherTimer() monitorGameStatusDispatcherTimer.Interval = New TimeSpan(0, 0, 0, 0, 34) ' 34 Milliseconds AddHandler monitorGameStatusDispatcherTimer.Tick, New EventHandler(AddressOf MonitorGameStatus) monitorGameStatusDispatcherTimer.Start()

[Visual C#] monitorGameStatusDispatcherTimer = new DispatcherTimer(); monitorGameStatusDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 34); // 34 Milliseconds monitorGameStatusDispatcherTimer.Tick += new EventHandler(MonitorGameStatus); monitorGameStatusDispatcherTimer.Start();

Task 2: Play the game.


1. Run the application. Press Ctrl+F5.

The Windows Phone emulator opens. It may take a while before your application is deployed, loaded, and displayed. 2. 3. 4. 5. Click the Player 1 text box. In the Player 1 text box, type Student by using the SIP keyboard. Click the application background to close the SIP keyboard. Switch to the advanced level. 6. 7. Click Go To Advanced Level.

Notice how the Student name has been copied across from the MainPage and is now stored in the Player 1 text box. In the game pad, click any of the squares, separated by a dashed line, to start the game. Notice how the application automatically selects a box. This time, the application selection is more advanced; it is actually trying to win. You, as Player 1, use the X as the symbol for a selected box, whereas the application or computer as Player 2 uses the O symbol.

16

Lab Answer Key: Windows Phone DevelopmentFirst Look

8.

Keep playing till you win, draw, or lose. Notice that if you draw, the message box pops up with the winning message. If you win or lose, you will see a message box stating whether the X's or O's win. In addition, notice the straight line being drawn across the three winning squares. Close the message box. Notice the new message box, prompting you to play another game.

9.

10. Cancel a new game. In the message box, click cancel.

11. Switch to the basic level. Click Back To Easy Level.

12. Close the Windows Phone 7 emulator. In the Windows Phone 7 emulator toolbar, click the Close button

13. Close all applications. You have now completed this lab.

You might also like