Hands-On Lab Launchers 和 Choosers

 

Hands-On Lab

 

Launchers 和 Choosers

 

 

Lab version:    1.0.0

Last updated:          2/29/2012

 


 

目錄

概述... 3

練習 1: Launchers介紹及使用... 3

任務 1 – 添加頁面和導航... 3

任務 2 – 使用Launchers. 3

練習 2: Choosers介紹及使用... 3

任務 1 – 使用Choosers. 3

任務 2 – 搜索通訊錄和日程... 3

總結... 3

 

 


 

Launchers和Choosers框架使Windows Phone應用程序可以爲用戶提供一些功能,比如撥打電話,發送電子郵件,選擇圖片等。

Windows Phone應用程序模型使每個應用程序的執行(包括內存隔離)以及文件存儲相互隔離。 Windows Phone應用程序不能直接讀取一些信息,比如聯繫人列表,也不能直接啓動另外一個應用程序,比如撥號應用程序和短信息應用程序。爲了支持一些一般任務比如撥打電話或者發送短信息,Windows Phone提供了一系列Launcher和Chooser使應用程序可以間接完成這些事情。Launchers和Choosers切換當前應用程序至內置應用程序,並在將當前運行的應用程序切換至後臺的時候提供一種無縫的體驗。

該框架分爲以下兩部分:

·        Launcher- 一個“沒有返回信息” 的動作, 它可以調用一個特定的手機功能,比如發送短信息,打開一個Web頁面,或者撥打電話

·        Chooser –一個 “打開文件對話框” 的動作, 它可以選擇一個特定應用程序存儲區域的信息,比如選擇電子郵件地址,聯繫人,或者照片。

 

以下是代號爲“芒果”的Windows Phone 7提供的完整的Launcher和Chooser列表:

Launcher

·        EmailComposeTask – 撰寫新的電子郵件

·        MarketplaceDetailTask – 啓動Marketplace並顯示指定應用程序的詳細信息

·        MarketplaceHubTask –啓動Marketplace

·        MarketplaceReviewTask –啓動Marketplace以便爲當前應用程序提供評論

·        MarketplaceSearchTask –啓動Marketplace並執行相關內容的搜索

·        MediaPlayerLauncher –啓動媒體播放器

·        PhoneCallTask – 向指定的號碼撥打電話

·        SaveEmailAddressTask – 撰寫新的電子郵件

·        SavePhoneNumberTask –保存電話號碼

·        SearchTask –啓動網頁搜索應用程序

·        SmsComposeTask –撰寫新的短信息

·        WebBrowserTask –可以啓動Web瀏覽器到指定的URL

 

Choosers

·        EmailAddressChooserTask – 從聯繫人列表中選擇一個電子郵件地址

·        CameraCaptureTask – 打開照相機應用程序以便拍照

·        PhoneNumberChooserTask –從聯繫人列表中選擇一個電話號碼

·        PhotoChooserTask – 從PictureGallery中選擇一張圖片

·        Contacts –根據姓名,電子郵件地址,電話號碼搜索聯繫人.

·        Appointments –搜索一段時間內的用戶的日程安排

 

應用程序什麼時候會被墓碑化?

一般來說,當用戶向前導航並離開當前應用程序的時候,應用程序會被墓碑化(即,應用程序被放置到到回退棧中)。當然也有少數例外,當系統需要額外的資源來激活應用程序時,處於後臺運行的應用程序會被墓碑化。

當啓動一些特殊的任務的時候,應用程序不會被自動墓碑化,這樣使得用戶感覺這些操作像是應用程序原生的功能。這些任務幫助用戶完成一些功能,比如選擇照片。避免墓碑化可以保證應用程序和這些特殊的任務之間的平滑過渡(比如,當選擇一張圖片回到應用程序的過程之間不會感覺到延遲)。

下面是這些任務,當他們被調用的時候,調用它的應用程序不會自動被墓碑化:

·        PhotoChooserTask

·        CameraCaptureTask

·        MediaPlayerLauncher

·        EmailAddressChooserTask

·        PhoneNumberChooserTask

 

有三種場景在後臺的應用程序會被立即墓碑化:

·        用戶向前導航並離開應用程序(比如用戶按下開始鍵)

·        應用程序啓動一些不在上述列表中的 launchers或者choosers

·        系統需要更多的資源來運行當前激活狀態的應用程序

 

 注意: 所有上述關於墓碑化的信息均針對Windows Phone 7.0有效。在Windows phone 7.1上,所有的launchers和choosers都不會導致應用程序墓碑化,但是應用程序仍然可能被墓碑化,如果系統需要更多的資源。更多關於最新的Windows phone 7.1應用程序執行模型的信息請參考相關文檔。

目標

完成本實驗, 你將會:

·        熟悉Windows Phone 7應用程序模型的Launcher和Choosers的概念

·        明白怎樣和什麼時候使用launchers 和 choosers

·        創建一個Silverlight應用程序使用各種launchers 和 choosers

 

 

前提條件

完成本動手實驗需要滿足以下要求:

·        安裝MicrosoftVisual Studio 2010 Express for Windows Phone 或者 Microsoft Visual Studio2010

·        Windows Phone 7.1 Developer Tools

Note: 你可以從以下鏈接下載所有這些工具 http://go.microsoft.com/?linkid=9772716.

 

實驗提綱

這個動手實驗由以下兩個練習組成:

·        WindowsPhone Launchers介紹及使用

·        WindowsPhone Choosers介紹及使用

 

完成本實驗需要花費時間: 45 分鐘.


 

練習 1: Launchers介紹及使用

在本練習中,你將新建一個解決方案完成以下任務:

·        添加頁面並在多個頁面之間導航

·        在每個頁面中實現一個不同的launcher

 MicrosoftVisual Studio 2010 Express for Windows Phone被用作開發環境,WindowsPhone Emulator 被用作調試工具.

解決方案選擇 Silverlight for WindowsPhone Panorama Application模板. 在開發中,啓動頁面是一個 Silverlight for Windows Phone 項目文件:Windows Phone Portrait 頁面.

注意: 這個動手實驗描述的過程是使用Microsoft Visual Studio 2010 Express for Windows Phone, 但是同樣適用於 Microsoft Visual Studio2010.

任務 1 – 添加頁面和導航頁面

在本任務中,提供了一個起始的解決方案,這個解決方案包括一個簡單的Windows Phone 7 全景視圖應用程序,包含一個主頁,以及爲下一個任務做了些準備.

1.               打開 MicrosoftVisual Studio 2010 Express for Windows Phone :  開始 | 所有應用程序| Microsoft Visual Studio 2010 Express | Microsoft Visual Studio 2010Express for Windows Phone.

Visual Studio 2010: 打開Visual Studio 2010 : start | AllProgram| Microsoft Visual Studio 2010.

 

2.               從菜單中選擇文件.文件的下拉菜單將會顯示.

3.               從 文件 的下拉菜單中, 選中 打開項目. 打開項目的窗口將會顯示.

Visual Studio 2010: 在文件下拉菜單中, 指向  Open Project/Solution.

 

4.               導航到這個實驗的啓動項目位置:Source\Ex1-Launchers\Begin , 選擇 LaunchersAndChoosers.sln, 單擊打開.

圖 1

正在打開開始解決方案

5.               檢查打開的項目:

◦                   這是一個標準的Windows Phone 全景視圖應用程序, 包含自定義的 MainPage.xaml, MainPage.xaml.cs文件, 在 App.xaml中添加了一些資源, 去掉了model 中的類(爲了簡便), 修改了啓動圖片 SplashScreenImage.jpg. 這個應用程序還包括一個資源文件ResourceDictionary.xaml,它用來調整界面.

◦                   項目添加了一個名叫“Views”的文件夾,它將用來保存本次任務中新添加的頁面

◦                   項目添加了兩個文件夾:“Toolkit.Content” 和 “Images”,它們用來保存一些應用程序的圖片

◦                   項目包括一個 “Media”文件夾用來保存媒體資源

◦                   項目包括一個 “Converters”文件夾包括一些本實驗會用到的轉換器.

6.               給項目添加一個頁面:

◦                   右擊 Views 文件夾

◦                   從 下拉菜單中選擇Add

◦                   從 Add下拉菜單中選擇 New Item

圖 2

添加新的頁面

注意: 可以使用以下方式替代, 在單擊 “Views” 文件夾的同時按住 “Ctrl+Shift+A”.

 

7.               選擇 “Windows Phone Portrait Page” 模板, 命名新的頁面叫 SavePhoneNumberPage, 單擊 Add.

圖 3

添加新的頁面

VisualStudio 設計器會自動打開新建的頁面文件.

8.               如果Visual Studio 設計器沒有自動打開, 雙擊新建的頁面文件SavePhoneNumberPage.xaml.

9.               定位到 PhoneApplicationPage 元素.

10.            修改 SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SavePhoneNumberPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

 

11.            定位到名爲TitlePanel的Stackpanel.

12.             設置應用程序標題爲PHONE SERVICES,設置頁面標題爲Save Phone ,並且根據以下示例修改Text屬性。注意通過使用 “StaticResourceAppName” ,文本將會被綁定到一個靜態資源,你可以在App.xaml中找到:

XAML

<TextBlock x:Name="ApplicationTitle"

       Text="{StaticResourceAppName}"

      Style="{StaticResource PhoneTextNormalStyle}"/>

<TextBlock x:Name="PageTitle"

       Text="Save Phone"

      Margin="-3,-8,0,0"

      Style="{StaticResource PhoneTextTitle1Style}"/>

13.            定位到名爲 ContentPanel 的Grid.

14.            通過添加RowDefinitions 定義Grid爲3行:

XAML

<!--ContentPanel - place additional content here-->

<Grid x:Name="ContentPanel" Grid.Row="1">

    <Grid.RowDefinitions>

        <RowDefinition/>

        <RowDefinition/>

        <RowDefinition/>

    </Grid.RowDefinitions>

</Grid>

Grid的第一行用來放置一個StackPanel,它包含一個TextBlock和一個TextBox 用來輸入電話號碼.通過設置 InputScope 屬性指示顯示數字鍵盤

15.            添加下面高亮部分的ContentPanel:

XAML

<!--ContentPanel- place additional content here-->

<Gridx:Name="ContentPanel" Grid.Row="1">

    <Grid.RowDefinitions>

         ...

    </Grid.RowDefinitions>

 

    <StackPanel Orientation="Vertical" Grid.Row="0">

        <TextBlock Style="{StaticResource TextBlockTitleLargeStyle }" Text="Please enter phonenumber:"/>

        <TextBox x:Name="txtInput" InputScope="TelephoneNumber"/>

    </StackPanel>

           

</Grid>

 

注意: 當開發Silverlight Applications for Windows Phone應用程序的時候,其中一個應該熟悉的概念是軟鍵盤. 軟鍵盤是一個虛擬的鍵盤,當一個文本輸入控件比如TextBox得到輸入焦點之後會自動出現,而不需要代碼調用,這個過程是自動的。但是Silverlight能夠爲每個輸入控件指定輸入範圍 ,這允許系統在運行時根據要輸入數據的類型使軟鍵盤顯示不同的樣式和鍵. 爲了實現這個功能,設置輸入控件的InputScope 屬性.

Grid的最後一個行放置一個stack panel,其中放置一些Button.

16.            在前面插入的StackPanel後面添加一個StackPanel到Grid的第二行,並放置一個Button用來保存號碼,代碼如下:

XAML

<StackPanel Orientation="Vertical" Grid.Row="2" VerticalAlignment="Bottom">

   <Button x:Name="btnSavePhone" Content="SavePhone Number" Height="100" Margin="0,5" Click="btnSavePhone_Click"/>

</StackPanel>

17.            雙擊 SavePhoneNumberPage.xaml.cs 文件切換到後臺代碼,並添加btnSavePhone_Click事件,代碼如下:

C#

private void btnSavePhone_Click(object sender, RoutedEventArgse)

{

 

}

18.            現在頁面創建成功,接下來添加從MainPage到這個頁面之間的導航

19.            打開 MainPage.xaml.cs 並且定位到如下注釋部分:

C#

private void btnSavePhoneNumber_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to save phone number page

}

20.            用下面的代碼替換掉註釋部分:

C#

private void btnSavePhoneNumber_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(

        newUri("/Views/SavePhoneNumberPage.xaml",UriKind.Relative));

}

21.            按F5編譯並運行程序 ,WindowsPhone模擬器將會啓動.

圖 5

在WindowsPhone模擬器中運行應用程序

22.            單擊 Save Phone Number 並檢查導航是否正常.

23.            單擊textbox確認軟鍵盤是否按電話號碼格式顯示. 由於保存號碼的代碼還沒有編寫,所以單擊保存按鈕沒有反應.

圖 6

電話號碼格式的軟鍵盤

24.            在 Visual Studio 中按 SHIFT+F5 停止調試並回到編輯模式.

25.            添加一個名爲SaveEmailAddressPage 的頁面至Views 文件夾,使用"Windows Phone Portrait Page" 模板

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇 New Item.

26.            如果新建的頁面沒有自動打開,雙擊新建的頁面打開Visual Studio設計器

27.            定位到 PhoneApplicationPage 元素.

28.            修改 SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SaveEmailAddressPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

 

29.            爲了簡化設計過程,用下面的代碼替換整個 LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <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="Save Email"Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1" Margin="0">

        <Grid.RowDefinitions>

            <RowDefinition/>

            <RowDefinition/>

            <RowDefinition/>

        </Grid.RowDefinitions>

 

        <StackPanel Orientation="Vertical" Grid.Row="0">

            <TextBlock Style="{StaticResourceTextBlockTitleLargeStyle}" Text="Please enteremail address:"/>

                <TextBox x:Name="txtInput"InputScope="EmailUserName"/>

        </StackPanel>

 

        <StackPanel Orientation="Vertical"Grid.Row="2"
VerticalAlignment="Bottom">

            <Button x:Name="btnSaveEmail"Content="Save Email Address"  Margin="0,5" Click="btnSaveEmail_Click"/>

        </StackPanel>

    </Grid>

</Grid>

注意: 這次輸入文本框需要支持Email格式的輸入,因此設置不同的InputScope 來顯示不同風格的軟鍵盤.

上述標記語言代碼使頁面呈現如下的樣子:

圖 7

Email格式的軟鍵盤

30.            打開 SaveEmailAddressPage.xaml.cs.

31.            添加下面的 btnSaveEmail_Click事件至末尾.

C#

private void btnSaveEmail_Click(object sender, RoutedEventArgse)

{

 

}

32.            打開 MainPage.xaml.cs 文件定位到如下注釋的地方:

C#

private void btnSaveEmail_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to save email address page

}

33.            用下面的代碼替換註釋部分:

C#

private void btnSaveEmail_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(

      new Uri("/Views/SaveEmailAddressPage.xaml",

      UriKind.Relative));

}

34.            添加一個新的頁面SearchTaskPageViews 文件夾,使用"Windows Phone Portrait Page" 模板.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item

35.            定位到PhoneApplicationPage 元素.

36.            修改SupportedOrientations屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SearchTaskPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

37.            爲了簡化設計過程, 用下面的代碼替換整個 LayoutRoot :

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource
AppName}"Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Search Task"Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <Grid.RowDefinitions>

            <RowDefinition/>

            <RowDefinition/>

            <RowDefinition/>

        </Grid.RowDefinitions>

        <StackPanel Orientation="Vertical"Grid.Row="0">

            <TextBlock Text="Define search terms:"
Style="{StaticResource TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtInput"InputScope="Search"/>

        </StackPanel>

 

        <StackPanel Orientation="Vertical"Grid.Row="2">

        <Button x:Name="btnSearch"Content="Search Everywhere"  Margin="0,5" Click="btnSearch_Click"/>

        </StackPanel>

    </Grid>

</Grid>

前面的標記語言代碼呈現如下的樣子:

圖 8

搜索頁面

38.            打開 SearchTaskPage.xaml.cs.

39.            添加 btnSearch_Click事件到SearchTaskPage.xaml.cs 文件中代碼的末尾:

C#

private void btnSearch_Click(object sender, RoutedEventArgse)

{

 

}

40.            打開 MainPage.xaml.cs 頁面並定位到如下注釋的部分:

C#

private void btnSearchTask_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to search task page

}

41.            使用以下的代碼替換掉註釋部分:

C#

private void btnSearchTask_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/SearchTaskPage.xaml", UriKind.Relative));

}

42.            添加新的頁面WebSearchPageViews 文件夾,使用 "Windows Phone Portrait Page" 模板.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item

43.            定位到PhoneApplicationPage 元素.

44.            修改SupportedOrientations屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.WebSearchPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

