Share via


Exercise 2: Introduction to the Controls Available for Windows Phone Applications

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.

  1. 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.
  2. We will begin by adding some assets that we will use throughout this exercise. Create two new project folders and name them Assets and Misc.
  3. Take all the files under the Source\Assets\Classes folder of this lab, and add them to the Misc project folder.
  4. Take all the files under the Source\Assets\Video and Source\Assets\Music folders of this lab, and add them to the Assets project folder.
  5. Create an additional project folder under the Assets folder and name it Images.
  6. Take all the files under the Source\Assets\Pictures folder of this lab, and add them to the Images project folder.
  7. Open the Default.xaml file from the Views\Video folder.
  8. Add the following markup snippet to the ContentPanel element:

    XAML

    <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
  9. Open the corresponding Default.xaml.cs file.
  10. 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:

    C#

    public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); }

  11. Add the following event handler function:

    C#

    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; } } }

  12. Modify the Default.xaml.cs file in the Music folder. Subscribe to the Loaded event of the page. Add the following code to the constructor code after the call to the InitializeComponent function:

    C#

    public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); }

  13. Add the following event handler function:

    C#

    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; } } }

  14. Compile and run the application. Navigate to the Video and/or Music pages to make sure it works.

    Figure 4

    Video page

  15. Stop the debugging and return to editing the application.

    During this task, you updated two of the application’s pages, 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.
  1. Create a new project folder under the Views folder and name it Pictures.
  2. Add a new portrait page to the newly created folder and name it Default.xaml.
  3. On the new page, change the TitlePanel according to the following markup snippet:

    XAML

    <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>

  4. Add the following markup to the ContentPanel element:

    XAML

    <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.

  5. 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.

  6. 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:

    C#

    event NotifyCollectionChangedEventHandler CollectionChanged;

    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.

  7. Call the function from the page constructor and make initialized collection the ItemsSource of a ListBox:

    C#

    public Default() { InitializeComponent(); InitializePhotos(); lstPictures.ItemsSource = photos; }

  8. Add an event handler function to handle Remove Button Click event:

    C#

    private void btnRemoveSelection_Click(object sender, RoutedEventArgs e) { if (null != lstPictures.SelectedItem) photos.Remove(lstPictures.SelectedItem as Photo); }

  9. Add an event handler function to handle ListBox SelectionChanged event:

    C#

    private void lstPictures_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (null != lstPictures.SelectedItem) { btnRemoveSelection.IsEnabled = true; } if (photos.Count == 0) btnRemoveSelection.IsEnabled = false; }

  10. Open App.xaml and add the following object into the Application.Resources element, which points to the image's location:

    XAML

    <Application.Resources> ... <system:String x:Key="ImagesLocation">Assets/Images/</system:String> </Application.Resources>

  11. Change MainPage.xaml by adding a Hyperlink to a new page (after Videos, before About page):

    XAML

    <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>

  12. Compile and run the application. Navigate to the Images page and check its functionality.

    Figure 5

    Images Page

  13. 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

  1. 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.
  2. In this task you also will add a new WebBrowser Page that will be used to create a basic Web browser.
  3. Create a new project folder under the Views folder and name it WebBrowser.
  4. Add a new Landscape page to the WebBrowser folder and name it Default.xaml.
  5. Change the TitlePanel content according to the markup snippet below:

    XAML

    <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>

  6. Add the following markup snippet to the ContentPanel element, which contains the Web Browser control.

    XAML

    <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>

  7. Design surface should look as follows:

    Figure 6

    WebBrowser page design

  8. Open the code-behind file for the page.
  9. Add the httpPrefix constant to the class.

    C#

    public partial class Default : PhoneApplicationPage { private const string httpPrefix = "https://"; public Default() { ... } }

  10. Subscribe to the Loaded event to handle navigation parameters. Add the following code to the class constructor:

    C#

    public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); }

  11. Create the appropriate event handler function and add business logic. The resulting code should look like:

    C#

    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 https://www.somesite.com/somefolder/somepage.html). If valid, the phone navigates to specified URL.

  12. Add the “Go” Button click event handler function. The functionality is similar to previous function. Get the desired navigation URL from the TextBox on the screen and after validation navigate to the location:

    C#

    privatevoidButton_Click(objectsender,RoutedEventArgse) { stringurlToNavigate= txtURL.Text.IndexOf(httpPrefix) > -1 ? txtURL.Text:httpPrefix+txtURL.Text; Uriuri; try { uri=newUri(urlToNavigate,UriKind.Absolute); } catch(Exceptionerr) { MessageBox.Show(err.Message,"Invalid URL",MessageBoxButton.OK); return; } if(null!=uri) wb.Navigate(uri); }

  13. Change MainPage.xaml by adding Hyperlink to a new page (after Images, before About page):

    XAML

    <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>

  14. Compile and run the application.
  15. Navigate to the Web Browser page and check its functionality.

    Figure 7

    Web BrowserPage within wrongly oriented emulator window

  16. 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 8

    Working Web Browser screen in Landscape orientation

  17. 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 the Source\Ex2-IntroductionToTheControls\End folder of this lab