Share via


Exercise 1: Introduction to Navigation in Windows Phone

In this exercise we will build an application named Wazup. At the end of this exercise the Wazup application will allow us to search stories on Digg and see the active Trends on Twitter.

The exercise will include the following tasks:

  • Create basic Windows Phone 7 Application placeholder pages
  • Implement Digg search page functionality
  • Implement Trends page functionality

We will use the Microsoft Visual Studio 2010 Express for Windows Phone development environment, and will deploy to the Windows Phone Emulator for debugging. The solution we will be working with is based upon the Silverlight for Windows Phone Application template. During development, we will add Silverlight for Windows Phone project specific items: Windows Phone Portrait Page, Windows Phone Pivot Page and Windows Phone Panorama Page.

Note:
The steps in this hands-on lab illustrate procedures using Microsoft Visual Studio 2010 Express for Windows Phone, but they are equally applicable to Microsoft Visual Studio 2010 with the Windows Phone Developer Tools. Instructions that refer generically to Visual Studio apply to both products.

Task 1 – Creating a Windows Phone 7 Application

In this task we will create the basic Windows Phone 7 project for the Wazup application.

At the end of this task the Wazup application will have two pages in addition to the main page.

The first page is a placeholder for the Digg functionality and the second page is a placeholder for the trends functionality. We will add functionality to these two pages in the following two tasks.

During this task we will see how to work with the Windows Phone Application Bar and how to navigate between pages in a Windows Phone application.