45.            爲了簡化設計過程,使用如下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource
AppName}"Style="{StaticResource PhoneTextNormalStyle}"/>

            <TextBlock x:Name="PageTitle" Text="Search Web"  Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

        <StackPanel Orientation="Vertical"Grid.Row="0">

            <TextBlock Text="Phrase:" Style="{StaticResource  TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtInput"InputScope="Text"/>

        </StackPanel>

        <StackPanel Orientation="Vertical" Grid.Row="1">

            <Button x:Name="btnGo" Content="Search With Bing"  Margin="0,5" Click="btnGo_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記語言代碼使界面看起來像這樣:

圖 9

瀏覽Web頁面

46.            打開 WebSearchPage.xaml.cs.

47.            添加 btnGo_Click事件到 WebSearchPage.xaml.cs 頁面:

C#

private void btnGo_Click(objectsender, RoutedEventArgs e)

{

 

}

48.            打開 MainPage.xaml.cs 文件定位到以下注釋部分:

C#

private void btnSearchWithBing_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to search with bing page

}

 

49.            用下面的代碼替換掉註釋部分:

C#

private void btnSearchWithBing_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/WebSearchPage.xaml", UriKind.Relative));

}

50.            添加一個新的頁面VideoPlayerPageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

51.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.VideoPlayerPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

52.            爲了簡化設計過程,使用以下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource  AppName}" Style="{StaticResourcePhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Play Video"Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <Button Content="Play Video" x:Name="btnPlayVideo"Click="btnPlayVideo_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記描述語言代碼使界面看起來像下面的樣子:

圖 10

視頻播放器頁面

53.            添加下面的事件至VideoPlayerPage.xaml.cs:

C#

private void btnPlayVideo_Click(object sender, RoutedEventArgse)

{

 

}

54.            添加新的導航命令至MainPage.xaml.cs. 定位到註釋部分:

C#

private void btnShowVideo_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to show video page

}

用下面的代碼替換掉註釋部分:

C#

private void btnShowVideo_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/VideoPlayerPage.xaml", UriKind.Relative));

}

55.            添加一個新的頁面SaveRingtonePageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

56.            修改 SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SaveRingtonePage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

57.            爲了簡化設計過程,使用下面的代碼替換掉整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <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="Save Ringtone"Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1" Margin="0">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <Button Content="Save Ringtone" x:Name="btnSaveRingtone"Click="btnSaveRingtone_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記描述語言使界面看起來像下面的樣子:

圖 11

保存鈴音頁面

58.            添加下面的事件到SaveRingtonePage.xaml.cs:

C#

private voidbtnSaveRingtone_Click(object sender, RoutedEventArgs e)

{

 

}

59.            在 MainPage.xaml.cs中 定位到如下注釋部分:

C#

private void btnSaveRingtone_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to the save ringtone page

}

使用下面的代碼替換掉註釋部分:

C#

private void btnSaveRingtone_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/SaveRingtonePage.xaml",

 UriKind.Relative));

}

60.            添加一個新的頁面ComposeEmailPageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

61.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ComposeEmailPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

62.            爲了簡化設計過程,使用以下的代碼替換掉整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <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="Email"
Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1" >

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <TextBlock Text="To:" Style="{StaticResource

TextBlockTitleMediumStyle}"/>

            <TextBox x:Name="txtTo" InputScope="EmailNameOrAddress" Margin="0"/>

            <TextBlock Text="CC:" Style="{StaticResourceTextBlockTitleMediumStyle}"/>

            <TextBox x:Name="txtCc" InputScope="EmailNameOrAddress" Margin="0"/>

            <TextBlock Text="BCC:" Style="{StaticResourceTextBlockTitleMediumStyle}"/>

            <TextBox x:Name="txtBcc"InputScope="EmailNameOrAddress" Margin="0"/>

            <TextBlock Text="Subject:" Style="{StaticResourceTextBlockTitleMediumStyle}"/>

            <TextBox x:Name="txtSubject"Margin="0"/>

            <TextBlock Text="Body:" Style="{StaticResourceTextBlockTitleMediumStyle}"/>

            <TextBox x:Name="txtBody" Margin="0"/>

            <Button Content="Create Email" x:Name="btnCreateEmail"Click="btnCreateEmail_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述的標記描述語言代碼使界面看起來像下面的樣子:

圖 12

發送Email頁面

63.            在 ComposeEmailPage.xaml.cs中添加如下事件:

C#

private voidbtnCreateEmail_Click(object sender, RoutedEventArgs e)

{

 

}

64.            在 MainPage.xaml.cs. 頁面中定位到如下的代碼:

C#

private void btnComposeEmail_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to the email composition page

}

用下面的代碼替換掉註釋部分:

C#

private void btnComposeEmail_Click(object sender, RoutedEventArgs e)

{

   NavigationService.Navigate(new Uri("/Views/ComposeEmailPage.xaml",

UriKind.Relative));

}

65.            添加新的頁面ShowMapPageViews 文件夾.

注意爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

66.            修改 SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ShowMapPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

67.            爲了簡化設計過程,使用以下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <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="Show Map" Margin="9,-7,0,0" Style="{StaticResourcePhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1" Margin="0">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <RadioButton x:Name="radioLocation"Content="Center on location:" IsChecked="True"/>

            <TextBox x:Name="txtLocation"IsEnabled="{Binding ElementName=radioLocation, Path=IsChecked}" Margin="0,0,0,10"/>

            <RadioButton x:Name="radioCoordinate"Content="Center on coordinate:"/>

            <Grid Margin="0,0,0,10">

                <Grid.ColumnDefinitions>

                   <ColumnDefinition Width="Auto"/>

                   <ColumnDefinition Width="*"/>

                </Grid.ColumnDefinitions>

 

                <Grid.RowDefinitions>

                    <RowDefinition Height="Auto"/>

                   <RowDefinition Height="Auto"/>

                </Grid.RowDefinitions>

 

                <TextBlock Text="Latitude:"Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Style="{StaticResource

TextBlockTitleMediumStyle}"/>

                <TextBox x:Name="txtLatitude"Grid.Row="0"

Grid.Column="1" IsEnabled="{Binding ElementName=radioCoordinate,

Path=IsChecked}" InputScope="Number"/>

                <TextBlock Text="Longitude:"Grid.Row="1"

Grid.Column="0"VerticalAlignment="Center" Style="{StaticResource

TextBlockTitleMediumStyle}"/>

                <TextBox x:Name="txtLongitude"Grid.Row="1" Grid.Column="1" IsEnabled="{Binding ElementName=radioCoordinate, Path=IsChecked}" InputScope="Number"/>

        </Grid>

 

        <TextBlock Text="Zoom level:"Style="{StaticResource TextBlockTitleLargeStyle}"/>

        <TextBox x:Name="txtZoom"InputScope="Number"/>

        <Button Content="Show Map" x:Name="btnShowMap" Click="btnShowMap_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記表述語言代碼使界面呈現以下的樣子:

圖 13

顯示地圖頁面

68.            在ShowMapPage.xaml.cs中添加如下的事件:

C#

private voidbtnShowMap_Click(object sender, RoutedEventArgs e)

{

 

}

69.            在 MainPage.xaml.cs. 定位到如下代碼位置:

C#

private void btnShowMap_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the map viewing page

}

使用下面的代碼替換掉註釋部分:

C#

private void btnShowMap_Click(object sender, RoutedEventArgs e)

{

   NavigationService.Navigate(new Uri("/Views/ShowMapPage.xaml", UriKind.Relative));

}

70.            添加新的頁面DirectionsPageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

71.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.DirectionsPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

72.            爲了簡化設計過程,使用以下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <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="Directions"Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1" >

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <TextBlock Text="Origin:" Style="{StaticResourceTextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtOrigin" Margin="0"/>

            <TextBlock Text="Destination:"Style="{StaticResource TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtDestination"Margin="0"/>

            <Button Content="Get Directions" x:Name="btnGetDirections"Click="btnGetDirections_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記描述語言使界面看起來像這樣:

圖 14

Directions頁面

73.            在DirectionsPage.xaml.cs中添加以下事件:

C#

private voidbtnGetDirections_Click(object sender, RoutedEventArgs e)

{

 

}

74.            在 MainPage.xaml.cs.中定位到如下注釋部分:

C#

private void btnGetDirections_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the directions page
}

然後用下面的代碼替換註釋部分:

C#

private void btnGetDirections_Click(object sender, RoutedEventArgs e)

{

    NavigationService.Navigate(new Uri("/Views/DirectionsPage.xaml", UriKind.Relative));

}

75.            添加新的頁面ShowMarketplacePageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

76.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ShowMarketplacePage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

77.            爲了簡化設計過程,使用下面的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

    <!--TitlePanel containsthe name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Marketplace"

Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

     <!--ContentPanel - placeadditional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <Button Content="Show Marketplace"

x:Name="btnShowMarketplace" Click="btnShowMarketplace_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述的標記描述語言使界面看起來像下面的樣子:

圖 15

顯示Marketplace 頁面

78.            在 ShowMarketplacePage.xaml.cs中添加以下事件:

C#

private voidbtnShowMarketplace_Click(object sender, RoutedEventArgs e)

{

 

}

79.            在 MainPage.xaml.cs.定位到以下注釋部分:

C#

private void btnShowMarketplace_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the marketplace

}

用以下代碼替換掉註釋部分:

C#

private void btnShowMarketplace_Click (object sender, RoutedEventArgs e)

{

   NavigationService.Navigate(new Uri("/Views/ShowMarketplacePage.xaml",

UriKind.Relative));

}

80.            添加新的頁面SearchMarketplacePageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

81.            修改 SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage x:Class="LaunchersAndChoosers.Views.SearchMarketplacePage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

82.            爲了簡化設計過程,使用以下代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Marketplace"Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <TextBlock Text="Search Term:"Style="{StaticResource TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtSearchTerm"/>

            <Button Content="Search Marketplace" x:Name="btnSearchMarketplace" Click="btnSearchMarketplace_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述標記描述語言使界面呈現以下效果:

圖 16

搜索 Marketplace 頁面

83.            在 SearchMarketplacePage.xaml.cs中添加以下事件:

C#

private voidbtnSearchMarketplace_Click(object sender,

RoutedEventArgs e)

{

 

}

84.            在MainPage.xaml.cs. 定位到以下注釋部分:

C#

private void btnSearchMarketplace_Click(object sender,

RoutedEventArgs e)

{

    //TODO - navigate to the marketplace search page

}

用下面的代碼替換註釋部分:

C#

private void btnSearchMarketplace_Click (object sender,

RoutedEventArgs e)

{

   NavigationService.Navigate(new
Uri("/Views/SearchMarketplacePage.xaml",UriKind.Relative));

}

85.            添加新的文件MarketplaceDetailsPageViews 文件夾.

注意: 爲了添加一個新的頁面, 右鍵單擊 Views 文件夾,從下拉菜單中選擇 Add ,然後從Add 上下文菜單中選擇New Item.

86.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape.

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.MarketplaceDetailsPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d=http://schemas.microsoft.com/expression/blend/2008

    xmlns:mc=http://schemas.openxmlformats.org/markup-compatibility/2006

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

87.            爲了簡化設計過程,使用下面的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the applicationand page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Text="{StaticResource

AppName}" Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Marketplace"

Margin="-3,-8,0,0" Style="{StaticResourcePhoneTextTitle1Style}"/>

    </StackPanel>

 
    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <StackPanel Grid.Row="0" Orientation="Vertical">

            <Button Content="ShowDetails"

x:Name="btnMarketplaceDetails" Click="btnMarketplaceDetails_Click"/>

        </StackPanel>

    </Grid>

</Grid>

上述的標記描述語言使界面呈現如下:

圖 17

Marketplace詳細頁面

88.            在 MarketplaceDetailsPage.xaml.cs添加如下事件:

C#

private voidbtnMarketplaceDetails_Click(object sender,
RoutedEventArgs e)

{

 

}

89.            在 MainPage.xaml.cs中定位到如下注釋部分:

C#

private void btnMarketplaceDetails_Click(object sender,

RoutedEventArgs e)

{

    //TODO - navigate to the marketplace details page

}

用下面的代碼替換掉註釋部分:

C#

private void btnSearchMarketplace_Click (object sender,

RoutedEventArgs e)

{

   NavigationService.Navigate(new

Uri("/Views/MarketplaceDetailsPage.xaml",UriKind.Relative));

}

90.            編譯並運行程序,檢查導航是否正確工作,並檢查不同頁面的軟鍵盤格式.

 

任務 2 – 使用 Launchers

一個 launcher是一個API,它啓動一個系統內置應用程序,通過這個內置應用程序用戶可以完成一些任務,當任務完成時沒有返回值. 其中一個例子是PhoneCallTask.應用程序可以提供給這個launcher一個電話號碼和顯示名稱來啓動電話程序. 當電話程序啓動的時候,用戶可以選擇是否撥打電話。當用戶關閉電話應用程序的時候,應用程序被重新激活,但是電話應用程序不返回任何數據。當應用程序啓動一個launcher,它不會得到返回值.

1.               打開SavePhoneNumberPage.xaml.cs.

注意: 在本實驗中使用正則表達式來驗證用戶輸入.

2.               添加下面的代碼到SavePhoneNumberPage 類:

C#

//Regex patterns provided by http://regexlib.com/

const string phoneNumberPattern = @"^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})(|-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$";

Note: The regular expression is providedby the “Regular Expression Library” site (http://regexlib.com).For more information about regular expressions refer to the MSDN documentation(http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx).

3.               添加下面的命名空間:

C#

using System.Text.RegularExpressions;

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

4.               重寫 OnNavigatedFrom 和 OnNavigatedTo 來保存電話號碼到頁面狀態,這樣當應用程序從墓碑化激活之後能重新顯示.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SavePhoneNumberPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

   State.Add(inputStateKey, txtInput.Text);

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SavePhoneNumberPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        string input = (string)State[inputStateKey];

        txtInput.Text = input;

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

5.               添加下面的常量到SavePhoneNumberPage 類.

C#

const string inputStateKey = "input";

6.               添加 SavePhoneNumberTask 變量到SavePhoneNumberPage 類.

C#

SavePhoneNumberTask savePhoneNumberTask;

 

7.               在構造函數中添加下面高亮部分的代碼初始化savePhoneNumberTask 變量 ,並輸出調試信息.

C#

public SavePhoneNumberPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofSavePhoneNumberPage\t ***");

 

   savePhoneNumberTask = new SavePhoneNumberTask();

    savePhoneNumberTask.Completed+= new EventHandler<TaskEventArgs>(savePhoneNumberTask_Completed);

}

8.               添加下面的代碼處理完成事件.

C#

voidsavePhoneNumberTask_Completed(object sender, TaskEventArgs e)

{

    Debug.WriteLine("***\t In savePhoneNumberTask_Completed function ofSavePhoneNumberPage\t ***");

   

    if (e.TaskResult == TaskResult.OK)

        MessageBox.Show("Phone number saved successfully", "Success", MessageBoxButton.OK);

    else if (e.TaskResult == TaskResult.Cancel)

        MessageBox.Show("Phone number was not saved - operation wascancelled", "Contact notselected", MessageBoxButton.OK);

    else

        MessageBox.Show("Error while saving phone number:\n" +e.Error.Message, "Fail", MessageBoxButton.OK);

}

9.               使用正則表達式驗證用戶輸入. 如果驗證通過,使用SavePhoneNumberTask 來保存合法的電話號碼. SavePhoneNumberTask 使應用程序可以啓動聯繫人應用程序.使用它可以使用戶保存一個電話號碼至已有或者新建聯繫人.

C#

private void btnSavePhone_Click(object sender, RoutedEventArgse)

{

    if (Regex.IsMatch(txtInput.Text,phoneNumberPattern, RegexOptions.IgnoreCase))

    {

        if (null !=savePhoneNumberTask)

        {

           savePhoneNumberTask.PhoneNumber = txtInput.Text;

           savePhoneNumberTask.Show();

        }

    }

    else

    {

        MessageBox.Show("Specifiedvalue is not a valid phone number\nValid phone number looks like thefollowing:\n1-(123)-123-1234, 123 123 1234, 1-800-ALPHNUM", "Invalid Input", MessageBoxButton.OK);

    }

 }

10.            按 F5 編譯並運行應用程序.

11.            導航到 Save Phone Number 頁面並輸入一個合法的電話號碼.

12.            點擊Save Phone Number 啓動Launcher.

13.            使用標準的 Windows® Phone 7 界面添加一個電話號碼至已有或新增聯繫人:

圖 18

添加一個電話號碼至已有或新增聯繫人

