In this section you will add media playback functionality to your created Music and Video pages, add new pages to present pictures, and use WebBrowser controls.
Task 1 – Adding Media Element to Play Media Files
During this task, you will add two new pages to the project. These pages will be used to present video content and play music files attached to the lab.
- If not already open, launch Visual Studio 2010 Express for Windows Phone from
Start | All Programs | Microsoft Visual Studio 2010 Express | Microsoft Visual Studio 2010 Express for Windows Phone.
Note:Visual Studio 2010: Open Visual Studio 2010 from Start | All Programs | Microsoft Visual Studio 2010. - If you completed the steps in the previous exercise, you may continue with the solution that you created for that exercise; otherwise, open Begin.sln from Ex2-IntroductionToTheControls\Begin in the Source folder of the lab.
- Open the Default.xaml file from the Views\Video folder.
- Add the following markup snippet to the ContentPanel element:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <MediaElement x:Name="media" HorizontalAlignment="Stretch" AutoPlay="True" VerticalAlignment="Stretch" Stretch="Uniform" /> </Grid>
Horizontal and Vertical Alignment properties get or set the alignment characteristics applied to a FrameworkElement when it is composed within a layout parent, such as a panel or items control. Values include Left, Center, Right, Stretch for HorizontalAlignment, and Top, Center, Bottom, and Stretch for VerticalAlignment. The Stretch property stretches the element to fill the entire layout slot of the parent element.
The Stretch property is very important when using media elements such as Image. Stretch determines how content is resized to fill its allocated space. Possible options for Stretch are:
- None - The content preserves its original size
- Fill - The content is resized to fill the destination dimensions without preserving the aspect ratio
- Uniform - The content is resized to fit in the destination dimensions while it preserves its native aspect ratio
- UniformToFill - The source content is resized to fill the destination dimensions while it preserves its native aspect ratio and, if necessary, is cropped to fit in the destination dimensions
Note:Alternatively you could use interactive design surface to add the MediaElement. To do this, open the Controls Toolbox, select the MediaElement from the list and drag it onto the design surface. - Open the Default.xaml code-behind.
Note:To open the code-behind file, right-click on the XAML file in Solution Explorer and select View Code. - Now you need to update the source of the added media element according to the parameters received from the navigation services. To do this, first subscribe to the page's
Loaded event. Add the following code to the constructor code after the call to the
InitializeComponent function:
public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); } - Add the following event handler function:
private void Default_Loaded(object sender, RoutedEventArgs e) { }
Note:You could make Visual Studio 2010 render the default event handler by pressing the Tab key twice after += in the event subscription. - Add the following code to the event handler function:
(Code Snippet – Navigation and Controls – Ex2 Task 1 Step 8 – Video Default_Loaded event handler code)
private void Default_Loaded(object sender, RoutedEventArgs e) { if (NavigationContext.QueryString.Count > 0) { try { media.Source = new Uri(NavigationContext.QueryString.Values.First(), UriKind.RelativeOrAbsolute); media.Position = TimeSpan.FromMilliseconds(0); media.Play(); } catch (Exception ex) { //handle the exception; } } } - Modify the Default.xaml file in the Music folder. Locate the “ContentPanel” element and add the following markup:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <MediaElement x:Name="media"/> <TextBlock x:Name="musicToPlay" Style="{StaticResource PhoneTextNormalStyle}"/> </Grid> - Open the code-behind file in order to modify it.
- Subscribe to the Loaded event of the page. Add the following code to the constructor code after the call to the
InitializeComponent function:
public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); } - Add the following event handler function:
private void Default_Loaded(object sender, RoutedEventArgs e) { }
Note:You can make Visual Studio 2010 generate the default event handler by pressing the Tab key twice after += in event subscription - Add the following code to the event handler function created before:
(Code Snippet – Navigation and Controls – Ex2 Task 1 Step 13 – Music Default_Loaded event handler code)
private void Default_Loaded(object sender, RoutedEventArgs e) { if (NavigationContext.QueryString.Count > 0) { this.musicToPlay.Text = this.NavigationContext.QueryString.Values.First(); try { media.AutoPlay = true; media.Source = new Uri(NavigationContext.QueryString.Values.First(), UriKind.RelativeOrAbsolute); media.Position = TimeSpan.FromMilliseconds(0); media.Play(); } catch (Exception ex) { //handle the exception; } } } - Compile and run the application. Navigate to the Video and/or Music pages to make sure it works.

Figure 22 Video page
- Stop the debugging and return to editing the application.
- During this task, you added two pages to the application, hooked up to the page's Loaded event, and created application logic based on provided query string parameters.
Task 2 – Using a ListBox to Display Images
During this task you will create a new page to present pictures included within the application. The pictures will be presented in the ListBox control. Later during the lab you will create a PictureView page to present detailed single pictures.
Note: |
|---|
| The current build doesn’t support the functionality of acquiring pictures from the phone picture hub, phone storage, or the phone camera. This will change in later versions. |
In this task you also will add a new Page to display pictures. The pictures will be displayed in a ListBox control.
- Add a new Default.xaml page to the Pictures folder.
- Change the TitlePanel according to the following markup snippet:
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12"> <TextBlock Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock Text="Images" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> - Add the following markup to the ContentPanel element:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal" Margin="5"> <Button x:Name="btnRemoveSelection" Content="Remove Image" Click="btnRemoveSelection_Click" IsEnabled="False"/> </StackPanel> <ListBox x:Name="lstPictures" Width="450" Height="520" Margin="10" SelectionChanged="lstPictures_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Image}" Width="100" Stretch="Uniform" HorizontalAlignment="Center"/> <TextBlock Text="{Binding Filename}" TextWrapping="Wrap" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Grid>This snippet adds Button and ListBox controls. The ListBox defines the DataTemplate for ListBox items. DataTemplate uses the DataBinding mechanism to resolve the data value at runtime.
- At this stage, the page design should look like:

Figure 23 Images page design
- Open the code-behind file.
Note:To open the code-behind file, right-click on the XAML file in Solution Explorer and select View Code. - Add following namespace directives at the top of the file:
using System.Collections.ObjectModel; using WindowsPhoneNavigation.Misc;
- In order to use the data binding mechanism with collections and receive notifications when collections change, Silverlight uses events. The event expected by the data binding engine when a collection changes is CollectionChanged. It is defined as follows:
[code
lang="CSharp"]
event NotifyCollectionChangedEventHandler CollectionChanged;
[/code]
The collection implementation should raise this event on every collection change (Add/Edit/Remove collection members, members order change, etc.). This event is defined in the INotifyCollectionChanged interface. To have data binding automatic updates on collection, you should create your own collection and implement this interface. Alternatively, you could use collections provided within the Silverlight class library which already implements this interface. Silverlight provides two classes/collections that implement the interface: ObservableCollection<T> and ReadOnlyObservableCollection<T>.
ObservableCollection - Represents a dynamic data collection that provides notifications when items get added, removed, or when the entire list is refreshed.
ReadOnlyObservableCollection - Represents a read-only ObservableCollection.
In both cases the data binding mechanism will respond to fired events by updating objects bound to the collection.
- Add an ObservableCollection object named photos, to bind images to the class.
public partial class Default : PhoneApplicationPage { ObservableCollection<Photo> photos = new ObservableCollection<Photo>(); public Default() { ... } } - Add an initialization function to initialize the photo collection.
(Code Snippet – Navigation and Controls – Ex2 Task 2 Step 9 – Photo Collection initialization method)
private void InitializePhotos() { photos.Add(new Photo() { Filename = "Butterfly.jpg", Image = Utils.GetImage("Butterfly.jpg") }); photos.Add(new Photo() { Filename = "Chrysanthemum.jpg", Image = Utils.GetImage("Chrysanthemum.jpg") }); photos.Add(new Photo() { Filename = "Desert.jpg", Image = Utils.GetImage("Desert.jpg") }); photos.Add(new Photo() { Filename = "Field.jpg", Image = Utils.GetImage("Field.jpg") }); photos.Add(new Photo() { Filename = "Flower.jpg", Image = Utils.GetImage("Flower.jpg") }); photos.Add(new Photo() { Filename = "Hydrangeas.jpg", Image = Utils.GetImage("Hydrangeas.jpg") }); photos.Add(new Photo() { Filename = "Jellyfish.jpg", Image = Utils.GetImage("Jellyfish.jpg") }); photos.Add(new Photo() { Filename = "Koala.jpg", Image = Utils.GetImage("Koala.jpg") }); photos.Add(new Photo() { Filename = "Leaves.jpg", Image = Utils.GetImage("Leaves.jpg") }); photos.Add(new Photo() { Filename = "Lighthouse.jpg", Image = Utils.GetImage("Lighthouse.jpg") }); photos.Add(new Photo() { Filename = "Penguins.jpg", Image = Utils.GetImage("Penguins.jpg") }); photos.Add(new Photo() { Filename = "Rocks.jpg", Image = Utils.GetImage("Rocks.jpg") }); photos.Add(new Photo() { Filename = "Tulip.jpg", Image = Utils.GetImage("Tulip.jpg") }); photos.Add(new Photo() { Filename = "Tulips.jpg", Image = Utils.GetImage("Tulips.jpg") }); photos.Add(new Photo() { Filename = "Window.jpg", Image = Utils.GetImage("Window.jpg") }); } - Call the function from the page constructor and make initialized collection the ItemsSource of a ListBox:
public Default() { InitializeComponent(); InitializePhotos(); lstPictures.ItemsSource = photos; } - Add an event handler function to handle Remove Button Click event:
(Code Snippet – Navigation and Controls – Ex2 Task 2 Step 11 – Remove Button Click event handler)
private void btnRemoveSelection_Click(object sender, RoutedEventArgs e) { if (null != lstPictures.SelectedItem) photos.Remove(lstPictures.SelectedItem as Photo); } - Add an event handler function to handle ListBox SelectionChanged event:
(Code Snippet – Navigation and Controls – Ex2 Task 2 Step 12 – Pictures Listbox SelectionChanged event handler)
private void lstPictures_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (null != lstPictures.SelectedItem) { btnRemoveSelection.IsEnabled = true; } if (photos.Count == 0) btnRemoveSelection.IsEnabled = false; } - Open App.xaml and add the following object into the Application.Resources element, which points to the image's location:
<Application.Resources> ... <system:String x:Key="ImagesLocation">Assets/Images/</system:String> </Application.Resources>
- Change MainPage.xaml by adding a Hyperlink to a new page (after Videos, before About page):
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ScrollViewer BorderBrush="Transparent"> <StackPanel Margin="5"> ... <TextBlock Text="Images" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/Pictures" Content="Images" Style="{StaticResource PhoneHyperlinkStyle}"/> <TextBlock Text="About" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/About" Content="About" Style="{StaticResource PhoneHyperlinkStyle}"/> </StackPanel> </ScrollViewer> </Grid> - Compile and run the application. Navigate to the Images page and check its functionality.

Figure 24 Application after completing Task 2

Figure 25 Images Page
- Stop the debugging and return to editing the application.
During this task you created additional page to the application. At this new page you crated a ListBox to hold pictures provided with the lab assets. The ListBox was data bound to the ObservableCollection in order to achieve updates while adding/removing pictures to the collection. In addition you created a DataTemplate to present each item in a ListBox with title near the picture icon.
Task 3 – Building the Simplest Web Browser
- In this task you will add a new page with WebBrowser and some additional controls. All together those controls will compose simple Web browser interface.
- In this task you also will add a new WebBrowser Page that will be used to create a basic Web browser.
- Add a new Landscape page to the WebBrowser folder and name it Default.xaml.

Figure 1 Adding a Landscape page to the WebBrowser folder
- Change the TitlePanel content according to the markup snippet below:
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationName" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="ListName" Text="Web Browser" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> - Add the following markup snippet to the ContentPanel element, which contains the Web Browser control.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="80"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <TextBox x:Name="txtURL" Margin="5" Width="400"/> <Button Content="Go" Click="Button_Click"/> </StackPanel> <phone:WebBrowser Grid.Row="1" x:Name="wb" Margin="10"/> </Grid> </Grid>
- Design surface should look as follows:

Figure 27 WebBrowser page design
- Open the code-behind file for the page.
- Add the httpPrefix constant to the class.
public partial class Default : PhoneApplicationPage { private const string httpPrefix = "http://"; public Default() { ... } } - Subscribe to the Loaded event to handle navigation parameters. Add the following code to the class constructor:
public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); } - Create the appropriate event handler function and add business logic. The resulting code should look like:
(Code Snippet – Navigation and Controls – Ex2 Task 3 Step 8 – WebBrowser Loaded event handler)
private void Default_Loaded(object sender, RoutedEventArgs e) { if (NavigationContext.QueryString.Count > 0) { string urlToNavigate = NavigationContext.QueryString.Values.First(); if (urlToNavigate.IndexOf(httpPrefix) == -1) urlToNavigate = httpPrefix + urlToNavigate; Uri uri = new Uri(urlToNavigate, UriKind.Absolute); if (null != uri) wb.Navigate(uri); } }This snippet code validates whether the navigation parameter exists and that it provides a valid URL address (according to the expected URL syntax format http://www.somesite.com/somefolder/somepage.html). If valid, the phone navigates to specified URL.
- Add the “Go” Button click event handler function. The functionality is similar to previous function. Get the desired navigation URL from
TextBox on screen and after validation navigate to the location:
(Code Snippet – Navigation and Controls – Ex2 Task 3 Step 9 – Go button Click event handler)
private void Button_Click(object sender, RoutedEventArgs e) { string urlToNavigate = txtURL.Text.IndexOf(httpPrefix) > -1 ? txtURL.Text : httpPrefix + txtURL.Text; Uri uri = new Uri(urlToNavigate, UriKind.Absolute); if (null != uri) wb.Navigate(uri); } - Change MainPage.xaml by adding Hyperlink to a new page (after Images, before About page):
<Grid x:Name="ContentPanel" Grid.Row="1" Grid.Row="12,0,12,0"> <ScrollViewer BorderBrush="Transparent"> <StackPanel Margin="5"> ... <HyperlinkButton NavigateUri="/Pictures" Content="Images" Style="{StaticResource PhoneHyperlinkStyle}"/> <TextBlock Text="Web" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/WebBrowser/www.bing.com" Content="Web Browser" Style="{StaticResource PhoneHyperlinkStyle}"/> <TextBlock Text="About" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/About" Content="About" Style="{StaticResource PhoneHyperlinkStyle}"/> </StackPanel> </ScrollViewer> </Grid> - Compile and run the application.

Figure 28 Main Page after completing the task
- Navigate to the Web Browser page and check its functionality.

Figure 29 Web BrowserPage within wrongly oriented emulator window
- When browsing to the Web Browser page, the phone emulator opens the page in Landscape orientation, even though the emulator is still set to Portrait orientation. To change the orientation, click on the “rotate” buttons:

Figure 30 Changing Emulator orientation

Figure 31 Working Web Browser screen in Landscape orientation
- This step concludes the second exercise.
During this exercise you added media playback functionality to your created Music and Video pages, used controls to add new pages to present pictures, and used Web Browser controls.
Note: |
|---|
| The solution for this exercise located at theSource\Ex2-IntroductionToTheControls\End folder of this lab |