Since this is rather a big application, we’ll start with adding some code, art and XAML that we’ve prepare in advance to allow you to fully focus on the core Windows Phone fundamentals.

  1. Open Microsoft Visual Studio 2010 Express for Windows Phone or Visual Studio 2010.
  2. Open the Begin.sln starter solution from the Source\Ex1-Navigation\Begin folder of this lab.
  3. Open the file App.xaml and add the following code into the resources section:

    XAML

    <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources>

  4. Open MainPage.xaml and add buttons to the phone application bar, instead of the commented use of PhoneApplicationPage.ApplicationBar, add the following after the LayoutRoot grid element:

    XAML

    <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="AppbarButtonDigg" IconUri="/Resources/App.Digg.png" Text="Digg" Click="AppbarButtonDigg_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonTwitter" IconUri="/Resources/App.Twitter.png" Text="Twitter" Click="AppbarButtonTwitter_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonBlog" IconUri="/Resources/App.Blog.png" Text="Blog" Click="AppbarButtonBlog_Click" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

  5. Open the file named Navigation.cs. Now we will implement the Navigation class. First we define an enum that contains an entry for each page in our final application:
    • The Navigation class provides an extension method of PhoneApplicationPage, named GoToPage, which allows us to navigate to a requested page
    • The GoToPage function uses a property of PhoneApplicationPage, named NavigationService to trigger the navigation
  6. Replace the content of the Navigation.cs file with the following code

    C#

    public enum ApplicationPages { Digg, Trends, Twitter, Blog } public static class Navigation { /// <summary> /// Goes to page. /// </summary> /// <param name="applicationPage">The application page.</param> public static void GoToPage(this PhoneApplicationPage phoneApplicationPage, ApplicationPages applicationPage) { switch (applicationPage) { case ApplicationPages.Digg: phoneApplicationPage.NavigationService.Navigate(new Uri("/Views/DiggPage.xaml", UriKind.Relative)); break; case ApplicationPages.Trends: phoneApplicationPage.NavigationService.Navigate(new Uri("/Views/TrendsPage.xaml", UriKind.Relative)); break; case ApplicationPages.Twitter: phoneApplicationPage.NavigationService.Navigate(new Uri("/Views/TwitterPage.xaml", UriKind.Relative)); break; case ApplicationPages.Blog: phoneApplicationPage.NavigationService.Navigate(new Uri("/Views/BlogPage.xaml", UriKind.Relative)); break; } } }

  7. Open the file MainPage.xaml.cs
  8. Replace the existing code inside the following event handlers with the following highlighted code event handlers below of the MainPage class. In this step we handle the button Click events for both the buttons we have added and the application bar buttons. In each event handler we use the Navigation class to go to the correct page. Note that the blog page doesn't exist yet; it will be created later in this lab.

    C#

    private void ButtonDigg_Click(object sender, RoutedEventArgs e) { this.GoToPage(ApplicationPages.Digg); } private void ButtonTwitter_Click(object sender, RoutedEventArgs e) { this.GoToPage(ApplicationPages.Trends); } private void ButtonBlog_Click(object sender, RoutedEventArgs e) { this.GoToPage(ApplicationPages.Blog); } #region Appbar handlers private void AppbarButtonDigg_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Digg); } private void AppbarButtonTwitter_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Trends); } private void AppbarButtonBlog_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Blog); } #endregion

  9. Compile and run the application
  10. At this stage the application looks like the following:

    Figure 1

    Opening screen of Wazup application

  11. Stop the debugging and return to the code. This step concludes the current task.

Task 2 – Implementing Digg Page Functionality

In this task we will implement the functionality of the Digg search page in the Wazup application. At the end of this task the Wazup application will have a working Digg search page.

During this task we will create the Digg page UI using some basic controls like TextBox, TextBlock, HyperlinkButton and ListBox. In addition, we will see how to save and load page state when navigating away from the application.

  1. Pay attention to files: DiggService.cs and DiggStory.cs under the Services folder. These classes handle the web requests for you, getting the relevant data from Digg.
  2. Add to the ProgressBar, under Helper folder, all the files from the Source\Assets\Helpers\ProgressBar folder of this lab. The following files should be added: BooleanToVisibilityConverter.cs, ProgressBarWithText.xaml, ProgressBarWithText.xaml.cs and RelativeAnimatingContentControl.cs. These files encapsulate a progress bar that have similar UI of the one used by Windows Phone.
  3. Open the file DiggPage.xaml
  4. Add the following XML namespace to the phone:PhoneApplicationPage element next to the other XML namespaces definitions:

    XAML

    xmlns:localHelpers="clr-namespace:Wazup.Helpers"

  5. Set the DataContext property of the DiggPage to be the DiggPage itself by adding the following line to the phone:PhoneApplicationPage element:

    XAML

    DataContext="{Binding RelativeSource={RelativeSource Self}}"

  6. Locate the LayoutRoot grid and replace the content with the following code. The Digg page has a TextBox that contains the text to be searched, a search Button, a TextBlock that presents the last searched text, a ListBox that will present the search results and a ProgressBarWithText control that will show status information while searching.

    Note:
    Note that the ProgressBarWithText control is a custom control that we have added to the project.

    The ListBox control is used to present a list of items. The ListBox items are set via the property ItemsSource which is bound to a collection of DiggStory items. In order to transform each DiggStory object into a valid UI we use the ItemTemplate property to define the name of the DataTemplate that will do the transformation. The DataTemplate will be defined in the next step.

    XAML

    <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid x:Name="ContentPanel" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBox x:Name="TextBoxSearch" Grid.Column="0" Text="{Binding SearchText, Mode=TwoWay}" /> <Button x:Name="ButtonSearch" Grid.Column="1" Click="ButtonSearch_Click" VerticalAlignment="Top" Padding="0" Style="{StaticResource ButtonGoStyle}" /> <TextBlock x:Name="TextBlock" Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding LastSearchText}" Margin="18,0,0,5" HorizontalAlignment="Left" FontSize="24" Height="45" /> <Path Grid.ColumnSpan="2" Data="M0,80 L448,80" Height="1" Margin="0,2,12,4" Grid.Row="1" Stretch="Fill" Stroke="#B2FFFFFF" UseLayoutRounding="False" VerticalAlignment="Bottom"/> <ListBox Grid.Row="2" Grid.ColumnSpan="2" ItemsSource="{Binding DiggSearchResults}" ItemTemplate="{StaticResource DiggSearchResultTemplate}" /> <localHelpers:ProgressBarWithText Grid.Row="2" Grid.ColumnSpan="2" Text="Searching..." ShowProgress="{Binding IsSearching}" /> </Grid> </Grid>

    Now we define a DataTemplate that will transform each DiggStory object into a presentable UI that contains the Digg story.

  7. We now add buttons to the application bar in the Digg page. Open DiggPage.xaml file. After the LayoutRoot grid ends, instead of the commented use of PhoneApplicationPage.ApplicationBar, add the following code:

    XAML

    <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="AppbarButtonDigg" IconUri="/Resources/App.Digg.png" Text="Digg" Click="AppbarButtonDigg_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonTwitter" IconUri="/Resources/App.Twitter.png" Text="Twitter" Click="AppbarButtonTwitter_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonBlog" IconUri="/Resources/App.Blog.png" Text="Blog" Click="AppbarButtonBlog_Click" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

  8. Open the file name StateManager.cs. This class will provide helper functions for saving and loading state information when the application exits.

    In order to save battery power Windows Phone 7 doesn't allow applications to run simultaneously. This means that if you open a new application while your application is running (for example, Web Browser), it will cause your application to exit. If you then return to your application by clicking Back, your application will open in a new instance (that is, an entirely different process). The application will be opened in the last opened page, since this information is saved by the operating system, but if the page had any information stored in its variables, that information will be completely erased, since this is a new instance of the page. In order to overcome this situation you need to:

    • Save variables information into a special state object when the page is being navigated away from (that is, the user is leaving the page)
    • Load the variables information from the special state object when the page is being navigated back to (that is, the user is returning to the page)

    Do this in the two functions OnNavigateTo and OnNavigateFrom.

  9. To prepare a helper class named StateManager that will help us implement these two functions, replace the content of the StateManager.cs file with the following code:

    C#

    namespace Wazup { /// <summary> /// State Manager /// </summary> public static class StateManager { /// <summary> /// Saves a key-value pair into the state object /// </summary> /// <param name="phoneApplicationPage">The phone application page.</param> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public static void SaveState(this PhoneApplicationPage phoneApplicationPage, string key, object value) { if (phoneApplicationPage.State.ContainsKey(key)) { phoneApplicationPage.State.Remove(key); } phoneApplicationPage.State.Add(key, value); } /// <summary> /// Loads value from the state object, according to the key. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="phoneApplicationPage">The phone application page.</param> /// <param name="key">The key.</param> /// <returns>The loaded value</returns> public static T LoadState<T>(this PhoneApplicationPage phoneApplicationPage, string key) where T : class { if (phoneApplicationPage.State.ContainsKey(key)) { return (T)phoneApplicationPage.State[key]; } return default(T); } } }

  10. Open the file DiggPage.xaml.cs
  11. Add to the DiggPage class the following dependency properties:
    • SearchText of type string – used to save the current search text
    • LastSearchText of type string – used to save the last search text
    • DiggSearchResults of type ObservableCollection<DiggStory> - used to save the collection of digg search results
    • IsSearching of type bool – used to indicate whether search is currently in progress

      C#

      #region SearchText /// <summary> /// SearchText Dependency Property /// </summary> public static readonly DependencyProperty SearchTextProperty = DependencyProperty.Register("SearchText", typeof(string), typeof(DiggPage), new PropertyMetadata((string)"")); /// <summary> /// Gets or sets the SearchText property. This dependency property /// indicates the text to be searched. /// </summary> public string SearchText { get { return (string)GetValue(SearchTextProperty); } set { SetValue(SearchTextProperty, value); } } #endregion #region LastSearchText /// <summary> /// LastSearchText Dependency Property /// </summary> public static readonly DependencyProperty LastSearchTextProperty = DependencyProperty.Register("LastSearchText", typeof(string), typeof(DiggPage), new PropertyMetadata((string)"")); /// <summary> /// Gets or sets the LastSearchText property. This dependency property /// indicates the last searched text. /// </summary> public string LastSearchText { get { return (string)GetValue(LastSearchTextProperty); } set { SetValue(LastSearchTextProperty, value); } } #endregion #region DiggSearchResults /// <summary> /// DiggSearchResults Dependency Property /// </summary> public static readonly DependencyProperty DiggSearchResultsProperty = DependencyProperty.Register("DiggSearchResults", typeof(ObservableCollection<DiggStory>), typeof(DiggPage), new PropertyMetadata((ObservableCollection<DiggStory>)null)); /// <summary> /// Gets or sets the DiggSearchResults property. This dependency property /// indicates digg search results. /// </summary> public ObservableCollection<DiggStory> DiggSearchResults { get { return (ObservableCollection<DiggStory>)GetValue(DiggSearchResultsProperty); } set { SetValue(DiggSearchResultsProperty, value); } } #endregion #region IsSearching /// <summary> /// IsSearching Dependency Property /// </summary> public static readonly DependencyProperty IsSearchingProperty = DependencyProperty.Register("IsSearching", typeof(bool), typeof(DiggPage), new PropertyMetadata((bool)false)); /// <summary> /// Gets or sets the IsSearching property. This dependency property /// indicates whether we are currently searching. /// </summary> public bool IsSearching { get { return (bool)GetValue(IsSearchingProperty); } set { SetValue(IsSearchingProperty, value); } } #endregion

  12. Add a handler for the Click event of the ButtonSearch control. In this handler we perform a search in Digg service. We do this by calling the asynchronous method DiggService.Search which accepts the search text, a callback function to call when the search is completed and a callback function to call if the search failed, for example, if the Digg service is not available. If the search completes successfully, we add the results to the DiggSearchResults collection which is bound to the ListBox.

    C#

    /// <summary> /// Handles the Click event of the ButtonSearch control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> private void ButtonSearch_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(SearchText)) { return; } IsSearching = true; DiggService.Search(SearchText, delegate(IEnumerable<DiggStory> diggSearchResults) { IsSearching = false; LastSearchText = SearchText; DiggSearchResults = new ObservableCollection<DiggStory>(); foreach (DiggStory diggSearchResult in diggSearchResults) { DiggSearchResults.Add(diggSearchResult); } }, delegate(string searchText, Exception exception) { IsSearching = false; LastSearchText = string.Format("Error while searching {0}.", searchText); System.Diagnostics.Debug.WriteLine(exception); }); }

  13. Override the functions OnNavigateTo and OnNavigateFrom of the page. Use the StateManager class to save and load page state when the current page is changing.

    C#

    private const string SearchTextKey = "SearchTextKey"; private const string LastSearchTextKey = "LastSearchTextKey"; private const string DiggSearchResultsKey = "DiggSearchResultsKey"; protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) { this.SaveState(SearchTextKey, SearchText); this.SaveState(LastSearchTextKey, LastSearchText); this.SaveState(DiggSearchResultsKey, DiggSearchResults); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { SearchText = this.LoadState<string>(SearchTextKey); LastSearchText = this.LoadState<string>(LastSearchTextKey); DiggSearchResults = this.LoadState<ObservableCollection<DiggStory>>(DiggSearchResultsKey); }

  14. Add the following event handlers in the DiggPage class. In this step we handle the application bar buttons. In each event handler we use the Navigation class to go to the correct page. Note that the blog page doesn't exist yet; we will create it later in this lab.

    C#

    #region Appbar handlers /// <summary> /// Handles the Click event of the AppbarButtonDigg control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonDigg_Click(object sender, EventArgs e) { SearchText = string.Empty; LastSearchText = string.Empty; DiggSearchResults = null; } /// <summary> /// Handles the Click event of the AppbarButtonTwitter control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonTwitter_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Trends); } /// <summary> /// Handles the Click event of the AppbarButtonBlog control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonBlog_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Blog); } #endregion

  15. Compile and run the application. If you get an error while searching Digg it might be because the Digg search service is down. You can check the status of the service at: https://developers.digg.com/
  16. At this stage the Digg search page should work and look like the following:

    Figure 2

    Digg search page with results

  17. Stop the debugging and return to the code.
  18. This step concludes the current task.

In this task we will implement the functionality of the Trends page in the Wazup application. At the end of this task the Wazup application will have a working Trends page.

During this task we will create the Trends page UI using some basic controls and handle the state of the Trends page when navigating away from the application.

  1. Now we will add the utility classes used to work with Trends service. Add to the Services folder the files: TwitterService.cs, Trend.cs and Twit.cs which are located in Source\Assets\Services folder of this lab.
  2. Since the trends service provider limits its access using an application key, you must create one for your lab. To do this, go to the site https://api.whatthetrend.com/; select "Request API key," which you can find on the right side of the display. Fill out the small form to get a free application key that you can use for the lab. Copy the generated key to the constant Wazup_WhatTheTrendApplicationKey that is defined in the file TwitterService.cs.

    Do not use the default key since it probably will not work.

    Figure 3

    Requesting an application key from WhatTheTrend.com

  3. Open the file TrendsPage.xaml
  4. Add the following XML namespace to the phone:PhoneApplicationPage element next to the other XML namespaces definitions:

    XAML

    xmlns:localHelpers="clr-namespace:Wazup.Helpers"

  5. Now we will define the UI for the trends page. Locate the LayoutRoot grid and replace the content with the following code. The trends page has a ListBox that will present the list of top 10 Twitter trends, a ProgressBarWithText control that will show status information while loading trends and a TextBlock that presents an attribution for the trends service supplier (whatthetrend.com). The ListBox items are set via the property ItemsSource which is bound to a collection of Trend items. In order to transform each Trend object into a valid UI we use the ItemTemplate property to define the name of the DataTemplate that will do the transformation. We will define the DataTemplate in the next step.

    XAML

    <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,16,0,27"> <TextBlock x:Name="ApplicationTitle" Text="TWITTER TRENDS" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="top trends" Margin="9,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ListBox ItemsSource="{Binding Trends}" ItemTemplate="{StaticResource TrendTemplate}" FontSize="32" /> <localHelpers:ProgressBarWithText Text="Loading Trends..." ShowProgress="{Binding IsTrendsLoading}" /> <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Trends by whatthetrend.com" VerticalAlignment="Top" Grid.Row="1" Foreground="#99FFFFFF" Margin="0,0,0,5"/> </Grid> </Grid>

  6. Now we define a DataTemplate that will transform each Trend object into a presentable UI that contains the trend. Add the following code into TrendsPage resources section.

    XAML

    <phone:PhoneApplicationPage.Resources> <DataTemplate x:Key="TrendTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="#" FontSize="32" MinHeight="72" VerticalAlignment="Center" HorizontalAlignment="Left" Foreground="#FFFFC425" Margin="0,0,1,0" /> <TextBlock Text="{Binding trend_index}" FontSize="32" MinHeight="72" VerticalAlignment="Center" HorizontalAlignment="Left" Foreground="#FFFFC425" Margin="0,0,5,0" /> <TextBlock x:Name="TextBlockTrend" Text="{Binding name}" MouseLeftButtonUp="TextBlockTrend_MouseLeftButtonUp" FontSize="32" MinHeight="72" VerticalAlignment="Center" HorizontalAlignment="Left" /> </StackPanel> </DataTemplate> </phone:PhoneApplicationPage.Resources>

  7. We now add buttons to the application bar in the trends page. After the LayoutRoot grid ends, instead of the commented use of PhoneApplicationPage.ApplicationBar, add the following code:

    XAML

    <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="AppbarButtonDigg" IconUri="/Resources/App.Digg.png" Text="Digg" Click="AppbarButtonDigg_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonTwitter" IconUri="/Resources/App.Twitter.png" Text="Twitter" Click="AppbarButtonTwitter_Click" /> <shell:ApplicationBarIconButton x:Name="AppbarButtonBlog" IconUri="/Resources/App.Blog.png" Text="Blog" Click="AppbarButtonBlog_Click" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>

  8. Open the file TrendsPage.xaml.cs
  9. Add to the TrendsPage class the following dependency properties:
    • Trends of type ObservableCollection<Trend> - used to save the collection of Twitter trends
    • IsTrendsLoading of type bool – used to indicate whether trends loading is currently in progress

      C#

      #region Trends /// <summary> /// Trends Dependency Property /// </summary> public static readonly DependencyProperty TrendsProperty = DependencyProperty.Register("Trends", typeof(ObservableCollection<Trend>), typeof(TrendsPage), new PropertyMetadata((ObservableCollection<Trend>)null)); /// <summary> /// Gets or sets the Trends property. This dependency property /// indicates the current twitter trends. /// </summary> public ObservableCollection<Trend> Trends { get { return (ObservableCollection<Trend>)GetValue(TrendsProperty); } set { SetValue(TrendsProperty, value); } } #endregion #region IsTrendsLoading /// <summary> /// IsTrendsLoading Dependency Property /// </summary> public static readonly DependencyProperty IsTrendsLoadingProperty = DependencyProperty.Register("IsTrendsLoading", typeof(bool), typeof(TrendsPage), new PropertyMetadata((bool)false)); /// <summary> /// Gets or sets the IsTrendsLoading property. This dependency property /// indicates whether we are currently loading trends. /// </summary> public bool IsTrendsLoading { get { return (bool)GetValue(IsTrendsLoadingProperty); } set { SetValue(IsTrendsLoadingProperty, value); } } #endregion

  10. Add a handler for the MouseLeftButtonUp event of the TextBlockTrend control. Currently we will leave it empty. We will add functionality as the lab progress.

    C#

    /// <summary> /// Handles the MouseLeftButtonUp event of the TextBlockTrend control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param> private void TextBlockTrend_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { }

  11. Override the functions OnNavigateTo and OnNavigateFrom of the page. Use the StateManager class to save and load page state when the current page is changing. In the function OnNavigateTo we need to check whether we loaded Trends from the state object – which implies the user have already seen this page and navigated from him. If we didn't, then it is a sign that we loaded from a new instance this page, and so need to get the Trends information from the trends service. We do this by calling the asynchronous method TwitterService.GetTrends, which accepts a callback function to call when the trends loading is complete and a callback function to call if the trends loading failed, for example, the trends service is not available. If the trends loading completed successfully we add the results to the Trends collection which is bound to the ListBox.

    C#

    private const string TrendsKey = "TrendsKey"; protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) { this.SaveState(TrendsKey, Trends); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { Trends = this.LoadState<ObservableCollection<Trend>>(TrendsKey); if (Trends == null) { IsTrendsLoading = true; TwitterService.GetTrends( delegate(IEnumerable<Trend> trends) { IsTrendsLoading = false; Trends = new ObservableCollection<Trend>(); foreach (Trend trend in trends) { Trends.Add(trend); } }, delegate(Exception exception) { IsTrendsLoading = false; System.Diagnostics.Debug.WriteLine(exception); }); } }

  12. Add the following event handlers in the TrendsPage class. In this step we handle the application bar buttons. In each event handler we use the Navigation class to go to the correct page. Note that the blog page doesn't exist yet; it will be created later in this lab.

    C#

    #region Appbar handlers /// <summary> /// Handles the Click event of the AppbarButtonDigg control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonDigg_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Digg); } /// <summary> /// Handles the Click event of the AppbarButtonTwitter control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonTwitter_Click(object sender, EventArgs e) { } /// <summary> /// Handles the Click event of the AppbarButtonBlog control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void AppbarButtonBlog_Click(object sender, EventArgs e) { this.GoToPage(ApplicationPages.Blog); } #endregion

  13. Compile and run the application.

    At this stage the trends page should work and look like the following:

    Figure 4

    Trends page showing Twitter trends

  14. Stop the debugging and return to the code. This step concludes the exercise.

During this exercise you learned how to create an application with several pages using common controls, how to navigate between the pages and how to save and load page state information.

Note:
The complete solution for this exercise is provided at the following location: Source\Ex1-Navigation\End.