14.            可選的, 可以給聯繫人一個名稱.

圖 19

新增聯繫人信息

 

15.            保存聯繫人並按下Back ():

圖 20

顯示返回信息

注意: 輸入的電話號碼顯示在輸入框,儘管應用程序在調用PhoneSaveTask 中被放置到後臺,分析調試輸出信息可以更好的理解這一點.

16.            重複以上步驟添加一個新聯繫人.

注意: 模擬器只會在運行期間保存聯繫人數據. 在這些步驟中請不要關閉模擬器,以保證在本實驗後面能看到聯繫人數據

17.            按 SHIFT+F5 停止調試並返回編輯模式.

18.            打開 SaveEmailAddressPage.xaml.cs.

19.            使用以下的正則表達式驗證用戶輸入. 添加下面的代碼到aveEmailAddressPage 類中:

C#

//Regex patterns provided by http://regexlib.com/

const string emailAddressPattern = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";

20.            添加下面的引用聲明:

C#

using System.Text.RegularExpressions;

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

21.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法用來保存Email地址到頁面狀態,這樣當應用程序從墓碑化激活後能重新顯示.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SaveEmailAddressPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

    State.Add(inputStateKey,txtInput.Text);

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SaveEmailAddressPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        string input = (string)State[inputStateKey];

        txtInput.Text= input;

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

 

22.            添加下面的常量到SaveEmailAddressPage 類.

C#

const string inputStateKey = "input";

23.            添加一個 SaveEmailAddressTask 變量到 SaveEmailAddressPage 類.

C#

SaveEmailAddressTask saveEmailAddressTask;

24.            在構造函數中用下面高亮部分的代碼來初始化saveEmailAddressTask 變量.

C#

public SaveEmailAddressPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofSaveEmailAddressPage\t ***");

 

   saveEmailAddressTask = new SaveEmailAddressTask();

    saveEmailAddressTask.Completed+= new EventHandler<TaskEventArgs>(saveEmailAddressTask_Completed);

}

 

25.            添加完成事件.

C#

void saveEmailAddressTask_Completed(objectsender, TaskEventArgs e)

{

    Debug.WriteLine("***\t InsaveEmailAddressTask_Completed function of SaveEmailAddressPage\t ***");

 

    if (e.TaskResult == TaskResult.OK)

        MessageBox.Show("Emailaddress saved successfully", "Success",MessageBoxButton.OK);

    else if (e.TaskResult== TaskResult.Cancel)

        MessageBox.Show("Emailaddress was not saved - operation was cancelled", "Contact not selected", MessageBoxButton.OK);

    else

        MessageBox.Show("Errorwhile saving email address:\n" + e.Error.Message, "Fail", MessageBoxButton.OK);

}

 

26.            使用正則表達式驗證用戶輸入. 如果驗證通過, 使用SaveEmailAddressTask來保存合法的郵件地址,SaveEmailAddressTask 使應用程序可以啓動內置聯繫人應用程序.這樣可以使用戶保存郵件地址到已有或新增聯繫人.

C#

private void btnSaveEmail_Click(object sender, RoutedEventArgse)

{

    if (Regex.IsMatch(txtInput.Text, emailAddressPattern, RegexOptions.IgnoreCase))

    {

        if (null !=saveEmailAddressTask)

        {

           saveEmailAddressTask.Email = txtInput.Text;

           saveEmailAddressTask.Show();

        }

    }

    else

    {

        MessageBox.Show("Specifiedvalue is not a valid email address\nValid email address looks like thefollowing:\[email protected], [email protected]", "Invalid Input", MessageBoxButton.OK);

    }

 }

27.            按 F5 編譯和運行應用程序.

28.            導航到 Save Email 頁面,並輸入一個合法的郵件地址.

29.            點擊 Save Email Address啓動Launcher.

30.            使用標準的 Windows® Phone 7 界面添加一個郵件地址至已有或新增聯繫人:

圖 21

添加新的電子郵件至已有或新增聯繫人

31.            保存聯繫人並單擊Back ():

圖 22

Launcherreturn notification

32.            按 SHIFT+F5 停止調試並返回編輯模式.

33.            打開 SearchTaskPage.xaml.cs.

34.            添加下面的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

35.            重寫OnNavigatedFrom 和 OnNavigatedTo 方法保存搜索關鍵字到頁面狀態,這樣當應用程序從墓碑化激活之後可以重新顯示:

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SearchTaskPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

   State.Add(inputStateKey, txtInput.Text);

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SearchTaskPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        string input = (string)State[inputStateKey];

        txtInput.Text= input;

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

36.            添加下面的常數到SearchTaskPage 類:

C#

const string inputStateKey = "input";

37.            在構造函數中用下面高亮部分的代碼創建調試信息:

C#

public SearchTaskPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofSearchTaskPage\t ***");

}

38.            爲了執行搜索功能,本實驗使用SearchTask 來啓動Web搜索應用程序,找到btnSearch_Click 事件並添加以下代碼:

C#

private void btnSearch_Click(object sender, RoutedEventArgse)

{

   SearchTask searchTask = new SearchTask();

    searchTask.SearchQuery =txtInput.Text;

    searchTask.Show();

}

39.            編譯並運行應用程序.

40.            導航到搜索頁面並輸入搜索關鍵字:

 

圖 23

搜索頁面

41.            單擊 Search Everywhere. 如果可能,第一次搜索會顯示以下信息:

圖 24

允許應用程序使用地理信息

注意: 爲了優化搜索結果,搜索引擎可以使用手機或模擬器提供的地理信息

42.            單擊 Allow允許使用地理信息. 模擬器連接Web並返回搜索結果:

圖 25

Web搜索結果

43.            單擊Back ()返回應用程序.

44.            按 SHIFT+F5 停止調試並返回編輯模式.

45.            打開 WebSearchPage.xaml.cs.

46.            添加下面的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

 

47.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法以保存搜索數據至頁面狀態,當應用程序從墓碑化激活的時候可以重新顯示這些數據.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of WebSearchPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

   State.Add(inputStateKey, txtInput.Text);

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of WebSearchPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        string input = (string)State[inputStateKey];

        txtInput.Text= input;

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

48.            添加下面的常量到WebSearchPage.

C#

const string inputStateKey = "input";

49.            在構造函數中添加下面高亮部分的代碼以輸出調試信息.

C#

public WebSearchPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofWebSearchPage\t ***");

}

 

50.            Silverlight 有一個WebBrowser 控件,可以在應用程序中和其他控件一樣使用. 同時Windows Phone 還有一個 WebBrowser 允許在應用程序中直接啓動IE瀏覽器。本實驗使用 WebBrowserTask..找到btnGo_Click 事件添加以下代碼:

C#

private void btnGo_Click(object sender, RoutedEventArgse)

{

   WebBrowserTask webBrowserTask = new WebBrowserTask();

    conststring url = "http://m.bing.com/search?q={0}&a=results";

    webBrowserTask.URL = string.Format(url, txtInput.Text);

    webBrowserTask.Show();

}

51.            按 F5 編譯並運行應用程序.

52.            導航到搜索頁面並輸入搜索關鍵字:

 

圖 26

瀏覽Web頁面

啓動IE瀏覽器並導航到Bing頁面:

圖 27

Windows®Phone 7.1 IE

注意: 在 Windows® Phone 7.0 上瀏覽器有不同的外觀.

53.            按 SHIFT+F5 停止調試返回到編輯模式.

54.            打開 VideoPlayerPage.xaml.cs.

55.            添加下面的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

 

56.            重寫OnNavigatedFrom 和 OnNavigatedTo 在應用程序墓碑化的時候輸出調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of VideoPlayerPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of VideoPlayerPage\t ***");

 

    base.OnNavigatedTo(e);

}

57.            從本實驗的Source\Assets文件夾中,添加已經存在的視頻文件到Media 文件夾.

圖 28

添加一個已經存在的視頻文件

58.            在 Add Existing Item 對話框中瀏覽到 Assets文件夾, 選擇視頻文件, 從 Add 按鈕的下拉菜單選擇 Add As Link.

圖 29

選擇視頻文件

59.            確保視頻文件設置爲Content 資源. 爲了檢查這個, 在 Solution Explorer中單擊添加的文件並按F4顯示屬性面板.

圖 30

檢查添加視頻文件的 Build Action

60.            在構造函數中添加下高亮部分的代碼以輸入調試信息.

C#

public VideoPlayerPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofVideoPlayerPage\t ***");

}

61.            添加點擊處理事件,該方法會使用MediaPlayerLauncher, 它啓動媒體播放器播放視頻。添加下面的代碼到類中:

C#

private voidbtnPlayVideo_Click(object sender, RoutedEventArgs e)

{

  MediaPlayerLaunchermediaPlayerLauncher =
         new MediaPlayerLauncher();

   mediaPlayerLauncher.Location =
          MediaLocationType.Install; //means is aresource of the app, otherwise it will try to resolve it in Data(IsolatedStorage) for application

   mediaPlayerLauncher.Media = new Uri("Media/Bear.wmv", UriKind.Relative);

   mediaPlayerLauncher.Show();

}

62.            按 F5 編譯並運行.

63.            導航到視頻播放頁面並播放視頻.

圖 31

播放視頻

64.            按 SHIFT+F5 停止調試並返回到編輯模式.

65.            打開 SaveRingtonePage.xaml.cs.

66.            添加下面的引用聲明:

C#

using System.IO.IsolatedStorage;

using System.IO;

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

67.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法以使應用程序在墓碑化的時候輸出調試信息.

C#

protected overridevoid OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SaveRingtonePage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected overridevoid OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SaveRingtonePage\t ***");

 

    base.OnNavigatedTo(e);

}

68.            添加一個音頻文件用來作爲鈴聲. 重複 步驟 57-59兩次 , 但是取代的添加 “Bear.wmv” 和 “Ringtone.mp3”文件.

69.            在構造函數中添加下面高亮部分的代碼以輸出調試信息,並把我們要使用的新的鈴聲放置到獨立存儲中.

C#

public ComposeEmailPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofSaveRingtonePage\t ***");

 

    PlaceAssetInIsolatedStorage();

}

70.            添加下面的方法用來將鈴聲保存到獨立存儲

C#

private staticvoid PlaceAssetInIsolatedStorage()

{

    using (IsolatedStorageFileiso =
IsolatedStorageFile.GetUserStoreForApplication())

    {

        Stream str = Application.GetResourceStream(new
Uri("Media/Ring.mp3",UriKind.Relative)).Stream;

 

        IsolatedStorageFileStream outFile =iso.CreateFile("Ring.mp3");

 

       outFile.Write(ReadToEnd(str), 0, (int)str.Length);

       str.Close();

       outFile.Close();

    }

}

 

private staticbyte[] ReadToEnd(System.IO.Stream stream)

{

    long originalPosition = stream.Position;

    stream.Position= 0;

    try

    {

        byte[] readBuffer = newbyte[4096];

        int totalBytesRead = 0;

        intbytesRead;

 

        while ((bytesRead = stream.Read(readBuffer,totalBytesRead,
readBuffer.Length - totalBytesRead)) > 0)

        {

           totalBytesRead += bytesRead;

            if (totalBytesRead == readBuffer.Length)

            {

                intnextByte = stream.ReadByte();

                if (nextByte != -1)

                {

                   byte[] temp = newbyte[readBuffer.Length * 2];

                   Buffer.BlockCopy(readBuffer, 0, temp,0,
readBuffer.Length);

                    Buffer.SetByte(temp,totalBytesRead,
(byte)nextByte);

                   readBuffer = temp; totalBytesRead++;

                }

            }

        }

 

        byte[] buffer = readBuffer;

 

        if (readBuffer.Length != totalBytesRead)

        {

            buffer= new byte[totalBytesRead];

            Buffer.BlockCopy(readBuffer, 0, buffer, 0,totalBytesRead);

        }

 

        return buffer;

    }

    finally

    {

       stream.Position = originalPosition;

    }

}

71.            爲了讓用戶將某個鈴聲應用到聯繫人,我們會使用SaveRingtoneTask. 找到btnSaveRingtone_Click 並添加下面的代碼:

C#

private void btnSaveRingtone_Click(object sender, RoutedEventArgse)

{

    SaveRingtoneTask ringtoneTask = new SaveRingtoneTask();

           

    ringtoneTask.Source = new Uri("isostore:/Ring.mp3", UriKind.Absolute);

 

    ringtoneTask.Show();

}

72.            按 F5 編譯並運行應用程序.

73.            導航到 “Save Ringtone” 頁面,並按下屏幕上唯一的按鈕:

 

圖 32

保存鈴聲頁面

74.            按下 “Save Ringtone”按鈕會轉換到系統內置的鈴音保存界面,允許指定一個文件名稱並設置爲當前鈴音:

圖 33

內置鈴音保存界面

75.            按 SHIFT+F5 停止調試,並回到編輯模式.

76.            打開 ComposeEmailPage.xaml.cs.

77.            添加下面的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

78.            添加下面的類. 我們會用它來保存用戶輸入的數據:

C#

public classEmailInputData

{

    public string To { get; set; }

    public string Cc { get; set; }

    public string Bcc { get; set; }

    public string Subject{ get; set; }

    public string Body { get; set; }

}

79.            重寫OnNavigatedFrom 和 OnNavigatedTo 方法以保存Email數據到頁面狀態,以使應用程序在被墓碑化時能重新顯示.

C#

protected overridevoid OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of ComposeEmailPage\t ***");

           

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

    EmailInputData inputData = new EmailInputData

    {

        To =txtTo.Text,

        Cc =txtCc.Text,

        Bcc =txtBcc.Text,

        Subject =txtSubject.Text,

        Body =txtBody.Text

    };

 

    State.Add(inputStateKey,inputData);

 

    base.OnNavigatedFrom(e);

}

 

protected overridevoid OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of ComposeEmailPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        EmailInputData inputData = (EmailInputData)State[inputStateKey];

 

        txtTo.Text= inputData.To;

        txtCc.Text= inputData.Cc;

        txtBcc.Text= inputData.Bcc;

       txtSubject.Text = inputData.Subject;

       txtBody.Text = inputData.Body;

 

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

80.            添加下面的常量到ComposeEmailPage 類.

C#

const string inputStateKey = "input";

81.            在構造函數中添加下面高亮部分的代碼以輸出調試信息.

C#

public ComposeEmailPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofComposeEmailPage\t ***");

}

82.            爲了能發送電子郵件,我們會使用到EmailComposeTask. EmailComposeTask 啓動內置的電子郵件發送程序,並用用戶提供的數據作爲郵件內容. 找到btnCreateEmail_Click 事件並添加下面的代碼:

C#

private void btnCreateEmail_Click(object sender, RoutedEventArgse)

{

    if (Microsoft.Devices.Environment.DeviceType ==

        Microsoft.Devices.DeviceType.Emulator)

            {

                MessageBox.Show("Thisoperation is not supported in the emulator. Please use an actual device.");

                return;

            }

 

    EmailComposeTask composeTask = new EmailComposeTask();

 

    composeTask.To= txtTo.Text;

    composeTask.Cc= txtCc.Text;

    composeTask.Bcc= txtBcc.Text;

   composeTask.Subject = txtSubject.Text;

   composeTask.Body = txtBody.Text;

 

   composeTask.Show();

}

注意: 注意我們在方法的開頭部分添加一段代碼阻止此任務在Windows® Phone 7 模擬器上運行. 我們這樣做是因爲這個任務必須通過一個Email賬戶才能正確運行,但是在模擬器上不能設置Email賬戶.在後續的步驟中請確保你的設備上正確設置了Email賬戶以使任務正確運行.

83.            按 F5 編譯並運行應用程序.

84.            導航到發送郵件頁面,並填充相應的字段:

 

圖 34

發送一封郵件

85.            按下 “Create Email” 按鈕將會打開系統內置的Email發送器,呈現一個帶有提供數據的Email界面.

86.            按下 SHIFT+F5 停止調試並返回到編輯模式.

87.            打開 ShowMapPage.xaml.cs.

88.            添加如下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

using System.Device.Location;

89.            用以下的代碼添加一個類,我們會用它來存儲用戶輸入的數據:

C#

public classMapInputData

{

    public boolCenterOnCoordinate { get; set; }

    public stringLongitude { get; set;}

    public stringLatitude { get; set;}

    public stringLocation { get; set;}

    public stringZoomLevel { get; set;}

}

90.            重寫OnNavigatedFrom 和 OnNavigatedTo 方法以保存地圖數據至頁面狀態,這樣當應用程序從墓碑化狀態恢復時可以顯示這些數據.

C#

