silverlight 2 hands-on lab · silverlight 2.0 beta2 runtime b. silverlight 2.0 beta 2 sdk c....

24
Page 1 of 24 Silverlight 2 Hands-on Lab Working with Layout and Data Contents Set up ........................................................................................................................................................ 2 Exercise 1: Use LINQ to XML to display a product ................................................................................... 2 Exercise 2: Binding Data ......................................................................................................................... 10 Exercise 3: Add a UserControl defined in a different XAML file ............................................................ 14 Exercise 4: Integrate with a WCF web service ....................................................................................... 19 Additional Resources and Labs ............................................................................................................... 24

Upload: others

Post on 26-Sep-2020

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 1 of 24

Silverlight 2 Hands-on Lab

Working with Layout and Data

Contents Set up ........................................................................................................................................................ 2

Exercise 1: Use LINQ to XML to display a product ................................................................................... 2

Exercise 2: Binding Data ......................................................................................................................... 10

Exercise 3: Add a UserControl defined in a different XAML file ............................................................ 14

Exercise 4: Integrate with a WCF web service ....................................................................................... 19

Additional Resources and Labs ............................................................................................................... 24

Page 2: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 2 of 24

Silverlight 2 Hands-on Labs

Set up Install the following software components on Windows Vista machine with at least 2GB RAM:

1. Visual Studio 2008

2. SQL Server 2008 Express

