Share via


Exercise 3: Introduction to Windows Phone Services

In this exercise you will explore the phone-specific functionality, including how to:

  1. Define page orientation
  2. Handle orientation change events
  3. Handle the “Back” button press event
  4. Add an Application Bar to your application

Task 1 – Handling Page Orientation Changes

During this task you will learn how to handle phone orientation events to provide better UIs for specific orientations.

  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 Ex3-IntroductionToWindowsPhoneServices\Begin in the Source folder of the lab.
  2. In order to add automatic handling of the page orientation, in the Page object, set the SupportedOrientations attribute. Open the Default.xaml file from the Views\About folder and change SupportedOrientations attribute value as follows:

    XAML

    <phone:PhoneApplicationPage x:Class="WindowsPhoneNavigation.Views.About.Default" ... Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True">

  3. Compile and run the application. Navigate to “About” page and change the emulator orientation. Observe orientation change behavior.

    Figure 9

    About page with automatic orientation

  4. Stop the debugging and return to editing the application.
  5. Repeat step 2 for following application pages:
    • MainPage.xaml
    • Views\Music\Default.xaml
    • Views\Pictures\Default.xaml
    • Views\WebBrowser\Default.xaml
    • Views\Video\Default.xaml
  6. Because a user will expect to see a larger video display when setting the phone to landscape orientation, you’ll use a variation of the above procedure to modify the Default.xaml page that resides in the Views\Video folder.
  7. In order to achieve this, open the code-behind Default.xaml.cs in the Views\Video folder and add an event handler for the OrientationChanged event in the constructor as follows:

    C#

    public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); this.OrientationChanged += (s, e) => { if (e.Orientation == PageOrientation.Landscape || e.Orientation == PageOrientation.LandscapeLeft || e.Orientation == PageOrientation.LandscapeRight) { TitlePanel.Visibility = System.Windows.Visibility.Collapsed; ContentPanel.SetValue(Grid.RowSpanProperty, 2); ContentPanel.SetValue(Grid.RowProperty, 0); } else { TitlePanel.Visibility = System.Windows.Visibility.Visible; ContentPanel.SetValue(Grid.RowSpanProperty, 1); ContentPanel.SetValue(Grid.RowProperty, 1); } }; }

  8. Compile and run the application. Navigate to one of Video screens and observe layout change behavior while the emulator orientation changes:

    Figure 10

    Video in Portrait mode

    Figure 11

    Video in Landscape mode

  9. Stop the debugging and return to editing the application.
  10. During this task you subscribed to OrientationChanged event, and in case of Video page provided functionality to increase the MediaElement space on the screen – thing which lets user see bigger representation of video.

Task 2 – Handling Back Button Press

During this task you will learn how to handle Windows Phone “Back” button press event.

  1. Open the Default.xaml.cs file in the Views\Video folder.
  2. In the constructor, add an event handler to the BackKeyPress event and stop the MediaElement playback:

    C#

    public Default() { InitializeComponent(); ... this.BackKeyPress += (s, e) => { if (media.CurrentState == MediaElementState.Playing) media.Stop(); }; }

  3. Repeat the previous step for the Default.xaml.cs file in the Views\Music folder

    C#

    public Default() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); this.BackKeyPress += (s, e) => { if (media.CurrentState == MediaElementState.Playing) media.Stop(); }; }

Task 3 – Adding an Application Bar

In many cases you want to provide common functionality across the application. In some cases you may want to provide specific functionality on a page when some condition is met. In other cases you just want to have more space on the screen. For these scenarios, Windows Phone provides the Application Bar, which is a container for buttons and/or menu commands that can be visible or hidden. In all cases, it occupies a fixed and relatively small part of the screen, at the bottom in Portrait orientation and at either the left or the right side in Landscape orientation (always near the hardware buttons).

An ApplicationBar class adds phone-specific UI components – specifically ApplicationBarMenuItem controls and ApplicationBarIconButton controls. These provide a phone-centric hook for the navigation experience. The ApplicationBar can be set on individual PhoneApplicationPage controls. The system tray (upper part of the screen) can be hidden by setting its IsVisible dependency property.

In this section we will:

  • Create a number of Application Bars as application resources and use them in relevant pages
  • Add Application Bar Buttons to the Application Bar
  • Add support for toggling the system tray visibility

Figure 12