protected overridevoid OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of ShowMapPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

    MapInputData inputData = newMapInputData

    {

       CenterOnCoordinate = radioCoordinate.IsChecked.Value,

        Longitude =txtLongitude.Text,

        Latitude = txtLatitude.Text,

        Location =txtLocation.Text,

        ZoomLevel =txtZoom.Text

    };

 

   State.Add(inputStateKey, inputData);

 

    base.OnNavigatedFrom(e);

}

 

protected overridevoid OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of ShowMapPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        MapInputData inputData = (MapInputData)State[inputStateKey];

 

        if (inputData.CenterOnCoordinate)

        {

            radioCoordinate.IsChecked = true;

        }

        else

        {

           radioLocation.IsChecked = true;

        }

 

       txtLocation.Text = inputData.Location;

 

       txtLatitude.Text = inputData.Latitude;

       txtLongitude.Text = inputData.Longitude;

       txtZoom.Text = inputData.ZoomLevel;

 

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

91.            添加如下變量到ShowMapPage 類.

C#

const string inputStateKey = "input";

92.            在構造函數中添加以下高亮部分的代碼以輸入調試信息.

C#

public ShowMapPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofShowMapPage\t ***");

}

93.            爲了使用戶可以查看地圖,我們將會使用BingMapsTask. 它啓動內置的地圖應用程序,用用戶提供的數據初始化地圖的位置,找到 btnShowMap_Click 事件並添加以下的代碼:

C#

private void btnShowMap_Click(object sender, RoutedEventArgse)

{

    BingMapsTask mapTask = new BingMapsTask();

 

    if (radioCoordinate.IsChecked.Value)

    {

        double longitude;

        double latitude;

 

        if (!double.TryParse(txtLongitude.Text,out longitude) ||

            Math.Abs(longitude) > 180)

        {

            MessageBox.Show("Pleasesupply a longitude between -180 and 180");

            return;

        }

 

        if (!double.TryParse(txtLatitude.Text,out latitude) ||

            Math.Abs(latitude) > 90)

        {

            MessageBox.Show("Pleasesupply a longitude between -90 and 90");

            return;

        }

 

       mapTask.Center = new GeoCoordinate(latitude, longitude);

    }

    else

    {

       mapTask.SearchTerm = txtLocation.Text;

 

        if (String.IsNullOrEmpty(mapTask.SearchTerm))

        {

            MessageBox.Show("Pleaseprovide a location.");

            return;

        }

    }

 

    int zoomLevel;

 

    if (!int.TryParse(txtZoom.Text,out zoomLevel) || zoomLevel < 1 ||

        zoomLevel> 19)

    {

        MessageBox.Show("Pleasesupply a zoom level which is a whole number between 1 and 19.");

        return;

    }

 

   mapTask.ZoomLevel = zoomLevel;

 

    mapTask.Show();

}

94.            按 F5 編譯並運行應用程序.

95.            導航到展示地圖的頁面,並使用搜索框或者條件選擇一個地點:

 

圖 35

選擇地圖地點

96.            按下 “Show Map” 按鈕將會導航到系統內置的地圖應用程序,以提供的地點爲中心位置:

圖 36

地圖以指定的地點爲中心

注意: 如果你沒有設置過允許使用地理信息,你會收到類似的提示信息.

97.            按 SHIFT+F5 停止調試並返回到編輯模式.

98.            打開 DirectionsPage.xaml.cs.

99.            添加下面的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

100.        添加如下的類,用來存儲用戶輸入的數據:

C#

public classMapInputData

{

    public boolCenterOnCoordinate { get; set; }

    public stringLongitude { get; set;}

    public stringLatitude { get; set;}

    public stringLocation { get; set;}

    public stringZoomLevel { get; set;}

}

101.        重寫OnNavigatedFrom 和 OnNavigatedTo 方法用來保存方向數據在頁面狀態,這樣應用程序在墓碑化之後能夠重新顯示

C#

protected overridevoid OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of DirectionsPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

       State.Remove(inputStateKey);

 

    DirectionsInputData inputData = new DirectionsInputData

    {

        Origin =txtOrigin.Text,

        Destination= txtDestination.Text

    };

 

   State.Add(inputStateKey, inputData);

 

    base.OnNavigatedFrom(e);

}

 

protected overridevoid OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of DirectionsPage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

        DirectionsInputData inputData =

            (DirectionsInputData)State[inputStateKey];

 

       txtOrigin.Text = inputData.Origin;

        txtDestination.Text= inputData.Destination;

 

       State.Remove(inputStateKey);

    }

 

    base.OnNavigatedTo(e);

}

102.        添加如下的常量到DirectionsPage 類.

C#

const string inputStateKey = "input";

103.        在構造函數中添加以下高亮部分的代碼以輸出調試信息.

C#

public ShowMapPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofDirectionsPage\t ***");

}

104.        爲了讓用戶查看方向,我們將會使用ingMapsDirectionsTask.它啓動內置地圖應用程序,找到 btnGetDirections_Click 事件並添加以下的代碼:

C#

private void btnGetDirections_Click(object sender, RoutedEventArgse)

{

    BingMapsDirectionsTask directionsTask =

        new BingMapsDirectionsTask();

 

    if (String.IsNullOrEmpty(txtOrigin.Text))

    {

        MessageBox.Show("Pleasesupply an origin.");

        return;

    }

 

    if (String.IsNullOrEmpty(txtDestination.Text))

    {

        MessageBox.Show("Pleasesupply a destination.");

        return;

    }

 

   directionsTask.Start = new LabeledMapLocation(txtOrigin.Text, null);

   directionsTask.End = new LabeledMapLocation(txtDestination.Text,

        null);

 

   directionsTask.Show();

}

105.        按 F5 編譯並運行應用程序.

106.        導航到方向頁面,並選擇你希望顯示方向的兩個地點:

 

Figure 37

Selectingorigin and destination

107.        按下 “Get Directions” 按鈕將會啓動系統內置地圖應用程序,顯示相關的方向:

圖 38

顯示指定地點之間的方向

108.        按 SHIFT+F5 停止調試並返回到編輯模式.

109.        打開 ShowMarketplacePage.xaml.cs.

110.        添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

111.        重寫OnNavigatedFrom 和 OnNavigatedTo 方法在應用程序墓碑化的時候輸出調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of ShowMarketplacePage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of ShowMarketplacePage\t ***");

 

    base.OnNavigatedTo(e);

}

112.        在構造函數中添加以下高亮部分的代碼以輸出調試信息.

C#

public VideoPlayerPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofShowMarketplacePage\t ***");

}

113.        爲了讓用戶可以查看 marketplace,我們將會使用MarketplaceHubTask. 它啓動系統內置marketplace 應用程序. 找到btnShowMarketplace_Click 事件並添加以下代碼:

C#

private voidbtnShowMarketplace_Click(object sender, RoutedEventArgs e)

{

   MarketplaceHubTask marketplaceTask = new MarketplaceHubTask();

 

   marketplaceTask.Show();

}

114.        按 F5 編譯並運行程序.

115.        導航到顯示 marketplace 的頁面,並按下按鈕前往marketplace 中心.

圖 39

顯示 marketplace的頁面

116.        按下 SHIFT+F5 停止調試並返回到編輯模式.

117.        打開 SeachMarketplacePage.xaml.cs.

118.        添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

119.        重寫OnNavigatedFrom 和 OnNavigatedTo 方法保存搜索條件到頁面狀態,這樣當墓碑化後可以重新顯示.

C#

protected overridevoid OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SearchMarketplacePage\t ***");

 

    if (State.ContainsKey(inputStateKey))

        State.Remove(inputStateKey);

 

   State.Add(inputStateKey, txtSearchTerm.Text);

 

    base.OnNavigatedFrom(e);

}

 

protected overridevoid OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SearchMarketplacePage\t ***");

 

    if (State.ContainsKey(inputStateKey))

    {

       txtSearchTerm.Text = (String)State[inputStateKey];

    }

 

    base.OnNavigatedTo(e);

}

120.        添加以下常量到SearchMarketplacePage 類.

C#

const string inputStateKey = "input";

121.        在構造函數中添加以下高亮部分的代碼以輸出調試信息.

C#

public ShowMapPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor ofSearchMarketplacePage\t ***");

}

122.        爲了讓用戶搜索marketplace,我們將會使用MarketplaceSearchTask. enables an 它啓動系統內置的marketplace應用程序, 並僅僅顯示匹配的應用程序內容,找到btnSearchMarketplace_Click 事件並添加以下代碼:

C#

private void btnSearchMarketplace_Click(object sender,
RoutedEventArgs e)

{

    MarketplaceSearchTask marketplaceTask = new MarketplaceSearchTask();

 

   marketplaceTask.SearchTerms = txtSearchTerm.Text;

 

   marketplaceTask.Show();

}

123.        按 F5 編譯並運行應用程序.

124.        導航到marketplace 搜索頁面,並輸入一個搜索條件:

 

圖 40

搜索 marketplace

125.        按下 “Search Marketplace” 按鈕將會啓動內置的marketplace應用程序,並用提供的條件搜索應用程序:

圖 41

匹配搜索條件的內容

126.        按下 SHIFT+F5 停止調試並返回到編輯模式.

127.        打開 MarketplaceDetailsPage.xaml.cs.

128.        添加以下引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

129.        重寫OnNavigatedFrom 和 OnNavigatedTo 方法,當應用程序墓碑化的時候輸出調試信息

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of MarketplaceDetailsPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of MarketplaceDetailsPage\t ***");

 

    base.OnNavigatedTo(e);

}

130.        在構造函數中添加下面高亮部分的代碼以顯示調試信息.

C#

public VideoPlayerPage()

{

   InitializeComponent();

 

    Debug.WriteLine("***\t In constructor of MarketplaceDetailsPage\t***");

}

131.        爲了讓用戶查看一個 marketplace應用程序的詳細頁面我們將會用到 MarketplaceDetailTask. 它啓動系統內置的marketplace 應用程序並顯示一個給定應用程序的詳細頁面. 找到 btnMarketplaceDetails_Click 事件並添加以下代碼:

C#

private voidbtnMarketplaceDetails_Click(object sender,

RoutedEventArgs e)

{

   MarketplaceDetailTask marketplaceTask = new MarketplaceDetailTask();

 

   marketplaceTask.ContentIdentifier = "35323b0f-84d8-df11-a844-00237de2db9e";

 

   marketplaceTask.Show();

}

132.        按 F5 編譯並運行應用程序.

133.        導航到marketplace details 頁面,並按下按鈕顯示 “The Harvest™”應用程序的marketplace詳細頁面.

圖 42

顯示 一個marketplace 應用程序的詳細頁面

注意: 如果設備連接到計算機,Marketplace 以及許多相關的操作都不能進行,即時在調試的時候也不行.

134.        按下 SHIFT+F5 停止調試並返回到編輯模式.

這個步驟包括以下練習.

注意: 這個練習的解決方案可以在以下文件夾找到:Source\Ex1-Launchers\End.

 


 

練習 2: Choosers介紹和使用

一個 chooser是一個應用程序接口,通過它可以啓動一個內置應用程序來幫助用戶完成一些任務,當任務完成之後會返回某種類型的數據給調用應用程序。例如phone chooser 啓動 "contact people" 的界面搜索一個特定的聯繫人,當完成的時候請求的聯繫人信息會被返回。另一個例子是 PhotoChooserTask.它可以啓動Photo Chooser 應用程序使用戶可以選擇一張照片,用戶可以選擇取消,當選擇完成之後,調用它的應用程序被重新激活,並返回數據給調用應用程序。 返回的數據包含一個值指示用戶是否完成了任務,如果用戶完成了任務,返回結果包含相關數據,比如包含選中照片文件的IO文件流.

任務 1 – 使用 Choosers

不像前面的練習,我們已經添加了搜索的頁面,剩下的僅僅是實現它的邏輯。這裏我們會添加每一個頁面並且立即實現它的邏輯.

1.               打開 MicrosoftVisual Studio 2010 Express for Windows Phone :Start | All Programs | MicrosoftVisual Studio 2010 Express | Microsoft Visual Studio 2010 Express for WindowsPhone.

Visual Studio 2010: 打開 Visual Studio 2010 : Start | All Programs |Microsoft Visual Studio 2010.

2.               從本實驗的文件夾打開起始解決方案:Source\Ex2-Choosers\Begin.

注意: 你也可以在前一個練習的基礎上繼續本實驗.

3.               在 Views 文件夾添加一個頁面命名爲 MakePhoneCallPage.

注意: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

4.               在我們剛創建的頁面找到PhoneApplicationPage 元素.

5.               修改 SupportedOrientations 屬性的值爲PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.MakePhoneCallPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

6.               爲了簡化設計過程,使用下面的代碼整個替換 LayoutRoot 元素:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResourcePhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="PhoneCall"Margin="-3,-8,0,0" Style="{StaticResourcePhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <StackPanel Orientation="Vertical" Grid.Row="0">

            <Button x:Name="btnMakePhoneCall" Content="MakeCall"Margin="0,5" Click="btnMakePhoneCall_Click"/>

        </StackPanel>

    </Grid>

</Grid>

7.               打開 MakePhoneCallPage.xaml.cs.

8.               添加 btnMakePhoneCall_Click事件到MakePhoneCallPage.xaml.cs 的末尾.

C#

private void btnMakePhoneCall_Click(object sender, RoutedEventArgse)

{

 

}

9.               打開 MainPage.xaml.cs 並找到以下注釋部分:

C#

private void btnMakePhoneCall_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to make phone call page

}

10.            用以下高亮部分的代碼替換掉註釋部分:

C#

private void btnMakePhoneCall_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/MakePhoneCallPage.xaml", UriKind.Relative));

}

11.            打開 MakePhoneCallPage.xaml.cs.

12.            添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

 

13.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法在應用程序墓碑化的時候輸出調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of MakePhoneCallPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of MakePhoneCallPage\t ***");

 

    base.OnNavigatedTo(e);

}

在這個頁面中,我們會撥打一個前面練習中添加的聯繫人,爲了獲取聯繫人的電話號碼號碼,我們會使用 PhoneNumberChooserTask 類. 它啓動聯繫人應用程序來獲得一個用戶選擇的聯繫人的電話號碼. 這個 chooser是異步的,因此必須在啓動它之前訂閱 “Completed” 事件. 當這個chooser返回一個電話號碼時,使用 PhoneCallTask 來撥打選中的電話號碼.

14.            添加以下的變量:

C#

PhoneNumberChooserTask phoneNumberChooserTask;

15.            在構造函數中添加以下高亮部分的代碼:

C#

public MakePhoneCallPage()

{

    InitializeComponent();

   

    Debug.WriteLine("***\t Inconstructor of MakePhoneCallPage\t ***");

   

    phoneNumberChooserTask = new PhoneNumberChooserTask();

    phoneNumberChooserTask.Completed+= new EventHandler<PhoneNumberResult>(phoneNumberChooserTask_Completed);

}

16.            使用以下代碼添加一個完成事件phoneNumberChooserTask_Completed 來處理一些邏輯:

C#

void phoneNumberChooserTask_Completed(object sender,

                        PhoneNumberResult e)

{

    string debugMsg = string.Format(

        "***\t In phoneNumberChooserTask_Completed function ofMakePhoneCallPage, phone number returned: {0}, for contact: {1}\t ***",

    e.PhoneNumber, e.DisplayName);

    Debug.WriteLine(debugMsg);

 

    if (e.TaskResult == TaskResult.OK)

    {

        PhoneCallTask phoneCallTask = new PhoneCallTask();

        phoneCallTask.PhoneNumber =e.PhoneNumber;

        phoneCallTask.Show();

    }

    else if(e.TaskResult == TaskResult.Cancel)

        MessageBox.Show("Cannot make a phone call without a phone number", "Number not selected", MessageBoxButton.OK);

    else

        MessageBox.Show("Error getting phone number:\n" +e.Error.Message, "Fail", MessageBoxButton.OK);

}

17.            添加以下事件btnMakePhoneCall_Click :

C#

private void btnMakePhoneCall_Click(object sender, RoutedEventArgse)

{

   phoneNumberChooserTask.Show();

}

18.            按 F5 編譯並運行程序.

19.            導航到 “Make a Phone Call” 頁面並 單擊 Make Call:

圖 43

撥打電話

20.            選擇聯繫人:

圖 44

選擇一個聯繫人

21.            如果一個聯繫人有多個電話號碼,會有一個額外的選擇頁面. 在本示例中,選擇其中一個電話號碼。如果此聯繫人只有一個電話號碼,選擇聯繫人及完成號碼的選擇.

圖 45

可選的號碼選擇步驟

22.            單擊 call 撥打電話:

圖 46

撥打電話

23.            單擊 end  返回撥打電話的頁面:

圖 47

正在通話屏幕

24.            按 SHIFT+F5 停止調試並返回編輯模式.

25.            在 Views 文件夾添加另外一個頁面命名爲SendSMSPage.

注意: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

26.            找到PhoneApplicationPage 元素.

27.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SendSMSPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

28.            爲了簡化設計過程,使用以下代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource
AppName}"Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Send SMS"
Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

            <RowDefinition Height="Auto"/>

        </Grid.RowDefinitions>

        <StackPanel Orientation="Vertical"Grid.Row="0">

            <TextBlock Text="Message:" Style="{StaticResource
TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtInput"InputScope="Chat"/>

        </StackPanel>

        <StackPanel Orientation="Vertical"Grid.Row="2">

            <Button x:Name="btnSendSMS" Content="Send SMS"
Margin="0,5" Click="btnSendSMS_Click"/>

        </StackPanel>

    </Grid>

</Grid>

 

29.            打開 SendSMSPage.xaml.cs.

30.            添加 btnSendSMS_Click事件到 SendSMSPage.xaml.cs 代碼中.

C#

private void btnSendSMS_Click(object sender, RoutedEventArgse)

{

 

}

31.            打開 MainPage.xaml.cs 並且找到以下注釋部分:

C#

private void btnSendSMS_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to send SMS page

}

32.            使用以下高亮部分代碼替換掉註釋部分:

C#

private void btnSendSMS_Click(objectsender, RoutedEventArgs e)

{

   NavigationService.Navigate(new Uri("/Views/SendSMSPage.xaml", UriKind.Relative));

}

33.            打開SendSMSPage.xaml.cs.

34.            添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

35.            重寫OnNavigatedFrom 和 OnNavigatedTo 方法在應用程序墓碑化的時候輸出調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of SendSMSPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of SendSMSPage\t ***");

 

    base.OnNavigatedTo(e);

}

這個練習使用戶可以發送短信息到前面練習中添加的其中一個聯繫人。跟前一個頁面一樣,這個頁面使用PhoneNumberChooserTask 來選擇電話號碼. 然後使用SmsComposeTask來啓動發送短信息的應用程序併發送短信到指定的聯繫人.

36.            添加下面的變量到類中:

C#

PhoneNumberChooserTask phoneNumberChooserTask;

37.            在構造函數中添加以下高亮部分的代碼:

C#

public UsePhoneNumberPage()

{

    InitializeComponent();

 

   Debug.WriteLine("***\t Inconstructor of SendSMSPage\t ***");

   

    phoneNumberChooserTask = new PhoneNumberChooserTask();

   phoneNumberChooserTask.Completed += new EventHandler<PhoneNumberResult>(phoneNumberChooserTask_Completed);

}

38.            添加 phoneNumberChooserTask_Completed 事件來處理相關邏輯:

C#

void phoneNumberChooserTask_Completed(object sender,
                         PhoneNumberResult e)

{

    string debugMsg = string.Format(

        "***\t In phoneNumberChooserTask_Completed function of SendSMSPage,phone number returned: {0}, for contact: {1}\t ***",

    e.PhoneNumber, e.DisplayName);

 

    Debug.WriteLine(debugMsg);

 

    if (e.TaskResult == TaskResult.OK)

    {

        SmsComposeTasksmsComposeTask = new SmsComposeTask();

        if(!string.IsNullOrEmpty(txtInput.Text))

            smsComposeTask.Body = txtInput.Text;

        smsComposeTask.To =e.PhoneNumber;

        smsComposeTask.Show();

    }

    else if(e.TaskResult == TaskResult.Cancel)

        MessageBox.Show("Cannot send SMS without a phone number","Number not selected", MessageBoxButton.OK);

    else

        MessageBox.Show("Error getting phone number:\n" + e.Error.Message,"Fail", MessageBoxButton.OK);

}

39.            添加 btnSendSMS_Click 事件:

C#

private void btnSendSMS_Click(object sender, RoutedEventArgse)

{

   phoneNumberChooserTask.Show();

}

40.            按 F5 編譯並運行應用程序.

41.            導航到 “Send SMS” 頁面,輸入一條信息並單擊Send SMS:

圖 48

發送信息

42.            選擇聯繫人.

圖 49

選擇一個聯繫人

43.            如果一個聯繫人有多個電話號碼,會有一個額外的選擇步驟,在本示例中我們選擇其中一個電話號碼. 如果只有一個電話號碼,選擇聯繫人就完成了電話號碼的選擇.

圖 50

可選的選擇電話號碼的步驟

44.            如果需要可以修改前面輸入的短信內容,然後單擊 Send ():

圖 51

發送短信息

45.            按 Back ().

46.            按 SHIFT+F5 停止調試並返回編輯模式.

注意: 接下來得步驟演示發送電子郵件到一個聯繫人. 記住我們前面提到的,此功能在Windows®Phone 模擬器中不可用.

47.            在 Views 文件夾下添加另外的頁面命名爲UseEmailAddressPage.

注意: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

48.            定位到PhoneApplicationPage 元素.

49.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.UseEmailAddressPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

50.            爲了簡化設計過程,使用以下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResourcePhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="EmailAddress"Margin="-3,-8,0,0" Style="{StaticResourcePhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <StackPanel Orientation="Vertical" Grid.Row="0">

            <Button x:Name="btnSendEmail" Content="SendEmail"Margin="0,5" Click="btnSendEmail_Click"/>

        </StackPanel>

    </Grid>

</Grid>

 

51.            打開 UseEmailAddressPage.xaml.cs.

52.            添加 btnSendEmail_Click事件到UseEmailAddressPage.xaml.cs 文件.

C#

private void btnSendEmail_Click(object sender, RoutedEventArgse)

{

 

}

53.            打開 MainPage.xaml.cs 找到以下注釋部分:

C#

private void btnUseEmailAddress_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to use saved email address page

}

54.            用以下代碼替換掉註釋部分:

C#

private void btnUseEmailAddress_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(

        new Uri("/Views/UseEmailAddressPage.xaml", UriKind.Relative));

}

55.            打開 the UseEmailAddressPage.xaml.cs.

56.            添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

57.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法在應用程序墓碑化的時候輸入調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of UseEmailAddressPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of UseEmailAddressPage\t ***");

 

    base.OnNavigatedTo(e);

}

在這個頁面中,我們將會選擇在前面添加的其中一個聯繫人發送電子郵件,爲了得到Email,我們將會使用EmailAddressChooserTask 類. 它啓動聯繫人應用程序並取到一個用戶選擇的聯繫人的電子郵件. 這個 chooser 是異步的,因此你必須在啓動它之前訂閱 “Completed” 事件. 當選擇完成返回Email地址之後我們使用EmailComposeTask 來發送電子郵件,前面我們已經完成此練習.

58.            添加下面的變量:

C#

EmailAddressChooserTask emailAddressChooserTask;

59.            在構造函數中添加以下代碼:

C#

public UseEmailAddressPage()

{

    InitializeComponent();

 

   Debug.WriteLine("***\t Inconstructor of UseEmailAddressPage\t ***");

   

    emailAddressChooserTask = new EmailAddressChooserTask();

    emailAddressChooserTask.Completed += newEventHandler<EmailResult>(emailAddressChooserTask_Completed);

}

60.            使用以下的代碼添加emailAddressChooserTask_Completed 事件:

C#

void emailAddressChooserTask_Completed(object sender, EmailResult e)

{

    string debugMsg = string.Format(

        "***\t InemailAddressChooserTask_Completed function of UseEmailAddressPage, emailaddress returned: {0}, for contact: {1}\t ***",

    e.Email,e.DisplayName);

    Debug.WriteLine(debugMsg);

 

    if (e.TaskResult == TaskResult.OK)

    {

        EmailComposeTaskemailComposeTask = new EmailComposeTask();

        emailComposeTask.Body = "Hi, will you attend the meeting tomorrow?";

        emailComposeTask.To = e.Email;

        emailComposeTask.Show();

    }

    else if (e.TaskResult == TaskResult.Cancel)

        MessageBox.Show("Cannot send email without the email address","Email address not selected", MessageBoxButton.OK);

    else

        MessageBox.Show("Error getting email address:\n" +e.Error.Message, "Fail", MessageBoxButton.OK);

}

61.            添加 btnSendEmail_Click 事件:

C#

private void btnSendEmail_Click(object sender, RoutedEventArgse)

{

    if (Microsoft.Devices.Environment.DeviceType == Microsoft.Devices.DeviceType.Device)

    {

       emailAddressChooserTask.Show();

    }

    else

    {

        MessageBox.Show("Thistask doesn't work properly on the Window Phone emulator.\nPlease use a realdevice!");

    }

}

注意: 這段代碼不會啓動 EmailAddressChooserTask 如果應用程序沒有運行在設備上,這是因爲前面我們提到的模擬器的限制.

62.            按 F5 編譯並運行應用程序.

63.            導航到 “Use Contact’s Email Address” 頁面並單擊 Send Email:

圖 52

發送電子郵件

64.            選擇聯繫人.

圖 53

選擇一個聯繫人

65.            如果一個聯繫人有多個電子郵件地址,會有額外的選擇步驟,這裏我們選擇其中一個郵件地址.

66.            編寫電子郵件(或者保持前面的文本)並單擊 Send.

67.            返回到應用程序單擊Back ().

68.            按 SHIFT+F5 停止調試並返回到編輯模式.

69.            在 Views 文件夾添加另外一個頁面命名爲ChoosePhotoPage.

注意: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

70.            找到PhoneApplicationPage 元素.

71.            修改SupportedOrientations 屬性的值爲PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ChoosePhotoPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

72.            爲了簡化設計過程,使用以下的代碼替換整個LayoutRoot:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinitionHeight="Auto"/>

        <RowDefinitionHeight="*"/>

   </Grid.RowDefinitions>

 

   <!--TitlePanel contains the name of the application andpage title-->

   <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="12,17,0,28">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResourceAppName}" Style="{StaticResourcePhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle"Text="Photos" Margin="9,-7,0,0"Style="{StaticResourcePhoneTextTitle1Style}"/>

   </StackPanel>

 

   <!--ContentPanel - place additional content here-->

   <Grid x:Name="ContentPanel"Grid.Row="1">

        <GridGrid.Row="0">

            <Grid.RowDefinitions>

                <RowDefinitionHeight="Auto" />

                <RowDefinitionHeight="*" />

            </Grid.RowDefinitions>

            <Button x:Name="btnChoosePhoto"Content="Choose a Photo" Grid.Row="0"Click="btnChoosePhoto_Click"/>

            <Image x:Name="imgChosenPhoto"Grid.Row="1" />

        </Grid>

   </Grid>

</Grid>

73.            打開 ChoosePhotoPage.xaml.cs.

74.            添加 button click事件到 ChoosePhotoPage.xaml.cs 類.

C#

private void btnChoosePhoto_Click(object sender, RoutedEventArgse)

{

 

}

75.            打開 MainPage.xaml.cs 並找到以下注釋部分:

C#

private void btnChoosePhoto_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to choose photo page

}

76.            使用以下代碼替換整個註釋部分:

C#

private void btnChoosePhoto_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/ChoosePhotoPage.xaml", UriKind.Relative));

}

77.            打開 ChoosePhotoPage.xaml.cs.

78.            添加以下的引用聲明:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

using System.Windows.Media.Imaging;

79.            重寫OnNavigatedFrom 和 OnNavigatedTo 方法在墓碑化的時候輸出調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of ChoosePhotoPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of ChoosePhotoPage\t ***");

 

    base.OnNavigatedTo(e);

}

在這個頁面我們將會從相冊中選擇一張照片.我們將會使用PhotoChooserTask 類. 它啓動照片選擇器在相冊中選擇一張照片. 這個 chooser 是異步的,因此你必須在啓動它之前訂閱完成事件 . 當chooser返回圖片文件流時,頁面將會顯示這張圖片.

80.            添加以下的變量:

C#

PhotoChooserTask photoChooserTask;

81.            在構造函數中添加以下代碼:

C#

public ChoosePhotoPage()

{

    InitializeComponent();

 

   Debug.WriteLine("***\t Inconstructor of ChoosePhotoPage\t ***");

   

    photoChooserTask= new PhotoChooserTask();

    photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);

}

82.            添加 photoChooserTask_Completed 事件來處理完成時的邏輯:

C#

void photoChooserTask_Completed(objectsender, PhotoResult e)

{

    Debug.WriteLine("***\t In photoChooserTask_Completedfunction of ChoosePhotoPage\t ***");

 

    if (e.TaskResult == TaskResult.OK)

    {

        BitmapImage bitmap = newBitmapImage();

       bitmap.SetSource(e.ChosenPhoto);

       imgChosenPhoto.Source = bitmap;

    }

    else if (e.TaskResult== TaskResult.Cancel)

        MessageBox.Show("Nophoto was chosen - operation was cancelled", "Photo not chosen", MessageBoxButton.OK);

    else

        MessageBox.Show("Errorwhile choosing photo:\n" + e.Error.Message, "Fail", MessageBoxButton.OK);

}

83.            添加 btnChoosePhoto_Click 事件:

C#

private void btnChoosePhoto_Click(object sender, RoutedEventArgse)

{

   photoChooserTask.Show();

}

84.            按 F5 編譯運行程序.

85.            導航到 “Choose a Photo” 頁然後點擊 Choose a Photo:

圖 54

選擇照片

86.            在Image Hub中單擊選取一個圖片.

Figure 55

從Image Hub中選取一個圖片

87.            選擇的圖片出現在ChoosePhotoPage.

Figure 56

Chosenphoto appears in the ChoosePhotoPage

88.            在Views文件夾填加另一個頁面 TakePicturePage.

Note: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

89.            定位到新創建頁的PhoneApplicationPage 元素.

90.            修改SupportedOrientations 屬性爲 PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.TakePicturePage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

91.            爲省略篇幅直接替換下面加亮的代碼到LayoutRoot 下Grid的內容:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinitionHeight="Auto"/>

        <RowDefinitionHeight="*"/>

   </Grid.RowDefinitions>

 

   <!--TitlePanel contains the name of the application andpage title-->

   <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="12,17,0,28">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResourceAppName}" Style="{StaticResourcePhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle"Text="Pictures" Margin="9,-7,0,0"Style="{StaticResourcePhoneTextTitle1Style}"/>

   </StackPanel>

 

   <!--ContentPanel - place additional content here-->

   <Grid x:Name="ContentPanel"Grid.Row="1">

        <GridGrid.Row="0">

            <Grid.RowDefinitions>

                <RowDefinitionHeight="Auto" />

                <RowDefinitionHeight="*" />

                <RowDefinitionHeight="Auto" />

            </Grid.RowDefinitions>

            <Button x:Name="btnTakePicture"Content="Capture New Picture" Grid.Row="0"Click="btnTakePicture_Click"/>

            <Image x:Name="imgTakenPicture"Grid.Row="1" />

            <StackPanelGrid.Row="2">

                <CheckBox x:Name="chkAddToImageHub"Content="Add to Image Hub" IsChecked="False"IsEnabled="False" />

                <Button x:Name="btnSavePicture"Content="Save Picture" IsEnabled="False"Click="btnSavePicture_Click" />

            </StackPanel>

        </Grid>

   </Grid>

</Grid>

92.            打開 TakePicturePage.xaml.cs.

93.            填加下面 picture button click事件處理函數到文件TakePicturePage.xaml.cs 的末尾.

(代碼  – Choosers and Launchers – Ex2 任務 1 步驟 93 – picture button clicksevent handler)

C#

private void btnTakePicture_Click(object sender, RoutedEventArgse)

{

 

}

 

private void btnSavePicture_Click(objectsender, RoutedEventArgs e)

{

 

}

94.            打開 MainPage.xaml.cs 定位到如下注釋:

C#

private void btnTakePicture_Click(object sender, RoutedEventArgse)

{

    //TODO - navigate to take picture page

}

95.            用下列代碼替換註釋:

C#

private void btnTakePicture_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(new Uri("/Views/TakePicturePage.xaml", UriKind.Relative));

}

96.            打開文件 TakePicturePage.xaml.cs.

97.            填加下面代碼:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

usingSystem.Windows.Media.Imaging;

usingSystem.IO.IsolatedStorage;

usingSystem.IO;

usingMicrosoft.Xna.Framework.Media;

98.            重寫 OnNavigatedFrom 和 OnNavigatedTo 方法,讓程序在墓碑狀態時記錄調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of TakePicturePage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of TakePicturePage\t ***");

 

    base.OnNavigatedTo(e);

}