a. AdventureWorks Sample Database (http://www.codeplex.com/MSFTDBProdSamples)

3. ASP.NET Extensions preview (http://asp.net/downloads/3.5-extensions/)

4. Silverlight Developer Tools (http://silverlight.net/GetStarted)

a. Silverlight 2.0 beta2 runtime

b. Silverlight 2.0 beta 2 SDK

c. Silverlight 2.0 templates for Visual Studio 2008

d. Expression Blend 2.5 June 2008 preview

Exercise 1: Use LINQ to XML to display a product Description: In this exercise we will build an application that will search for product inventory reorder

information queried from a local XML document. The completed screen will look like the one shown

below (user clicked Search by SKU input E8-5666 as the SKU Click Search):

Page 3: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 3 of 24

1. Create a project with Silverlight Application Visual Studio 2008 template and name it SL2LinqToXml.

One of the dialogue boxes will look like below:

2. The completed project will look like the solution explorer image shown below:

3. Add a reference to System.Xml.Linq.dll as we will use LINQ later in the lab.

Page 4: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 4 of 24

4. In this step we will edit Page.xaml to make the screen look like the following:

Through a series steps we will add various XML fragments build the above view

a. Replace the default UserControl definition with the following fragment:

<!-- Frag#1 replace the UserControl--> <UserControl x:Class="SL2LinqToXml.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Width="479" Height="381" >

<!-- Insert Fragment #2 -->

</UserControl>

b. Surround the default <Grid/> with a <Border/> element and add the three row

definitions as below:

<!-- Frag#2: Define top level grid with border -->

<Border Background="#FFACEA84" BorderBrush="Beige" BorderThickness="2"

CornerRadius="10">

<Grid x:Name="LayoutRoot">

<Grid.RowDefinitions>

<RowDefinition Height="Auto" MinHeight="61.876" />

<RowDefinition Height="Auto" MinHeight="34.903" />

<RowDefinition Height="Auto" MinHeight="0" />

</Grid.RowDefinitions>

<!-- Insert Frag #3 for Row 1 -->

<!-- Insert Frag #4 for Row 2 -->

<!-- Insert Frag #5 for Row 3 -->

</Grid>

</Border>

c. Add a TextBlock to display the header in the first row of the grid… use the following XAML

fragment:

Page 5: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 5 of 24

<!-- Frag#3 Define title for row 1-->

<TextBlock Text="Inventory Manager" HorizontalAlignment="Center"

Margin="10,20" FontFamily="Verdana" FontSize="18"

FontWeight="Bold" Foreground="#FFD25820" Grid.Row="0" />

d. Add a StackPanel and “Search by SKU” and “Search by Name” RadioButtons to 2nd row of the grid… use the following XAML fragment:

<!-- Frag#4: Define menu for row 2 --> <StackPanel Grid.Row="1" HorizontalAlignment="Center"

Orientation="Horizontal" Margin="10">

<RadioButton Content="Search by SKU" x:Name="radioSearchBySku"

GroupName="SearchGroup" IsChecked="true" FontWeight="Bold" FontSize="16"

Foreground="Teal" Click="radioSearchBySku_Click"/>

<RadioButton Content="Search by Name" x:Name="radioSearchByName"

GroupName="SearchGroup" Margin="25,0,0,0" FontWeight="Bold"

Foreground="Teal" FontSize="16" Click="radioSearchByName_Click"/>

</StackPanel>

e. Now we will assemble the 3rd row of the grid to display search input as well as the search results. The entire 3rd row will be contained inside a Canvas as we need control over positioning of various elements. Add the following <Canvas/> element and the search input elements:

<!-- Frag#5: Define canvas for row 3--> <Canvas Height="250" Margin="36,0,23,-258" VerticalAlignment="Bottom"

Grid.Row="2" x:Name="canvasSearchBySku">

<TextBox Height="25" Width="200" Canvas.Left="89" Canvas.Top="20"

FontSize="12" x:Name="textSku"/>

<HyperlinkButton x:Name="linkSearch" Height="20" Width="61"

Canvas.Left="295" Canvas.Top="23" Content="Search" Foreground="Brown"

FontWeight="Bold" FontSize="14" Click="linkSearchNow_Click" />

<!-- Insert Frag #6 -->

</Canvas>

The user will input the search information (e.g. SKU) into a text box and click the HyperlinkButton.

f. Add the following XAML markup to display the single product returned by “Search by SKU” option:

<!-- Frag#6: Define details grid --> <Border x:Name="borderInventoryView" Background="Yellow" Canvas.Left="50"

Canvas.Top="60" CornerRadius="10" BorderThickness="2" BorderBrush="Blue"

Visibility="Collapsed">

<Grid x:Name="gridInventoryDetails" Margin="10,5">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="Auto"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

Page 6: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 6 of 24

<RowDefinition Height="Auto"/>

</Grid.RowDefinitions>

<!-- Insert Frag #7 -->

</Grid>

</Border>

The above markup will add a canvas with a yellow border and a grid with 2 columns x 6 rows. The grid will be filled with mark up for displaying product information. By default, the border will be in a collapsed mode and hence not part of the rendered control tree. When Search link is clicked the borderInventoryView will be displayed. Add the following XAML fragment to the grid (gridInventoryDetails) mark up to complete the details pane:

<!-- Frag#7: Define details controls -->

<TextBlock Text="Product ID: " Grid.Row="0" Grid.Column="0"/>

<TextBlock x:Name="textProductID" Width="150" Grid.Row="0" Grid.Column="1"

Text=""/>

<TextBlock Text="Product Name: " Grid.Row="1" Grid.Column="0"/>

<TextBlock x:Name="textProductName" Width="150" Grid.Row="1" Grid.Column="1"

Text=""/>

<TextBlock Text="Product Number: " Grid.Row="2" Grid.Column="0"/>

<TextBlock x:Name="textProductNumber" Width="150" Grid.Row="2" Grid.Column="1"

Text=""/>

<TextBlock Text="Safety Stock Level: " Grid.Row="3" Grid.Column="0"/>

<TextBlock x:Name="textSafetyStockLevel" Width="150" Grid.Row="3"

Grid.Column="1" Text=""/>

<TextBlock Text="Reorder Point: " Grid.Row="4" Grid.Column="0"/>

<TextBlock x:Name="textReorderPoint" Width="150" Grid.Row="4" Grid.Column="1"

Text=""/>

The completed skeletal markup hierarchy will like the one below:

<UserControl x:Class="SL2LinqToXml.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:inv="clr-namespace:SL2LinqToXml"

Width="479" Height="381" >

<!-- Frag#2: Define top level grid with border -->

<Border Background="#FFACEA84" BorderBrush="Beige" BorderThickness="2"

CornerRadius="10">

<Grid x:Name="LayoutRoot">

<Grid.RowDefinitions>

<RowDefinition Height="Auto" MinHeight="61.876" />

<RowDefinition Height="Auto" MinHeight="34.903" />

<RowDefinition Height="Auto" MinHeight="0" />

</Grid.RowDefinitions>

<!-- Frag#3 Define title for row 1-->

<TextBlock Text="Inventory Manager" HorizontalAlignment="Center"

Margin="10,20" FontFamily="Verdana" FontSize="18" FontWeight="Bold"

Foreground="#FFD25820" Grid.Row="0" />

<StackPanel Grid.Row="1" HorizontalAlignment="Center"

Orientation="Horizontal" Margin="10">

<RadioButton Content="Search by SKU" x:Name="radioSearchBySku"

GroupName="SearchGroup" IsChecked="true" FontWeight="Bold" FontSize="16"

Foreground="Teal" Click="radioSearchBySku_Click"/>

<RadioButton Content="Search by Name"

x:Name="radioSearchByName" GroupName="SearchGroup" Margin="25,0,0,0"

Page 7: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 7 of 24

FontWeight="Bold" Foreground="Teal" FontSize="16"

Click="radioSearchByName_Click"/>

</StackPanel>

<Canvas Height="250" Margin="36,0,23,-258"

VerticalAlignment="Bottom" Grid.Row="2" x:Name="canvasSearchBySku">

<TextBox Height="25" Width="200" Canvas.Left="89"

Canvas.Top="20" FontSize="12" x:Name="textSku"/>

<HyperlinkButton x:Name="linkSearch" Height="20" Width="61"

Canvas.Left="295" Canvas.Top="23" Content="Search" Foreground="Brown"

FontWeight="Bold" FontSize="14" Click="linkSearchNow_Click" />

<Border x:Name="borderInventoryView" Background="Yellow"

Canvas.Left="50" Canvas.Top="60" CornerRadius="10" BorderThickness="2"

BorderBrush="Blue" Visibility="Collapsed">

<Grid x:Name="gridInventoryDetails" Margin="10,5">

<Grid.ColumnDefinitions>

<ColumnDefinition Width="Auto"/>

<ColumnDefinition Width="Auto"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

<RowDefinition Height="Auto"/>

</Grid.RowDefinitions>

<TextBlock Text="Product ID: " Grid.Row="0"

Grid.Column="0"/>

<TextBlock x:Name="textProductID" Width="150"

Grid.Row="0" Grid.Column="1" Text="{Binding ProductID}"/>

<TextBlock Text="Product Name: " Grid.Row="1"

Grid.Column="0"/>

<TextBlock x:Name="textProductName" Width="150"

Grid.Row="1" Grid.Column="1" Text="{Binding ProductName}"/>

<TextBlock Text="Product Number: " Grid.Row="2"

Grid.Column="0"/>

<TextBlock x:Name="textProductNumber" Width="150"

Grid.Row="2" Grid.Column="1" Text="{Binding ProductNumber}"/>

<TextBlock Text="Safety Stock Level: " Grid.Row="3"

Grid.Column="0"/>

<TextBlock x:Name="textSafetyStockLevel" Width="150"

Grid.Row="3" Grid.Column="1" Text="{Binding ProductSafetyStockLevel}"/>

<TextBlock Text="Reorder Point: " Grid.Row="4"

Grid.Column="0"/>

<TextBlock x:Name="textReorderPoint" Width="150"

Grid.Row="4" Grid.Column="1" Text="{Binding ProductReorderPoint}"/>

</Grid>

</Border>

<Border x:Name="borderInventoryTableView" Background="Yellow"

Canvas.Left="0"

Canvas.Top="60" CornerRadius="10" BorderThickness="2"

BorderBrush="Blue"

Visibility="Collapsed">

<inv:ProductListView x:Name="dataGridProductList"/>

</Border>

</Canvas>

</Grid>

</Border>

</UserControl>

Page 8: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 8 of 24

5. Add the event handler code below the Page() constructor in Page.xaml.cs as shown below:

// Frag#8: Change event handler code

private void linkSearchNow_Click(object sender, RoutedEventArgs e)

{

this.borderInventoryView.Visibility = Visibility.Visible;

}

private void radioSearchBySku_Click(object sender, RoutedEventArgs e)

{

if (this.textSku.Text.Length > 0)

this.borderInventoryView.Visibility = Visibility.Visible;

}

private void radioSearchByName_Click(object sender, RoutedEventArgs

e)

{

this.borderInventoryView.Visibility = Visibility.Collapsed;

}

Page 9: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 9 of 24

6. Compile and test SL2LinqToXmal application by browsing SL2LinqToXmlTestPage.html page from the project SL2Main_Web project. The display will be as shown below:

7. Enter the product sku(EB-5866) and click Search. The screen display will look like this:

Page 10: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 10 of 24

Exercise 2: Binding Data We have a problem with the data display in the details screen. We will fix this issue by adding the data binding logic using data in an XML file and LINQ to XML to query that data. 8. Data bind TextBlock.Text property of various TextBlock contained inside gridInventoryDetails per

this table:

TextBlock name Data binding value textProductID {Binding ProductID} textProductName {Binding ProductName} textProductNumber {Binding ProductNumber} textSafetyStockLevel {Binding ProductSafetyStockLevel} textReorderPoint {Binding ProductReorderPoint}

As an example, the XAML should look like:

<TextBlock x:Name="textProductID" Width="150"

Grid.Row="0" Grid.Column="1" Text="{Binding ProductID}"/>

9. We need a class that defines our product data coming from our data source. Add ProductInfo class

into SL2LinqToXml project as shown below:

//Frag#9: Add ProductInfo.cs

using System;

namespace SL2LinqToXml

{

public class ProductInfo

{

public int _productID;

public string _productName;

public string _productNumber;

public int _productSafetyStockLevel;

public int _productReorderPoint;

public int ProductID

{

get { return this._productID; }

set { this._productID = value; }

}

public string ProductName

{

get { return this._productName; }

set { this._productName = value; }

}

public string ProductNumber

{

get { return this._productNumber; }

set { this._productNumber= value; }

}

public int ProductSafetyStockLevel

{

get { return this._productSafetyStockLevel; }

set { this._productSafetyStockLevel = value; }

}

public int ProductReorderPoint

{

get { return this._productReorderPoint; }

set { this._productReorderPoint = value; }

}

Page 11: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 11 of 24

}

}

10. We’ll use static data here for now, so let’s add some XML. Add Products.xml file to the SL2LinqToXml project:

<?xml version="1.0" encoding="utf-8" ?>

<!--Frag#11: Add Products.xml to the project -->

<products>

<product ProductID="1" ProductName="Adjustable Race" ProductNumber="AR-5381"

ProductSafetyStockLevel="1000" ProductReorderPoint="750"/>

<product ProductID="2" ProductName="Bearing Ball" ProductNumber="BA-8327"

ProductSafetyStockLevel="1000" ProductReorderPoint="750"/>

<product ProductID="3" ProductName="BB Ball Bearing" ProductNumber="BE-2349"

ProductSafetyStockLevel="800" ProductReorderPoint="600"/>

<product ProductID="4" ProductName="Headset Ball Bearings" ProductNumber="BE-

2908"

ProductSafetyStockLevel="800" ProductReorderPoint="600"/>

<product ProductID="316" ProductName="Blade" ProductNumber="BE-2036"

ProductSafetyStockLevel="800" ProductReorderPoint="600"/>

<product ProductID="317" ProductName="LL Crankarm" ProductNumber="CA-5965"

ProductSafetyStockLevel="500" ProductReorderPoint="375"/>

<product ProductID="318" ProductName="ML Crankarm" ProductNumber="CA-6738"

ProductSafetyStockLevel="500" ProductReorderPoint="375"/>

<product ProductID="319" ProductName="HL Crankarm" ProductNumber="CA-7457"

ProductSafetyStockLevel="500" ProductReorderPoint="375"/>

<product ProductID="320" ProductName="Chainring Bolts" ProductNumber="CB-2903"

ProductSafetyStockLevel="1000" ProductReorderPoint="750"/>

<product ProductID="321" ProductName="Chainring Nut" ProductNumber="CN-6137"

ProductSafetyStockLevel="1000" ProductReorderPoint="750"/>

</products>

(Note: Products.XML will be downloaded as a part of SL2LinqToXml.xap to the web browser cache)

11. This helper class will enable us to retrieve certain fragments from our Silverlight package (XAP). Add PackageUtil class to the project and replace the default code with the following:

// Frag#12: Add SLUtil (Silverlight Library project)

using System;

using System.Collections.Generic;

using System.Windows;

using System.Windows.Markup;

using System.Windows.Resources;

using System.Reflection;

using System.Net;

using System.IO;

using System.Xml;

using System.Xml.Linq;

namespace SLUtil

{

public class PackageUtil

{

public static XElement GetXmlDocFromDefaultPackage(string fileName)

{

XmlReaderSettings settings = new XmlReaderSettings();

settings.XmlResolver = new XmlXapResolver();

XmlReader reader = XmlReader.Create("Products.xml");

//create an XmlElement from XmlReader

XElement element = XElement.Load(reader);

Page 12: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 12 of 24

return element;

}

}

}

12. Query inventory information from Products.xml using LINQ to XML. Add a DataUtil class to the project with the following code:

//Frag#13. Add DataUtil class to SL2LinqToXml project using System;

using System.Linq;

using System.Xml;

using System.Xml.Linq;

using System.Collections;

namespace SL2LinqToXml

{

public class DataUtil

{

public static ProductInfo GetInventoryInfo(string sku)

{

XElement e = PackageUtil.GetXmlDocFromDefaultPackage("Products.xml");

var products = from product in e.Elements("product")

where (string)product.Attribute("ProductNumber") == sku

select product;

if (products == null) return null;

XElement el = products.ElementAt<XElement>(0);

ProductInfo p = new ProductInfo

{

ProductID = (int)el.Attribute("ProductID"),

ProductName = (string)el.Attribute("ProductName"),

ProductNumber = (string)el.Attribute("ProductNumber"),

ProductSafetyStockLevel =

(int)el.Attribute("ProductSafetyStockLevel"),

ProductReorderPoint = (int)el.Attribute("ProductReorderPoint")

};

return p;

}

}

}

13. Add LINQ code to retrieve the ProductInfo object for the entered product ID and data bind it to gridInventoryDetails.

a. Replace linkSearchBySkuNow_Click handler code with the following:

//Frag#14: Add linkSearchBySkuNow_Click that calls DataUtil-->

private void linkSearchNow_Click(object sender, RoutedEventArgs e)

{

this.borderInventoryView.Visibility = Visibility.Visible;

ProductInfo p = DataUtil.GetInventoryInfo(this.textSku.Text);

this.gridInventoryDetails.DataContext = p;

}

(Note: The data binding logic automatically binds to the properties of the object assigned to the DataContext)

Page 13: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 13 of 24

14. Compile it and test the solution by entering various product SKUs.

Page 14: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 14 of 24

Exercise 3: Add a UserControl defined in a different XAML file Description: In this exercise we will implement a user control to display the multiple products returned

by Search by Name option. We will implement a separate UserControl to search by partial name and

data bind it the returned result to a user control located in a different C# file. Note: use clr-namespace

mapping in XAML.

1. Add a Silverlight User Control and name it ProductListView.xaml. The following images shows the dialog box:

2. Add System.Windows.Controls.Data.dll to project references. We will be using the DataGrid control in this exercise and the control exists in a different assembly.

3. Replace the default XAML content with the following XAML fragment:

<!--Frag#2 Replace the default UserControl definition--> <UserControl x:Class="SL2LinqToXml.ProductListView"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

>

<data:DataGrid x:Name="dataGridProductListBase"

Height="175" Width="400" VerticalAlignment="Top" Margin="5,5,5,5"

AutoGenerateColumns="True" />

</UserControl>

Note: The ProductListView UserControl will use DataGrid that is located inside System.Windows.Controls.Data.dll under System.Windows.Controls namespace. CLR objects from external names spaces require xmlns declaration (e.g. xmlns:data= "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data")

4. Add the ProductListView user control to the Page.xaml. This requires the following two steps:

a. Add the CLR namespace to the Page.xaml <UserControl/> declaration as shown below:

<UserControl x:Class="SL2LinqToXml.Page"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:inv="clr-namespace:SL2LinqToXml"

Width="479" Height="381" >

Page 15: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 15 of 24

b. Add ProductListView to borderInventoryTableView(created in Step 1) as shown below:

<Canvas>

<Border x:Name="borderInventoryView" .....>

<Grid x:Name="gridInventoryDetails".....>

</Grid>

</Border>

<!--Frag#4 Add detail Border to the Canavas-->

<Border x:Name="borderInventoryTableView" Background="Yellow" Canvas.Left="0"

Canvas.Top="60" CornerRadius="10" BorderThickness="2" BorderBrush="Blue"

Visibility="Collapsed">

<inv:ProductListView x:Name="dataGridProductList"/>

</Border>

</Canvas>

Note: note the inv: prefix that was declared in the UserControl header

5. Add a ResetDisplay() function Page.Xaml.cs:

//Frag#5 Add ResetDisplay to Page.xaml.cs private void ResetDisplay()

{

if (this.textSku.Text.Length > 0)

{

if (this.radioSearchBySku.IsChecked == true)

{

this.borderInventoryView.Visibility = Visibility.Visible;

this.borderInventoryTableView.Visibility = Visibility.Collapsed;

}

else

{

this.borderInventoryView.Visibility = Visibility.Collapsed;

this.borderInventoryTableView.Visibility = Visibility.Visible;

}

}

else

{

this.borderInventoryView.Visibility = Visibility.Collapsed;

this.borderInventoryTableView.Visibility = Visibility.Collapsed;

}

}

6. Change the click hander code for partial product name search by adding the SL2LinqToXml project’s

Page.xaml.cs the following code:

//Frag#6 Change SearchBySkuNow_click handler to to call

DataUtil.GetInventoryByName private void linkSearchNow_Click(object sender, RoutedEventArgs e)

{

ResetDisplay();

if (this.radioSearchBySku.IsChecked == true)

{

ProductInfo p = DataUtil.GetInventoryInfo(this.textSku.Text);

this.gridInventoryDetails.DataContext = p;

Page 16: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 16 of 24

}

else

{

this.dataGridProductList.DataContext =

DataUtil.GetInventoryInfoByName(this.textSku.Text);

}

}

Note: The above code won’t compile yet as DataUtil.GetInventoryInfo() doesn’t exist yet.

7. Add GetInventoryInfo to DataUtil.cs file per the following code fragment:

public static IEnumerable<ProductInfo> GetInventoryInfoByName(string productName)

{

List<ProductInfo> productData = GetSampleData();

var products = from product in productData

where product.ProductName.StartsWith(productName)

select product;

return products;

}

Note: GetSampleData() will return a list of ProductInfo objects for testing purposes. In subsequent

exercises, this will be replaced with web service calls.

8. Add GetSampleData() method to DataUtil.cs to complete the exercise. The Following is a partial list

of the GetSampleData() method implementation:

public static List<ProductInfo> GetSampleData()

{

List<ProductInfo> products = new List<ProductInfo>();

products.Add(new ProductInfo { ProductID = 1, ProductName = "Adjustable Race",

ProductNumber = "AR-5381", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 2, ProductName = "Bearing Ball",

ProductNumber = "BA-8327", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 3, ProductName = "BB Ball Bearing",

ProductNumber =

"BE-2349", ProductSafetyStockLevel = 800, ProductReorderPoint

= 600 });

products.Add(new ProductInfo { ProductID = 4, ProductName = "Headset Ball Bearings",

ProductNumber

= "BE-2908", ProductSafetyStockLevel = 800,

ProductReorderPoint = 600 });

products.Add(new ProductInfo { ProductID = 327, ProductName = "Down Tube",

ProductNumber =

"DT-2377", ProductSafetyStockLevel = 800, ProductReorderPoint

= 600 });

products.Add(new ProductInfo { ProductID = 328, ProductName = "Mountain End Caps",

ProductNumber =

"EC-M092", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 371, ProductName = "Thin-Jam Hex Nut 7",

ProductNumber =

Page 17: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 17 of 24

"HJ-7161", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 372, ProductName = "Thin-Jam Hex Nut 8",

ProductNumber =

"HJ-7162", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 373, ProductName = "Thin-Jam Hex Nut 12",

ProductNumber

= "HJ-9080", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

products.Add(new ProductInfo { ProductID = 374, ProductName = "Thin-Jam Hex Nut 11",

ProductNumber

= "HJ-9161", ProductSafetyStockLevel = 1000,

ProductReorderPoint = 750 });

return products;

}

Note: this is merely a method used to represent sample data. In a later step it will be replaced to use

data from a SQL Server Express database.

9. Compile and test the application to query various part names. Select Search by Name option and

enter “Thin” in the input field and click Search.

Page 18: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 18 of 24

There is a problem with the above display… no data! The DataContext is not flowing into the

ProductListView user control. Set the ItemSource property to the <data:DataGrid/> definition :

ItemsSource="{Binding}"

Also note the data binding syntax (ItemsSource="{Binding}")… DataGrid uses ItemSource property for

data binding and the DataContext property will be ignored unless data binding is indicated through

ItemSource. Test the code again with “Thin” as the search input… if the following screen is displayed,

the system is working:

Page 19: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 19 of 24

Exercise 4: Integrate with a WCF web service Description: Create a web service to search for the inventory information of a product from

AdventureWorks database, LINQ and WCF. Consume this service in displaying product inventory

information for Search by SKU and Search by Name options.

1. Add new project to the solution and name it SL2Services_Web using “ASP.NET Web Application”

template. The Solution Explorer view should look like the one below:

2. Add WCF Service and call the file InventoryManager.svc

3. Add ProductInfo DataContract to InventoryManager.svc.cs using the following fragment:

//Frag#2: Create ProductInfo [DataContract] inside InventoryManager.svc.cs

[DataContract]

public class ProductInfo

{

[DataMember]

public int ProductID;

[DataMember]

public string ProductName;

[DataMember]

public string ProductNumber;

[DataMember]

public int ProductSafetyStockLevel;

[DataMember]

public int ProductReorderPoint;

}

Page 20: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 20 of 24

4. Add two interface methods for IInventoryManager.cs as follows:

[OperationContract]

List<ProductInfo> GetInventoryBySku(string sku);

[OperationContract]

List<ProductInfo> GetInventoryByName(string name);

5. Provide the empty implementation of the IInventoryManager interface inside InventoryManager.svc.cs:

//Frag#4: Provide empty IInventoryManager implementation inside

// InventoryManager.svc.cs

public class InventoryManager : IInventoryManager

{

#region IInventoryManager Members

public List<ProductInfo> GetInventoryBySku(string sku)

{

throw new NotImplementedException();

}

public List<ProductInfo> GetInventoryByName(string name)

{

throw new NotImplementedException();

}

#endregion

}

6. Because this service will be on a site different than where our Silverlight application is hosted, we

need a cross-domain policy file to authorize Silverlight to access the service. Add a file named clientaccesspolicy.xml to the WCF service project and put the following code in it:

<?xml version="1.0" encoding="utf-8" ?>

<access-policy>

<cross-domain-access>

<policy>

<allow-from http-request-headers="*">

<domain uri="*"/>

</allow-from>

<grant-to>

<resource include-subpaths="true" path="/"/>

</grant-to>

</policy>

</cross-domain-access>

</access-policy>

7. Set up SQL Server Express with mixed mode authentication and add the following user:

User Id: test Password: Pass@word1

8. Add AdventureWorks data connection to the Server Explorer inside Visual Studio 2008. (Note: ViewServer Explorer)

9. Add AdventureWorks.dbml to the SL2Services_Web project using “LINQ to SQL Classes” template in Visual Studio 2008.

Page 21: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 21 of 24

10. Open AdventureWorks.dbml in design mode and drag and drop the Product and ProductInventory tables and retain only the properties shown in the picture.

11. Implement GetInventoryBySku() as shown below:

//Frag#7: Implement GetInventoryBySku using LINQ in InventoryManager.svc.cs

public List<ProductInfo> GetInventoryBySku(string sku)

{

string constr =

ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"]

.ConnectionString;

AdventureWorksDataContext advDC = new AdventureWorksDataContext(constr);

IEnumerable<ProductInfo> products = from p in advDC.Products

where p.ProductNumber.StartsWith(sku)

select new ProductInfo

{

ProductID = p.ProductID,

ProductName = p.Name,

ProductNumber = p.ProductNumber,

ProductReorderPoint = p.ReorderPoint,

ProductSafetyStockLevel = p.SafetyStockLevel

};

return new List<ProductInfo>(products);

}

12. Implement GetInventoryByName() using the following code fragment:

//Frag#8: Implement GetInventoryByName using LINQ in InventoryManager.svc.cs

public List<ProductInfo> GetInventoryByName(string name)

{

string constr =

ConfigurationManager.ConnectionStrings["AdventureWorksConnectionString"]

Page 22: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 22 of 24

.ConnectionString;

AdventureWorksDataContext advDC = new AdventureWorksDataContext(constr);

IEnumerable<ProductInfo> products =

from p in advDC.Products

where p.Name.StartsWith(name)

select new ProductInfo

{

ProductID = p.ProductID,

ProductName = p.Name,

ProductNumber = p.ProductNumber,

ProductReorderPoint = p.ReorderPoint,

ProductSafetyStockLevel = p.SafetyStockLevel

};

List<ProductInfo> pList = new List<ProductInfo>(products);

return pList;

}

13. Edit web.config file to replace wsHttpBinding with basicHttpBinding for the service endpoint

binding. 14. Compile SL2Services_Web project , right click on InventoryManager.svc and browse.

(Note: this will start the test web server on a random port. If service works, it will display a WSDL link.)

15. Add a service reference to the InventoryManager WCF service in the SL2LinqToXml project and use InventoryProxy as the namespace. In the SL2LinqToXml project choose Add Service Reference from the right-click menu on the project and then you can click Discover to locate the service in your local solution.

16. Replace linkSearchNow_Click to call InventoryManager service with the following code:

private void linkSearchNow_Click(object sender, RoutedEventArgs e)

{

InventoryProxy.InventoryManagerClient inv = new

InventoryProxy.InventoryManagerClient();

if (this.radioSearchBySku.IsChecked == true)

{

inv.GetInventoryBySkuCompleted += new

EventHandler<InventoryProxy.GetInventoryBySkuCompletedEventArgs>

(inv_GetInventoryBySKUCompleted);

inv.GetInventoryBySkuAsync(textSku.Text);

}

else

{

inv.GetInventoryByNameCompleted += new

EventHandler<InventoryProxy.GetInventoryByNameCompletedEventArgs>

(inv_GetInventoryByNameCompleted);

inv.GetInventoryByNameAsync(textSku.Text);

}

}

17. The above linkSearchNow_Click implementation requires inv_GetInventoryBySKUCompleted and

inv_GetInventoryByNameCompleted delegate implementations. Add the following code to Page.xaml.cs:

Page 23: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 23 of 24

void inv_GetInventoryByNameCompleted(object sender,

SL2LinqToXml.InventoryProxy.GetInventoryByNameCompletedEventArgs e)

{

ResetDisplay();

if (e.Error == null)

{

dataGridProductList.dataGridProductListBase.DataContext = e.Result;

}

}

void inv_GetInventoryBySkuCompleted(object sender,

SL2LinqToXml.InventoryProxy.GetInventoryBySkuCompletedEventArgs e)

{

ResetDisplay();

if (e.Error == null)

{

gridInventoryDetails.DataContext = e.Result[0];

}

}

18. Compile and test the solution with PE-2349 as the SKU and “Thin” as the Name.

Page 24: Silverlight 2 Hands-on Lab · Silverlight 2.0 beta2 runtime b. Silverlight 2.0 beta 2 SDK c. Silverlight 2.0 templates for Visual Studio 2008 d. Expression Blend 2.5 June 2008 preview

Page 24 of 24

Additional Resources and Labs Be sure to visit the Silverlight community site at http://silverlight.net to learn more about Silverlight 2,

access more hands-on labs, How-do-I videos and tutorials, and participate in the Forums to ask

questions (over 36,000 questions answered).