Phone screen layout

  1. Add all files from the lab’s Source\Assets\Icons folder directly under the WindowsPhoneNavigation project, replacing any existing files.
  2. Open App.xaml.
  3. Locate the ImagesLocations resource (added previously), to which you will add a number of resources.
  4. First add an application bar for the MainMenu screen. This Application Bar will hold 2 buttons and 1 menu item. Buttons will point to Images and WebBrowser screens (created previously) and a menu item will navigate to “About” screen. Add the following markup after ImagesLocation resource in App.xaml.

    XAML

    <Application.Resources> ... <system:String x:Key="ImagesLocation">Assets/Images/</system:String> <shell:ApplicationBar x:Key="MainAppBar" IsVisible="True"> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="About" Click="ApplicationBarAbout_Click" /> </shell:ApplicationBar.MenuItems> <shell:ApplicationBar.Buttons> <shell:ApplicationBarIconButton Text="Web" IconUri="ie_icon.png" Click="ApplicationBarIconWebBrowserButton_Click" /> <shell:ApplicationBarIconButton Text="Images" IconUri="pictures_Icon.png" Click="ApplicationBarIconPictures_Click" /> </shell:ApplicationBar.Buttons> </shell:ApplicationBar> </Application.Resources>

  5. Open the code-behind file App.xaml.

    When working with the Application Bar and providing common functionality to the whole application, the natural choice for a common code location should be the App.xaml.cs file, and the App class there. The code written in this class will work across all the application, since the Application object is created by Silverlight runtime while initializing the application, and stays alive during entire application life cycle. In this case, the event handler for Application Bar functionality is a good example of the code relating to the whole application logic and not just to the specific page.

  6. Add event handlers for the “About” application bar’s menu item and two buttons:

    C#

    private void ApplicationBarIconWebBrowserButton_Click(object sender, EventArgs e) { PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; root.Navigate(new Uri("/WebBrowser/www.bing.com", UriKind.Relative)); } private void ApplicationBarIconPictures_Click(object sender, EventArgs e) { PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; root.Navigate(new Uri("/Pictures", UriKind.Relative)); } private void ApplicationBarAbout_Click(object sender, EventArgs e) { PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; root.Navigate(new Uri("/About", UriKind.Relative)); }

  7. Open the MainPage.xaml file and remove the following unneeded TextBlocks and Hyperlinks to the Images, Web and About pages.

    XAML

    <TextBlock Text="Images" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton NavigateUri="/Pictures" Content="Imges" 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}"/>

  8. Open MainPage.xaml and add a reference to the Application Bar resource at the PhoneApplicationPage element of the page:

    XAML

    <phone:PhoneApplicationPage ... SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" shell:SystemTray.IsVisible="True" ApplicationBar="{StaticResource MainAppBar}">

  9. Compile and run the application. Check navigation by clicking buttons on the application bar and menu.

    Figure 13

    Application with ApplicationBar

    Note:
    To raise the menu click the icon at the Application Bar.

  10. Stop the debugging and return to editing the application.
  11. In order to hide the System Tray from view, toggle the SystemTray.IsVisible dependency property.
  12. Open the MainPage.xaml file and add the following markup snippet after the Video hyperlink:

    XAML

    <TextBlock Text="System Tray" Style="{StaticResource PhoneTextGroupHeaderStyle}"/> <HyperlinkButton Content="Toggle System Tray" Click="OnSystemTrayToggle" Style="{StaticResource PhoneHyperlinkStyle}"/>

  13. Switch to the code-behind of this page and add following namespace directive at the top of the file:

    C#

    using Microsoft.Phone.Shell;

  14. Now add an event handler for the Hyperlink Click event into the MainPage class:

    C#

    private void OnSystemTrayToggle(object sender, RoutedEventArgs e) { this.SetValue(SystemTray.IsVisibleProperty, !(bool)this.GetValue(SystemTray.IsVisibleProperty)); }

  15. Compile and run the application. Click the “Toggle System Tray” hyperlink and notice that the system tray disappear:

    Figure 14

    Hiding the system tray

    Note:
    The system tray may not display anything at times. Simply tap the top of the display to reveal the battery and reception icons.
  16. Stop the debugging and return to editing the application.
  17. Open the App.xaml file to add two more Application bars – one will be used for the Images page, and one will be used in all other pages.
  18. First add the GlobalAppBar which will be used in all pages (after the MainAppBar declaration):

    XAML

    <Application.Resources> ... <shell:ApplicationBar x:Key="MainAppBar" IsVisible="True"> ... </shell:ApplicationBar> <shell:ApplicationBar x:Key="GlobalAppBar" IsVisible="True"> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Text="About" Click="ApplicationBarAbout_Click" /> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </Application.Resources>

  19. Add the following Application Bar markup to the pages listed below:

    XAML

    <phone:PhoneApplicationPage ... shell:SystemTray.IsVisible="True" ApplicationBar="{StaticResource GlobalAppBar}">

    • Views\Music\Default.xaml
    • Views\Video\Default.xaml
    • Views\WebBrowser\Default.xaml
  20. Now add an Application Bar for the Images screen. It should be visible only when an image is selected from the ListBox. This Application Bar will provide 2 menu items – one to show the selected image in detail and one to navigate to the “About” page. Add the following markup to the App.xaml (after the GlobalAppBar added in the previous step):

    XAML

    <shell:ApplicationBar x:Key="PictureAppBar" IsVisible="False"> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem x:Name="appBarMenuItemShowPicture" Text="Show Picture"/> <shell:ApplicationBarMenuItem Text="About" Click="ApplicationBarAbout_Click"/> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar>

  21. Now open the Default.xaml file from the Views\Pictures folder and add the following markup to the PhoneApplicationPage object:

    XAML

    <phone:PhoneApplicationPage ... shell:SystemTray.IsVisible="True" ApplicationBar="{StaticResource PictureAppBar}">

  22. Open the code-behind of the Default.xaml file from the Views\Pictures folder and add the following namespace directive:

    C#

    using Microsoft.Phone.Shell;

  23. To show/hide the application bar when the user selects a picture, replace the lstPictures_SelectionChanged function according to the following code snippet:

    C#

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

  24. In the page constructor , add the following code snippet to subscribe to the Applications’ Bar menu item event:

    C#

    public Default() { InitializeComponent(); InitializePhotos(); lstPictures.ItemsSource = photos; (ApplicationBar.MenuItems[0] as ApplicationBarMenuItem).Click += new EventHandler(ApplicationBar_OnClick); }

  25. Add following event handler function at the bottom of the class:

    C#

    private void ApplicationBar_OnClick(object sender, EventArgs e) { if (null != lstPictures.SelectedItem) { PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; root.Navigate(new Uri("/PictureView/" + (lstPictures.SelectedItem as Photo).Filename, UriKind.Relative)); } }

  26. Add new Landscape page under the Views\Pictures folder and name it PictureView.xaml.
  27. Change SupportedOrientation property to PortraitOrLandscape in the PhoneApplicationPage opening tag as shown in the following code snippet:

    XAML

    <phone:PhoneApplicationPage ... Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="PortraitOrLandscape" Orientation="Landscape" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True">

  28. Now add the GlobalAppBar Application Bar to the page as shown below:

    XAML

    <phone:PhoneApplicationPage ... shell:SystemTray.IsVisible="True" ApplicationBar="{StaticResource GlobalAppBar}">

  29. Change the TitlePanel according to the following markup snippet:

    XAML

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="{Binding Filename}" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel>

  30. Now add an image control to the ContentPanel according to following code snippet:

    XAML

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Image Stretch="Uniform" Source="{Binding Image}"/> </Grid>

  31. Open the PictureView.xaml code-behind file and add following namespace directive:

    C#

    using WindowsPhoneNavigation.Misc;

  32. Subscribe to Loaded event in the page’s constructor code:

    C#

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

  33. Create a default event handler. The event handler function will load the picture defined in navigation parameters and set the data context for the page:

    C#

    private void Default_Loaded(object sender, RoutedEventArgs e) { if (NavigationContext.QueryString.Count > 0) { Photo thePhoto = new Photo(); thePhoto.Filename = NavigationContext.QueryString.Values.First(); thePhoto.Image = Utils.GetImage(NavigationContext.QueryString.Values.First()); this.DataContext = thePhoto; } }

  34. In the constructor code, add a subscription to the OrientationChanged event and hide/show TitlePanel according to orientation. In addition this will change the ContentPanel location in the page main Grid according to orientation. Add the following code snippet to page constructor:

    C#

    public PictureView() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Default_Loaded); this.OrientationChanged += (s, e) => { if (e.Orientation == PageOrientation.Landscape || e.Orientation == PageOrientation.LandscapeLeft || e.Orientation == PageOrientation.LandscapeRight) { TitlePanel.Visibility = System.Windows.Visibility.Collapsed; ContentPanel.SetValue(Grid.RowSpanProperty, 2); ContentPanel.SetValue(Grid.RowProperty, 0); } else { TitlePanel.Visibility = System.Windows.Visibility.Visible; ContentPanel.SetValue(Grid.RowSpanProperty, 1); ContentPanel.SetValue(Grid.RowProperty, 1); } };

    }

  35. Compile and run the application. Navigate to Images screen (), select an image and observe the Application Bar appearance. To raise the menu, click the icon at the Application Bar.
  36. Click Show Picture and check that the navigation works:

    Figure 15

    PictureView page in Portrait orientation

  37. Change emulator’s orientation to see the bigger picture:

    Figure 16

    PictureView page in Landscape orientation

  38. Click the Back button () to return to the Pictures list.
  39. Select some pictures and click the Remove Button. Check that the pictures are removed from the list.
  40. Stop the debugging.

    This step concludes the third exercise.

    During this exercise you created Application Bar with buttons and menu items, handled page orientation and Back button press events.

    Note:
    The solution for this exercise is located at the Source\Ex3-IntroductionToWindowsPhoneServices\End folder of this lab.