在這頁中,一張新的圖片被拍下並且保存在電話中。拍照片用的是CameraCaptureTask類。這個類允許應用程序運行拍照程序並且用相機的攝像頭拍照。這個過程是異步的,所以需要註冊其完成事件。當它帶着圖片流返回的時候,頁面會將其保存到獨立存儲區。

99.            填加下面的代碼:

C#

CameraCaptureTask cameraCaptureTask;

 

100.  填加下面加亮部分的代碼到方法InitializeComponent 之後:

C#

public TakePicturePage()

{

    InitializeComponent();

 

   Debug.WriteLine("***\t Inconstructor of TakePicturePage\t ***");

   

    cameraCaptureTask= new CameraCaptureTask();

    cameraCaptureTask. Completed += new EventHandler<PhotoResult>(cameraCaptureTask_Completed);

}

 

101.  填加 cameraCaptureTask_Completed 事件處理方法來處理完成事件:

C#

void cameraCaptureTask_Completed(objectsender, PhotoResult e)

{

    Debug.WriteLine("***\t IncameraCaptureTask_Completed function of TakePicturePage\t ***");

 

    if (e.TaskResult == TaskResult.OK)

    {

        BitmapImage bitmap = newBitmapImage();

       bitmap.SetSource(e.ChosenPhoto);

       imgTakenPicture.Source = bitmap;

 

       chkAddToImageHub.IsEnabled = true;

       btnSavePicture.IsEnabled = true;

    }

    else if (e.TaskResult== TaskResult.Cancel)

        MessageBox.Show("Photowas not captured - operation was cancelled", "Photo not captured", MessageBoxButton.OK);

    else

        MessageBox.Show("Errorwhile capturing photo:\n" + e.Error.Message, "Fail", MessageBoxButton.OK);

}

102.  填加 btnTakePicture_Click 處理方法:

C#

private void btnTakePicture_Click(object sender, RoutedEventArgse)

{

   cameraCaptureTask.Show();

}

注意: 記住多媒體任務在設備連接到電腦的時候是不可用的.

103.  填加下面的代碼到btnSavePicture_Click 處理方法中:

C#

private void btnSavePicture_Click(object sender, RoutedEventArgse)

{

    BitmapImage bitmap = (BitmapImage)imgTakenPicture.Source;

 

    string photosStr = "Photo";

    using (IsolatedStorageFilestorage = IsolatedStorageFile.GetUserStoreForApplication())

    {

        const string fileName= "image.jpg";

        if (storage.FileExists(fileName))

        {

           storage.DeleteFile(fileName);

        }

 

        using (IsolatedStorageFileStreamimageFileStream = storage.CreateFile(fileName))

        {

            WriteableBitmap writableBitmap = new WriteableBitmap(bitmap);

           writableBitmap.SaveJpeg(imageFileStream, writableBitmap.PixelWidth,writableBitmap.PixelHeight, 0, 90);

        }

 

        if (chkAddToImageHub.IsChecked.Value)

        {

            using (IsolatedStorageFileStreamimageFileStream = storage.OpenFile(fileName, FileMode.Open,FileAccess.Read))

            {

                MediaLibrary library = newMediaLibrary();

               library.SavePicture(fileName, imageFileStream);

               photosStr += 's';

            }

        }

    }

 

    MessageBox.Show(photosStr + " saved successfully", "Success", MessageBoxButton.OK);

}

注意:這段代碼用的是固定的圖片文件名稱 – image.jpg. 建議將其存入Image Hub時給一個更合理的名稱.

104.   按 F5  編譯並且運行程序.

105.  導航到 “Take A Picture” 頁單擊 Capture New Picture:

Figure 57

初始化拍照任務

106.  在相機頁中,單擊:

注意: 當程序是在物理設備運行的時候,直接按設備的拍照鍵.

注意: TheWindows® Phone 模擬器的相機任務不會顯示任何圖像。模擬器的相機並沒有鏈接到計算機的攝像頭(假如有的話)。這樣你看到的是屏幕中一個在屏幕邊緣移動的黑色三角。

Figure 58

相機任務程序

107.  單擊 Accept, 或者Retake 來拍另外一張照片.

108.  拍的圖片不會顯示在TakePicturePage:

圖 59

圖片出現在 TakePicturePage

109.  照片保存到Image Hub,選中Add to Image Hub 複選框.

110.  單擊 Save Picture. 照片存儲到獨立存儲區域並且會根據你的選擇存儲到Image Hub.

111.  回到應用程序,單擊Back ().

112.  按 SHIFT+F5 停止調試並且回到Visual Studio.

113.        在文件夾 Views 中填加另外一個頁面 UseAddressPage.

注意:填加新項,右鍵單擊Views文件夾,選擇Add,NewItem..

114.        設置 SupportedOrientations 屬性爲 PortraitOrLandscape:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.UseAddressPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

   SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">

115.        爲省略篇幅直接替換下面加亮的代碼到LayoutRoot 下Grid的內容:

XAML

<!--LayoutRoot contains the root grid where allother page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

    <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanel contains the name of the application andpage title-->

    <StackPanel x:Name="TitlePanel"Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle"Text="{StaticResource
AppName}"Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Address"
Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel - place additional content here-->

    <Grid x:Name="ContentPanel"Grid.Row="1">

        <StackPanel Orientation="Vertical"Grid.Row="0">

            <TextBlock Text="Display name:"Style="{StaticResource
TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtDisplayName"IsEnabled="False"
Margin="0,0,0,10"/>

            <TextBlock Text="Address:" Style="{StaticResource
TextBlockTitleLargeStyle}"/>

            <TextBox x:Name="txtAddress"IsEnabled="False" Height="160" TextWrapping="Wrap"/>

            <Button x:Name="btnGetAddress"Content="Get Address"
Margin="0,5" Click="btnGetAddress_Click"/>

        </StackPanel>

    </Grid>

</Grid>

 

116.        打開文件 UseAddressPage.xaml.cs.

117.        填加下面的代碼到btnGetAddress_Click事件處理方法到文件UseAddressPage.xaml.cs 末尾.

C#

private void btnGetAddress_Click(objectsender, RoutedEventArgs e)

{

 

}

118.        打開 MainPage.xaml.cs 定位到下面註釋的部分:

C#

private void btnUseAddress_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the use address page

}

119.        用下面的代碼替換註釋:

C#

private void btnUseAddress_Click(object sender, RoutedEventArgse)

{

   NavigationService.Navigate(

        new Uri("/Views/UseAddressPage.xaml", UriKind.Relative));

}

120.        打開 UseAddressPage.xaml.cs 文件.

121.        填加下面的代碼:

C#

using Microsoft.Phone.Tasks;

using System.Diagnostics;

using System.Windows.Navigation;

122.        重寫 OnNavigatedFrom 和 OnNavigatedTo 方法,讓程序在墓碑狀態時記錄調試信息.

C#

protected override void OnNavigatedFrom(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedFrom function of UseAddressPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override void OnNavigatedTo(NavigationEventArgse)

{

    Debug.WriteLine("***\tIn OnNavigatedTo function of UseAddressPage\t ***");

 

    base.OnNavigatedTo(e);

}

本頁用戶可能會看到選擇的聯繫人。獲取聯繫人的信息,頁面用到了AddressChooserTask類。這個類允許用戶運行聯繫人程序來獲取用戶選中的聯繫人信息的地址信息。由於其是異步運行的,所以需要爲其註冊完成事件。當其返回地址信息的時候,其內容會顯示在頁面中。

 

123.        填加下面的代碼:

C#

AddressChooserTask addressChooserTask;

124.            把下面加亮的代碼填入到類的構造函數中的InitializeComponent方法後面:

C#

public UseAddressPage()

{

    InitializeComponent();

 

   Debug.WriteLine("***\t Inconstructor of UseEmailAddressPage\t ***");

   

    addressChooserTask = new AddressChooserTask();

    addressChooserTask.Completed += newEventHandler<AddressResult>(addressChooserTask_Completed);

}

125.        添加 addressChooserTask_Completed 事件處理代碼:

C#

void addressChooserTask_Completed(object sender, AddressResulte)

{

    string debugMsg = string.Format(

        "***\t In addressChooserTask_Completed function ofUseAddressPage, address returned: {0}, for contact: {1}\t ***",

    e.Address,e.DisplayName);

    Debug.WriteLine(debugMsg);

 

    if (e.TaskResult == TaskResult.OK)

    {

        txtDisplayName.Text= e.DisplayName;

       txtAddress.Text = e.Address;

    }

    else if (e.TaskResult== TaskResult.Cancel)

        MessageBox.Show("Cannotdisplay address information.", "Addressnot selected", MessageBoxButton.OK);

    else

        MessageBox.Show("Errorgetting address:\n" + e.Error.Message, "Fail",MessageBoxButton.OK);

}

126.        添加下面的代碼到btnGetAddress_Click 事件處理方法:

C#

private void btnGetAddress_Click(object sender, RoutedEventArgse)

{

    addressChooserTask.Show();

}

127.        按 F5編譯和運行程序.

128.        單擊Get Address按鈕打開 “Use Contact’sAddress” 頁:

Figure 60

獲取聯繫人地址

129.        選擇一個聯繫人.

Figure 61

選擇一個聯繫人

130.        如果一個聯繫人有多個地址信息,這裏會再彈出一個頁面讓用戶指定選擇哪一個地址信息。

131.        選擇的地址信息會出現在頁面上.

132.        返回到程序,單擊Back ().

133.        按 SHIFT+F5 終止調試並且返回到 Visual Studio.

 

任務 2 –查詢聯繫人和約會

新版本的Windows® Phone 7.1 允許用戶通過Appointments  Contacts類搜索約會和聯繫人信息,這兩個類位於Microsoft.Phone.UserData下。下面的練習會添加頁面來演示這兩個功能。

注意: 這部分內容用到的控件是Windows Phone Toolkit. 實驗代碼已經包含這些控件,但是也可以在這裏獲得: http://silverlight.codeplex.com/

1.               在文件夾 Views 下添加另外一個頁面 SearchAppointmentsPage.

注意: 新建頁面的方法,右鍵Views文件夾,選擇Add,NewItem。.

2.      定位到新創建頁面的PhoneApplicationPage元素.

3.      修改SupportedOrientations屬性爲 PortraitOrLandscape, 填加toolkit 命名空間以及頁面的DataContext:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.SearchAppointmentsPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True"

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

4.      爲省略篇幅,直接添加下面加亮的代碼到頁面LayoutRoot的Grid下面::

XAML

<!--LayoutRootcontains the root grid where all other page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Text="{StaticResource AppName}" Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Appointments"
Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <Grid Margin="0" VerticalAlignment="Top">

            <Grid.RowDefinitions>

                <RowDefinition/>

                <RowDefinition Height="Auto"/>

            </Grid.RowDefinitions>

            <ListBox x:Name="listResults" ItemsSource="{Binding SearchResults}" VerticalAlignment="Top" Visibility="{Binding ResultsVisibility}" Margin="12,0">

            <ListBox.Resources>

                <conv:TimeSpanToDateTimeConverter
x:Key="TimeSpanToDateTimeConverter"/>

            </ListBox.Resources>

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <StackPanel Margin="12,0">

                        <Path Data="M15.5,159.5 L436.57007,159.5" Height="2" Stretch="Fill" Stroke="{StaticResource PhoneAccentBrush}" UseLayoutRounding="False" Margin="12,0"/>

                        <TextBlock Text="Start Time:"
Style="{StaticResource TextBlockTitleMediumStyle}" Margin="12,0"/>

                        <Grid  DataContext="{Binding StartTime}" Margin="0,-10,0,-10">

                            <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="Auto"/>

                                <ColumnDefinition Width="Auto"/>

                            </Grid.ColumnDefinitions>

                            <toolkit:DatePicker Value="{Binding Date}" IsEnabled="False"/>

                            <toolkit:TimePicker Value="{Binding TimeOfDay, Converter={StaticResource TimeSpanToDateTimeConverter}}" IsEnabled="False"  Grid.Column="1"/>

                        </Grid>

                        <TextBlock Text="End time:"
Style="{StaticResource TextBlockTitleMediumStyle}" Margin="12,0"/>

                        <Grid  DataContext="{Binding EndTime}" Margin="0,-10,0,-10" >

                            <Grid.ColumnDefinitions>

                        <ColumnDefinition Width="Auto"/>

                        <ColumnDefinition Width="Auto"/>

                    </Grid.ColumnDefinitions>

 

                    <toolkit:DatePicker Value="{Binding Date}" IsEnabled="False" />

                    <toolkit:TimePicker Value="{Binding TimeOfDay, Converter={StaticResourceTimeSpanToDateTimeConverter}}" IsEnabled="False" Grid.Column="1"/>

                </Grid>

                <Path Data="M15.5,159.5L436.57007,159.5" Height="1" Stretch="Fill" Stroke="#99FFFFFF"UseLayoutRounding="False" Margin="12,0"/>

                <TextBlock Text="Subject:"
Style="{StaticResource TextBlockTitleMediumStyle}" Margin="12,5,12,0"/>

                <TextBlock Text="{Binding Subject}"
Style="{StaticResource TextBlockLargeStyle}" Margin="12,0,12,10"/>

                <TextBlock Text="Organizer:"
Style="{StaticResource TextBlockTitleMediumStyle}"/>

                <StackPanel DataContext="{Binding
Path=Organizer}" Margin="12,0,12,10">

                <TextBlock Text="{Binding
Path=DisplayName}" Style="{StaticResource TextBlockLargeStyle}"/>

                <TextBlock Text="{Binding
Path=EmailAddress}" Style="{StaticResource TextBlockLargeStyle}"/>

            </StackPanel>

            <TextBlock Text="Location:"
Style="{StaticResource TextBlockTitleMediumStyle}"/>

            <TextBlock Text="{Binding Path=Location}" Margin="12,0,12,10" Style="{StaticResource TextBlockLargeStyle}"/>

            <TextBlock Text="Attendees:"
Style="{StaticResource TextBlockTitleMediumStyle}"/>

            <ListBox ItemsSource="{Binding
Path=Attendees}" Margin="12,0,12,10">

                <ListBox.ItemTemplate>

                    <DataTemplate>

                        <StackPanel Margin="6, 0, 0, 0">

                            <TextBlock Text="{Binding Path=DisplayName}" Style="{StaticResourceTextBlockLargeStyle}"/>

                                <TextBlock Text="{Binding Path=EmailAddress}" Style="{StaticResourceTextBlockLargeStyle}"/>

                        </StackPanel>

                    </DataTemplate>

                </ListBox.ItemTemplate>

            </ListBox>

            <TextBlock Text="Details:"
Style="{StaticResource TextBlockTitleMediumStyle}" Margin="12,10,12,0"/>

                <TextBlock Text="{Binding Path=Details}" Style="{StaticResource TextBlockLargeStyle}" Margin="12,0,12,10"/>

                    <Path Data="M15.5,159.5L436.57007,159.5" Height="2" Stretch="Fill" Stroke="{StaticResourcePhoneAccentBrush}" UseLayoutRounding="False" Margin="12,0"/>

                </StackPanel>

            </DataTemplate>

        </ListBox.ItemTemplate>

    </ListBox>

    <Button x:Name="btnNewSearch" Content="NewSearch"
Click="btnNewSearch_Click" Visibility="{Binding ResultsVisibility}" d:LayoutOverrides="Height" Grid.Row="1"/>

    </Grid>

    <StackPanel Orientation="Vertical" Grid.Row="0" d:IsHidden="True">

        <TextBlock Text="Start time:" Visibility="{Binding SearchVisibility}" Style="{StaticResource TextBlockTitleMediumStyle}"/>

        <Grid Visibility="{Binding SearchVisibility}">

                <Grid.ColumnDefinitions>

                    <ColumnDefinition Width="Auto"/>

                    <ColumnDefinition Width="Auto"/>

                </Grid.ColumnDefinitions>

                <toolkit:DatePicker x:Name="dateStart"/>

                <toolkit:TimePicker x:Name="timeStart" Grid.Column="1"/>

            </Grid>

            <TextBlock Text="End time:" Visibility="{Binding SearchVisibility}" Style="{StaticResource TextBlockTitleMediumStyle}"/>

            <Grid Visibility="{Binding SearchVisibility}">

                <Grid.ColumnDefinitions>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition Width="Auto"/>

            </Grid.ColumnDefinitions>

            <toolkit:DatePicker x:Name="dateEnd"  />

            <toolkit:TimePicker x:Name="timeEnd"  Grid.Column="1"/>

 

        </Grid>

        <Button x:Name="btnSearchAppointments"
Content="Search Appointments" Margin="0"
Click="btnSearchAppointments_Click" Visibility="{Binding SearchVisibility}"/>

        </StackPanel>

    </Grid>

</Grid>

5.               打開 MainPage.xaml.cs 定位到下面註釋的部分:

C#

private void btnSearchAppointments_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the search appointments page

}

6.               用下面的代碼替換註釋:

C#

private void btnSearchAppointments_Click(object sender, RoutedEventArgse)

{

    NavigationService.Navigate(

        new Uri("/Views/SearchAppointmentsPage.xaml",UriKind.Relative));

}

7.               打開文件 SearchAppointmentsPage.xaml.cs.

8.               添加下面的代碼:

C#

usingMicrosoft.Phone.UserData;

usingSystem.Collections.ObjectModel;

usingSystem.Windows.Navigation;

using System.Diagnostics;

9.               在類中添加下面的字段和屬性:

C#

public ObservableCollection<Appointment>SearchResults { get;
private set; }

 

Appointments appointments;

 

public Visibility SearchVisibility

{

    get { return (Visibility)GetValue(SearchVisibilityProperty);}

    set {SetValue(SearchVisibilityProperty, value); }

}

 

public static readonly DependencyProperty SearchVisibilityProperty =

    DependencyProperty.Register("SearchVisibility", typeof(Visibility),typeof(SearchAppointmentsPage),null);

 

public Visibility ResultsVisibility

{

    get { return (Visibility)GetValue(ResultsVisibilityProperty);}

    set {SetValue(ResultsVisibilityProperty, value); }

}

 

public static readonly DependencyProperty ResultsVisibilityProperty =

    DependencyProperty.Register("ResultsVisibility", typeof(Visibility),typeof(SearchAppointmentsPage),null);

10.  重寫 OnNavigatedFrom 和 OnNavigatedTo 方法,讓程序在墓碑狀態時記錄調試信息.

C#

protected override voidOnNavigatedFrom(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedFrom function ofSearchAppointmentsPage\t ***");

 

    if(e.NavigationMode == NavigationMode.Back)

    {

        if(State.ContainsKey("StartTime"))

        {

            State.Remove("StartTime");

        }

 

        if(State.ContainsKey("EndTime"))

        {

            State.Remove("EndTime");

        }

 

        if(State.ContainsKey("ResultsVisible"))

        {

            State.Remove("ResultsVisible");

        }

    }

    else

    {

        State["StartTime"]=
dateStart.Value.Value.Add(timeStart.Value.Value.TimeOfDay);

        State["EndTime"]=
dateEnd.Value.Value.Add(timeEnd.Value.Value.TimeOfDay);

        State["ResultsVisible"]= ResultsVisibility;

    }

 

    base.OnNavigatedFrom(e);

}

 

protected override voidOnNavigatedTo(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedTo function ofSearchAppointmentsPage\t ***");

 

    if(State.Count > 0)

    {

    if(e.Uri.OriginalString.EndsWith("DatePickerPage.xaml"))

    {

        timeStart.Value =
                new DateTime().Add(

                 ((DateTime)State["StartTime"]).TimeOfDay);

                timeEnd.Value =

                newDateTime().Add(

                 ((DateTime)State["EndTime"]).TimeOfDay);

    }

 

        if(e.Uri.OriginalString.EndsWith("TimePickerPage.xaml"))

        {

            dateStart.Value =

                 ((DateTime)State["StartTime"]).Date;

                dateEnd.Value =

                 ((DateTime)State["EndTime"]).Date;

        }

 

        ResultsVisibility = (Visibility)State["ResultsVisible"];

        SearchVisibility = ResultsVisibility ==Visibility.Visible ?
            Visibility.Collapsed: Visibility.Visible;

 

        // Refreshthe search

        if(ResultsVisibility == Visibility.Visible)

        {

           btnSearchAppointments_Click(this, null);

        }

    }

 

    base.OnNavigatedTo(e);

}

在本頁中用戶利用Appointments chooser通過兩個時間點來查找約會。由於其是異步執行的所以需要爲其註冊完成事件。當它返回相應的約會信息時,會顯示在頁面上。

11.  把下面加亮的代碼填入到類的構造函數中的InitializeComponent方法後面:

C#

public UseAddressPage()

{

    InitializeComponent();

 

    Debug.WriteLine("***\tIn constructor of SearchAppointments\t ***");

 

    SearchResults = new ObservableCollection<Appointment>();

 

    ResultsVisibility= Visibility.Collapsed;

    SearchVisibility= Visibility.Visible;

 

    appointments = new Appointments();

    appointments.SearchCompleted+= new

EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);

}

12.            添加 appointments_SearchCompleted 事件處理代碼,以及一個方法來處理完成事件:

C#

voidappointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)

{

    Dispatcher.BeginInvoke(() =>UpdateResults(e.Results));

}

 

private void UpdateResults(IEnumerable<Appointment> result)

{

    SearchResults.Clear();

 

    foreach (Appointment appointment inresult)

    {

        SearchResults.Add(appointment);

    }

 

    ResultsVisibility = Visibility.Visible;

    SearchVisibility = Visibility.Collapsed;

}

13.            添加下面的代碼響應界面上按鈕的單擊事件:

C#

private void btnSearchAppointments_Click(object sender, RoutedEventArgse)

{

    if(!dateStart.Value.HasValue || !timeStart.Value.HasValue)

    {

        MessageBox.Show("Please supply a start time.");

        return;

    }

 

    if(!dateEnd.Value.HasValue || !timeEnd.Value.HasValue)

    {

        MessageBox.Show("Please supply an end time.");

        return;

    }

 

   appointments.SearchAsync(dateStart.Value.Value.Add(timeStart.Value.Value.TimeOfDay),

       dateEnd.Value.Value.Add(timeEnd.Value.Value.TimeOfDay), null);

}

 

private void btnNewSearch_Click(objectsender, RoutedEventArgs e)

{

    SearchVisibility = Visibility.Visible;

    ResultsVisibility = Visibility.Collapsed;

}

14.            按 F5 編譯並運行程序.

15.            導航到 “Search Appointments”頁面填寫起始事件和結束事件,然後按 “SearchAppointments” 按鈕:

Figure 62

查找約會信息

Figure 63

查找到的約會信息

16.            相關的聯繫人信息顯示在了頁面上.

17.            返回程序,按Back ().

18.            按 SHIFT+F5終止調試並且返回到 the Visual Studio.

19.            在文件夾 Views 下創建新頁面 FindNextAppointmentPage.

注意: 新建頁面的方法,右鍵Views文件夾,選擇Add,NewItem。

20.  定位到新創建頁面的PhoneApplicationPage元素.

21.  修改SupportedOrientations屬性爲 PortraitOrLandscape, 填加toolkit 命名空間以及頁面的DataContext:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.FindNextAppointmentPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True"

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

22.  爲省略篇幅,直接添加下面加亮的代碼到頁面LayoutRoot的Grid下面:

XAML

<!--LayoutRootcontains the root grid where all other page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

    <TextBlock x:Name="ApplicationTitle" Text="{StaticResource
AppName}"Style="{StaticResource PhoneTextNormalStyle}"/>

    <TextBlock x:Name="PageTitle" Text="Appointments"
Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <ScrollViewer>

        <StackPanel Orientation="Vertical" Grid.Row="0"
DataContext="{Binding Path=FirstAppointment}">

            <StackPanel.Resources>

                <conv:TimeSpanToDateTimeConverter
x:Key="TimeSpanToDateTimeConverter"/>

            </StackPanel.Resources>

            <Button x:Name="btnFindNext"
Content="Find Next Appointment" Margin="0,5" Click="btnFindNext_Click"/>

            <TextBlock Text="Start Time:"
Style="{StaticResource TextBlockTitleMediumStyle}" Margin="12,0"/>

            <Grid  DataContext="{Binding StartTime}"
Margin="0,-10,0,-10">

                <Grid.ColumnDefinitions>

                    <ColumnDefinition Width="Auto"/>

                    <ColumnDefinition Width="Auto"/>

                </Grid.ColumnDefinitions>

                <toolkit:DatePicker Value="{Binding Date}"
IsEnabled="False" />

                <toolkit:TimePicker Value="{Binding TimeOfDay,
Converter={StaticResource TimeSpanToDateTimeConverter}}"
IsEnabled="False" Grid.Column="1"/>

            </Grid>

            <TextBlock Text="End time:" Style="{StaticResource
TextBlockTitleMediumStyle}" Margin="12,0"/>

            <Grid DataContext="{Binding EndTime}"
Margin="0,-10,0,-10" >

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="Auto"/>

                    <ColumnDefinition Width="Auto"/>

                </Grid.ColumnDefinitions>

                <toolkit:DatePicker Value="{Binding Date}"
IsEnabled="False"/>

                <toolkit:TimePicker Value="{Binding TimeOfDay,
Converter={StaticResource TimeSpanToDateTimeConverter}}"
IsEnabled="False"  Grid.Column="1"/>

            </Grid>

            <Path Data="M15.5,159.5L436.57007,159.5" Height="1"
Stretch="Fill" Stroke="#99FFFFFF" UseLayoutRounding="False"
Margin="12,0"/>

            <TextBlock Text="Subject:" Style="{StaticResource
TextBlockTitleMediumStyle}" Margin="12,5,12,0"/>

            <TextBlock Text="{Binding Path=Subject}"
Style="{StaticResource TextBlockLargeStyle}" Margin="12,0,12,10"/>

            <TextBlock Text="Organizer:" Style="{StaticResource
TextBlockTitleMediumStyle}"/>

            <StackPanel DataContext="{Binding Path=Organizer}"
Margin="12,0,12,10">

            <TextBlock Text="{Binding Path=DisplayName}"
Style="{StaticResource TextBlockLargeStyle}"/>

            <TextBlock Text="{Binding Path=EmailAddress}"
Style="{StaticResource TextBlockLargeStyle}"/>

        </StackPanel>

        <TextBlock Text="Location:" Style="{StaticResource
TextBlockTitleMediumStyle}"/>

            <TextBlock Text="{Binding Path=Location}"
Margin="12,0,12,10" Style="{StaticResource TextBlockLargeStyle}"/>

            <TextBlock Text="Attendees:" Style="{StaticResource
TextBlockTitleMediumStyle}"/>

                <ListBox ItemsSource="{Binding Path=Attendees}"
Margin="12,0,12,10">

                    <ListBox.ItemTemplate>

                        <DataTemplate>

                            <StackPanel Margin="6, 0, 0, 0">

                                <TextBlock Text="{Binding
Path=DisplayName}" Style="{StaticResource TextBlockLargeStyle}"/>

                                <TextBlock Text="{Binding
Path=EmailAddress}" Style="{StaticResource TextBlockLargeStyle}"/>

                        </StackPanel>

                    </DataTemplate>

                </ListBox.ItemTemplate>

            </ListBox>

            <TextBlock Text="Details:" Style="{StaticResource
TextBlockTitleMediumStyle}" Margin="12,10,12,0"/>

            <TextBlock Text="{Binding Path=Details}"
Style="{StaticResource TextBlockLargeStyle}" Margin="12,0,12,10"/>

            </StackPanel>

        </ScrollViewer>

    </Grid>

</Grid>

23.            打開文件 MainPage.xaml.cs 並且定位到註釋部分:

C#

private void btnFindNextMeeting_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the search appointments page

}

24.            用下面的代碼替換註釋代碼:

C#

private void btnFindNextMeeting_Click(object sender, RoutedEventArgse)

{

    NavigationService.Navigate(

        new Uri("/Views/FindNextAppointmentPage.xaml",UriKind.Relative));

}

25.            打開文件 FindNextAppointmentPage.xaml.cs.

26.            添加下面的代碼:

C#

usingMicrosoft.Phone.UserData;

usingSystem.Windows.Navigation;

using System.Diagnostics;

27.            在類裏添加下面的字段和屬性:

C#

Appointments appointments;

 

public Appointment FirstAppointment

{

    get { return (Appointment)GetValue(FirstAppointmentProperty);}

    set {SetValue(FirstAppointmentProperty, value); }

}

 

public static readonly DependencyProperty FirstAppointmentProperty =

    DependencyProperty.Register("FirstAppointment", typeof(Appointment),typeof(FindNextAppointmentPage),null);

28.  重寫 OnNavigatedFrom 和 OnNavigatedTo 方法,讓程序在墓碑狀態時記錄調試信息.

C#

protected override voidOnNavigatedFrom(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedFrom function ofFindFirstAppointmentPage\t ***");

 

    base.OnNavigatedFrom(e);

}

 

protected override voidOnNavigatedTo(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedTo function ofFindFirstAppointmentPage\t ***");

 

    base.OnNavigatedFrom(e);

 

    if(!e.IsNavigationInitiator)

    {

        btnFindNext_Click(this, null);

    }

}

本頁中通過Appointments Chooser查找到最近的約會信息。由於其是異步執行的所以需要爲其註冊完成事件。當它返回相應的約會信息時,會顯示在頁面上。

29.  把下面加亮的代碼填入到類的構造函數中的InitializeComponent方法後面:

C#

public UseAddressPage()

{

    InitializeComponent();

 

    Debug.WriteLine("***\tIn constructor of FindNextAppointmentPage\t ***");

 

    appointments = new Appointments();

    appointments.SearchCompleted += new
EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);

}

30.            添加appointments_SearchCompleted 事件處理代碼,以及另外一個方法來處理完成事件:

C#

private void appointments_SearchCompleted(object sender,
AppointmentsSearchEventArgs e)

{

    Dispatcher.BeginInvoke(() =>
UpdateResults(e.Results.FirstOrDefault()));

}

 

private void UpdateResults(Appointmentresult)

{

    if (result== null)

    {

        MessageBox.Show("There are no appointments.");

        return;

    }

 

    FirstAppointment = result;

}

31.            添加下面的代碼響應頁面上的按鈕事件:

C#

private void btnFindNext_Click(objectsender, RoutedEventArgs e)

{

    appointments.SearchAsync(DateTime.Now, DateTime.MaxValue,1, null);

}

32.            按 F5 編譯和運行程序.

33.            導航到 “Find Next Appointments” 頁,按下 “Find Next Appointment” 按鈕:

Figure 64

顯示下一條約會信息

34.            相關的約會信息顯示在了頁面上.

35.            返回程序,按Back ().

36.            按 SHIFT+F5終止調試並且返回到 Visual Studio.

37.            在文件夾 Views下填加子文件夾Resources.

注意: 新建文件夾的方法,右鍵Views文件夾,選擇Add,NewFolder。.

38.            添加文件 ContactListDictionary.xaml, 可以在 Source\Assets 文件夾下找到上節創建的文件夾,文件定義了用戶接口模版,這個是用來接下來我們用於顯示存儲在設備上的聯繫人信息的。

39.            在文件夾 Views下新建一個頁面ShowContactsPage.

注意:新建頁面的方法,右鍵Views文件夾,選擇Add,NewItem。定位到新創建頁面的 the PhoneApplicationPage元素.

40.            修改SupportedOrientations 屬性爲 PortraitOrLandscape, 添加toolkit 命名空間以及頁面的DataContext。:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ShowContactsPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True"

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

41.            立即在PhoneApplicationPage元素後面,添加下面這段在第38步使用到的Xaml資源片段:

XAML

<phone:PhoneApplicationPage.Resources>

    <ResourceDictionary>

        <ResourceDictionary.MergedDictionaries>

            <ResourceDictionary
                Source="Resources/ContactListDictionary.xaml"/>

        </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

</phone:PhoneApplicationPage.Resources>

42.            爲省略篇幅,直接添加下面加亮的代碼到頁面LayoutRoot的Grid下面:

XAML

<!--LayoutRootcontains the root grid where all other page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <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="Contacts"
Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

        <Grid.Resources>

            <conv:VisibilityInvertConvertor
x:Key="VisibilityInvertConvertor"/>

        </Grid.Resources>

        <StackPanel VerticalAlignment="Center" Visibility="{Binding
Path=ContactsListVisibility, Converter={StaticResource
VisibilityInvertConvertor}}">

            <TextBlock Text="Loading Contacts..."
HorizontalAlignment="Center" Style="{StaticResource
TextBlockMediumStyle}"/>

                <ProgressBar IsIndeterminate="True"/>

        </StackPanel>

        <toolkit:LongListSelector ItemsSource="{Binding
Path=ContactsCollection}" ItemTemplate="{StaticResource
ContactItemTemplate}" Visibility="{Binding Path=ContactsListVisibility}" GroupHeaderTemplate="{StaticResource ContactsGroupHeaderTemplate}"
GroupItemTemplate="{StaticResource ContactsGroupItemTemplate}"
GroupItemsPanel="{StaticResource ContactGroupViewTemplate}"/>         

    </Grid>

</Grid>

43.            在 PhoneApplicationPage元素結尾之前,你應該會看到兩段註釋,其中第一段以“Sample code showing usage of ApplicationBar”開頭. 用下面的代碼替換掉Xaml註釋:

XAML

<phone:PhoneApplicationPage.ApplicationBar>

    <shell:ApplicationBar IsVisible="True"IsMenuEnabled="True">

        <shell:ApplicationBarIconButton IconUri="Images/Search.png"
Text="Search" Click="ApplicationBarSearchButton_Click"/>           

    </shell:ApplicationBar>

</phone:PhoneApplicationPage.ApplicationBar>

44.            打開 MainPage.xaml.cs 定位到下面註釋的部分:

C#

private void btnSearchContacts_Click(object sender, RoutedEventArgse)

{

    //TODO - navigateto the search contacts page

}

45.            用下面的代碼替換註釋:

C#

private void btnSearchContacts_Click(object sender, RoutedEventArgse)

{

    NavigationService.Navigate(

        new Uri("/Views/ShowContactsPage.xaml",UriKind.Relative));

}

46.            打開文件 ShowContactsPage.xaml.cs.

47.            添加下面的代碼:

C#

usingSystem.Collections.ObjectModel;

usingSystem.Windows.Navigation;

usingMicrosoft.Phone.UserData;

using System.Collections;

using System.Diagnostics;

48.            爲類添加下面的字段和屬性:

C#

private Contacts contacts;

 

public ObservableCollection<ContactsGroup>ContactsCollection

{

    get { return (ObservableCollection<ContactsGroup>)GetValue(
ContactsCollectionProperty); }

    set {SetValue(ContactsCollectionProperty, value); }

}

       

public static readonly DependencyProperty ContactsCollectionProperty =

    DependencyProperty.Register("ContactsCollection", typeof(ObservableCollection<ContactsGroup>), typeof(ShowContactsPage), null);       

 

public Visibility ContactsListVisibility

{

    get { return (Visibility)GetValue(ContactsListVisibilityProperty);}

    set {SetValue(ContactsListVisibilityProperty, value);}

}

 

public static readonly DependencyProperty ContactsListVisibilityProperty= DependencyProperty.Register("ShowContactsList", typeof(Visibility),typeof(ShowContactsPage),null);

49.  重寫 OnNavigatedFrom 和 OnNavigatedTo 方法,讓程序在墓碑狀態時記錄調試信息.

C#

protected override voidOnNavigatedFrom(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedFrom function ofShowContactsPage\t ***");

 

    base.OnNavigatedFrom(e);

 

    // Hide thecontacts list if we go back to the main page

    if(e.IsNavigationInitiator && e.NavigationMode ==
        NavigationMode.Back)               

    {

        ContactsListVisibility = Visibility.Collapsed;

        ((App)App.Current).ShowContactsPage = null;

    }           

}

 

protected override voidOnNavigatedTo(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedTo function ofShowContactsPage\t ***");

 

    base.OnNavigatedTo(e);

 

    ((App)App.Current).ShowContactsPage = this;

 

    // Refresh thecontact list unless it is already visible (we make

    // sure it is not visible if it needs a

    // refresh)

    if(ContactsListVisibility == Visibility.Collapsed)

    {

        contacts.SearchAsync(String.Empty, FilterKind.None,null);

    }

}

在本頁中會顯示用戶在聯繫人界面中選取的聯繫人信息。由於其是異步的所以需要爲其註冊完成事件。當它返回聯繫人信息的時候,會顯示在程序的頁面上。

50.  把下面加亮的代碼填入到類的構造函數中的InitializeComponent方法後面:

C#

public ShowContactsPage()

{

    InitializeComponent();

 

    Debug.WriteLine("***\tIn constructor of ShowContactsPage\t ***");

 

    ContactsListVisibility = Visibility.Collapsed;

 

    ContactsCollection = new ObservableCollection<ContactsGroup>();

 

    contacts = new Contacts();

    contacts.SearchCompleted +=contacts_SearchCompleted;

}

ContactsGroup 用來在聯繫人顯示之前對其進行分組,我們將會在後面創建它。

51.            用下面的代碼添加contacts_SearchCompleted事件處理方法:

C#

voidcontacts_SearchCompleted(object sender, ContactsSearchEventArgs e)

{

    // Group allcontacts according to the first letter in their display

    // name

    varitemsSource = e.Results.GroupBy(c => c.DisplayName.First()).
        OrderBy(group =>group.Key).Select(group => new ContactsGroup(
        group));

 

    Dispatcher.BeginInvoke(() =>

        {

            ContactsListVisibility = Visibility.Visible;

 

            ContactsCollection =
                newObservableCollection<ContactsGroup>(itemsSource);

        });

}

52.            添加下面的代碼來處理應用程序欄按鈕按下的事件,它會將我們引導到另外一個搜索頁面:

C#

private void ApplicationBarSearchButton_Click(object sender,

EventArgs e)

{

    NavigationService.Navigate(new Uri("/Views/SearchContactsPage.xaml",
        UriKind.Relative));

}

53.            在文件裏添加另外一個類. 這個類就是我們前面提到過的 ContactsGroup:

C#

public class ContactsGroup : IEnumerable<Contact>

{

    private IEnumerable<Contact> items;

 

    public string Title { get; set; }

 

    /// <summary>

    /// Creates a new groupof contracts. The group's title will be the

    /// first letter in thefirst contact's display name.

    /// </summary>

    /// <paramname="items">The contacts to include in the group.

    /// </param>

    public ContactsGroup(IEnumerable<Contact> items)

    {

        this.items= items;

        Title = char.ToLower(items.First().DisplayName.First()).

            ToString();

    }

 

    #regionIEnumerable<Contact> Members

 

    public IEnumerator<Contact>GetEnumerator()

    {

        returnitems.GetEnumerator();

    }

 

    #endregion

 

    #regionIEnumerable Members

 

    IEnumerator IEnumerable.GetEnumerator()

    {

        returnitems.GetEnumerator();

    }

 

    #endregion

}

54.            按 F5編譯運行程序.

55.            導航到“Search Contacts” 頁,可以看到設備的聯繫人信息:

Figure 65

顯示設備的聯繫人信息

按應用程序欄的按鈕會導致程序崩潰,因爲轉向的頁面我們還沒有完成,我們會在下面完成相關的頁面。

56.            返回到程序,單擊Back ().

57.            按 SHIFT+F5 終止調試並且返回到Visual Studio.

58.            在文件夾 Views 下添加另外一個頁面 SearchContactsPage.

注意: 爲了添加一個新頁面, 右鍵 點擊Views 文件夾, 從下拉菜單中選擇 Add 然後從下拉菜單中選擇New Item.

59.            在新創建頁中定位到 PhoneApplicationPage 元素.

60.            設置 SupportedOrientations 屬性爲 PortraitOrLandscape, 填加 toolkit 命名控件並且添加頁面的data context,如下所示:

XAML

<phone:PhoneApplicationPage

    x:Class="LaunchersAndChoosers.Views.ShowContactsPage"

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

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

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="PortraitOrLandscape"

    Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True"

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

61.            在PhoneApplicationPag元素之後, 添加下面這段在38中使用到的Xaml資源片段:

XAML

<phone:PhoneApplicationPage.Resources>

    <ResourceDictionary>

        <ResourceDictionary.MergedDictionaries>

            <ResourceDictionary
                Source="Resources/ContactListDictionary.xaml"/>

        </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

</phone:PhoneApplicationPage.Resources>

62.            便於精簡,使用下面加亮的代碼完全替換LayoutRoot主Grid裏的內容:

XAML

<!--LayoutRootcontains the root grid where all other page content is placed-->

<Grid x:Name="LayoutRoot" Background="Transparent">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

 

    <!--TitlePanelcontains the name of the application and page title-->

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">

        <TextBlock x:Name="ApplicationTitle" Margin="-3,-8,0,0" Text="CONTACTS" Style="{StaticResource PhoneTextNormalStyle}"/>

        <TextBlock x:Name="PageTitle" Text="Search" Margin="-3,-8,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

    </StackPanel>

 

    <!--ContentPanel- place additional content here-->

    <Grid x:Name="ContentPanel" Grid.Row="1">

        <Grid>

            <Grid.RowDefinitions>

                <RowDefinition Height="Auto"/>

                <RowDefinition Height="*"/>

             </Grid.RowDefinitions>

             <StackPanel Orientation="Vertical" Grid.Row="0"

Margin="0,2,0,-2">

                <Grid>

                    <Grid.ColumnDefinitions>

                        <ColumnDefinition Width="Auto"/>

                        <ColumnDefinition Width="*"/>

                    </Grid.ColumnDefinitions>

                    <TextBlock Text="Search by:" Grid.Column="0"

Style="{StaticResource TextBlockTitleMediumStyle}"/>

                    <toolkit:ListPicker x:Name="listFilterType"

Grid.Column="1">

                    <toolkit:ListPickerItem>DisplayName

</toolkit:ListPickerItem>

                    <toolkit:ListPickerItem>Email

</toolkit:ListPickerItem>

                    <toolkit:ListPickerItem>PhoneNumber

</toolkit:ListPickerItem>

                    </toolkit:ListPicker>

                </Grid>

                <TextBox x:Name="txtSearchTerm"/>

            </StackPanel>

 

            <toolkit:LongListSelector x:Name="listSearchResults" ItemsSource="{Binding SearchResults}" Grid.Row="1" IsFlatList="True" ItemTemplate="{StaticResource ContactItemTemplate}"/>

        </Grid>

    </Grid>

 </Grid>

63.            打開ShowContactsPage.xaml.c文件.

64.            添加下面的代碼:

C#

usingMicrosoft.Phone.UserData;

usingSystem.Collections.ObjectModel;

usingSystem.Windows.Navigation;

using System.Diagnostics;

65.            添加下面的字段和屬性:

C#

private object syncObject = new object();

 

private bool searchInProgress = false;

private bool searchQueued = false;

       

 

Dictionary<string, FilterKind> filterDictionary;

 

private Contacts contacts;

 

public ObservableCollection<Contact> SearchResults

{

    get { return (ObservableCollection<Contact>)GetValue(
        SearchResultsProperty); }

    set {SetValue(SearchResultsProperty, value); }

}

 

public static readonly DependencyProperty SearchResultsProperty =

    DependencyProperty.Register("SearchResults",     typeof(ObservableCollection<Contact>),     typeof(SearchContactsPage), null);

66.            重寫OnNavigatedFrom和OnNavigatedTo 方法以當程序處於墓碑狀態填加調試信息並且在退回到這個界面的時候刷新查詢結果信息.

C#

protected override voidOnNavigatedFrom(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedFrom function ofSearchContactsPage\t ***");

 

    if(e.NavigationMode == NavigationMode.Back)

    {

        if (State.ContainsKey("SearchTerm"))

        {

            State.Remove("SearchTerm");

        }

 

        if(State.ContainsKey("FilterIndex"))

        {

            State.Remove("FilterIndex");

        }

    }

    else

    {

        State["SearchTerm"]= txtSearchTerm.Text;

        State["FilterIndex"]= listFilterType.SelectedIndex;

    }

 

    base.OnNavigatedFrom(e);

}

 

protected override voidOnNavigatedTo(NavigationEventArgs e)

{

    Debug.WriteLine("***\t In OnNavigatedTo function ofSearchContactsPage\t ***");

 

    base.OnNavigatedTo(e);

 

    if(State.ContainsKey("SearchTerm"))

    {

        txtSearchTerm.Text = State["SearchTerm"].ToString();

    }

 

    if(State.ContainsKey("FilterIndex"))

    {

        listFilterType.SelectedIndex = (int)State["FilterIndex"];

    }

}

在這頁裏用戶可以根據顯示名稱,電子郵件或者電話號碼來搜索聯繫人。這就是靠Contacts Chooser實現的。下面加入一個方法來初始化用戶在查詢條件框裏的輸入。

67.            把下面加亮的代碼填入到類的構造函數中的InitializeComponent方法後面:

C#

public ShowContactsPage()

{

    InitializeComponent();

 

    Debug.WriteLine("***\t In constructor of SearchContactsPage\t***");

 

    SearchResults = newObservableCollection<Contact>();

 

    InitializeFilterDictionary();

 

    contacts = newContacts();

    contacts.SearchCompleted +=contacts_SearchCompleted;

 

    listFilterType.SelectionChanged +=listFilterType_SelectionChanged;

 

    txtSearchTerm.KeyUp += txtSearchTerm_KeyUp;

}

68.            添加InitializeFilterDictionary 方法, that will link the entries available to the user through the UI toactual contacts search types:

C#

private void InitializeFilterDictionary()

{

    filterDictionary = newDictionary<string,FilterKind>();

 

    filterDictionary["DisplayName"] = FilterKind.DisplayName;

    filterDictionary["Email"]= FilterKind.EmailAddress;

    filterDictionary["PhoneNumber"] = FilterKind.PhoneNumber;

}

69.            添加 listFilterType_SelectionChanged 事件處理方法來處理用戶選擇不同的查詢方法:

C#

voidlistFilterType_SelectionChanged(object sender, SelectionChangedEventArgs e)

{

    InputScopescope = new InputScope();

    InputScopeNamename = new InputScopeName();

 

    switch(filterDictionary[(listFilterType.SelectedItem asListPickerItem).Content.ToString()])

    {

        case FilterKind.DisplayName:

            name.NameValue = InputScopeNameValue.Default;

            scope.Names.Add(name);

 

            txtSearchTerm.InputScope = scope;

            break;

        case FilterKind.EmailAddress:

            name.NameValue = InputScopeNameValue.EmailNameOrAddress;

            scope.Names.Add(name);

 

            txtSearchTerm.InputScope = scope;

            break;

        case FilterKind.PhoneNumber:

            name.NameValue = InputScopeNameValue.Number;

            scope.Names.Add(name);

 

            txtSearchTerm.InputScope = scope;

            break;

        default:

            break;

    }

 

    QueueSearch();

}

注意上面的方法在輸入搜索關鍵字的時候會根據搜索方式更改鍵盤上顯示的內容。

70.            添加 QueueSearch 方法. 這個方法執行一個不在進行中的查詢:

C#

private void QueueSearch()

{

    lock(syncObject)

    {

        if(searchInProgress)

        {

            searchQueued = true;

            return;

        }

 

        searchInProgress = true;

 

        PerformSearch();

    }

}

71.            添加 PerformSearch 方法來執行查詢:

C#

private void PerformSearch()

{

    if (String.IsNullOrEmpty(txtSearchTerm.Text))

    {

        // There isnothing to look for

        SearchResults.Clear();

        searchInProgress = false;

        return;

    }

 

    contacts.SearchAsync(txtSearchTerm.Text, filterDictionary[(listFilterType.SelectedItemas ListPickerItem).Content.ToString()],null);

}

72.            添加 txtSearchTerm_KeyUp 事件處理方法來初始化用戶的輸入。:

C#

void txtSearchTerm_KeyUp(object sender, KeyEventArgse)

{

    QueueSearch();

}

73.            添加 contacts_SearchCompleted 事件處理方法, 實現的方法爲當查詢完成的時候對UI進行更新:

C#

private void contacts_SearchCompleted(object sender, ContactsSearchEventArgse)

{

    Dispatcher.BeginInvoke(() =>

    {

        try

        {

            SearchResults =

                newObservableCollection<Contact>(e.Results);

        }

        catch

        {

            // Ignoreexceptions, which are caused by searching for a

            // phonenumber with a string that does not contains digits             // alone

        }

        finally

        {

            lock(syncObject)

            {

                searchInProgress = false;

 

                if(searchQueued == true)

                {

                    //A search was queued while already searching.

                    //Try performing it again.

                    searchQueued = false;

                    QueueSearch();

                }

            }

        }

    });           

}

74.            按F5 編譯運行程序.

75.            導航到前面創建的 “Search Contacts” 頁面,點擊application bar的Search按鈕:

圖 66

查找聯繫人。

選擇搜索模式然後輸入檢索條件。

76.            回到應用程序,單擊Back ().

77.            按 SHIFT+F5 停止調試並且返回到 Visual Studio.

此部分有相關實驗代碼.

注意:示例代碼的位置:Source\Ex2-Choosers\End.

 

 

 

總結

本節實驗演示了Windows Phone7中的Launchers和Chooser的使用。每個程序中的頁面中都用到了相應的Launcher和Chooser。參考這些示例你可以在你以後的程序中很容易的使用Launcher和Choosers.

 


發佈了23 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章