Windows 8 Metro Style Apps 開發攻略 - 藉由不同的 Contracts 打造更優良的使用者體驗


序言

在 Windows 8 Metro Style Apps 中,除了使用者介面和以往一般的 Desktop Apps 有著極大的差異之外,在開發 Metro Style Apps 的時候,我們還可以透過不同的 Contract,讓 App 得以透過 Windows 8 裡面的各種 Charm 面版,進行多種不同的互動,讓 Apps 和作業系統甚至是其他的 App 之間能夠有更緊密的結合,以打造出更一致且無接縫的使用者體驗。

而這篇文章,就會針對各種 Contract,提供比較初步的介紹,也提供幾個非常簡單的小範例,讓大家能動手實作看看,體驗一下 Contract 和 Charm 之間的互動。

至於每種 Contract 的詳細用法及運作原理等等細節,就留在日後的章節,再針對各別的 Contract 為大家作更深入且詳細的介紹囉!!

淺論 Contract

在 Windows 8 中,提供了以下幾種 Contract 供 Metro Style Apps 使用:

我們可以把這些 Contract 看作是作業系統中預先定義好的介面,我們只需要在我們開發的 Metro Style Apps 裡實作這些 Contract 的邏輯,就可以透過這些 Contract,輕鬆的與其他一樣有實作這些 Contract 的 Metro Style Apps 及作業系統進行互動,而不用詳細的知道我們要互動的對象本身 (不論是其他的 Metro Style Apps 或 Windows 8) 實作的方式和細節。

在介紹各種 Contract 之前,先跟各位分享一組實用的熱鍵組合—Windows 按鈕 +C 鍵 (或是將滑鼠移到螢幕的最右上或右下角),就可以開啟作業系統的 Charm 選單,Charm 選單裡面提供了搜尋、分享、設定等等相關功能,這些功能都和我們等一下要介紹的 Contract 是有密切關係的喔~

接著來簡短的針對各種 Contract 作一下初步的介紹:

Search contract
Search contract 可以用來建立針對 Metro Style Apps 中內容的搜尋功能。我們可以輕鬆的透過 Search contract 的實作,讓使用者能直接透過 Windows 8 裡的 Search Charm 對我們開發的 Metro Style Apps 的內容裡的字串或是文字進行查找。

一旦我們的 App 實作了 Search contract,當使用者打開 Windows 8 的 Search Charm 時,我們的 App 就會出現在右下方的 Apps 列表,使用者就可以直接在該介面點選我們的 App 的 Icon,針對我們的 App 中的資料內容進行搜尋,如此一來,我們也不用特別去多花心思去為我們的每一個 App 設計個自的搜尋使用者介面,一切都交給 Windows 8 的 Search Charm 就行了。

直接開啟 Windows 8 內建的 Search 面版的熱鍵為 Windows 鈕 + Q鍵。

不過,透過 Search contract 並不能針對 App 中特定文件的內容進行搜尋,如果要實作出針對特定文件內容的搜尋功能的話,就得自己在 App 中撰寫搜尋的使用者介面和邏輯喔!!

Share contract
Share contract 比較特別的地方是,它有所謂的「來源端 App」及「目標端 App」。如果我們開發的 Metro Style Apps 裡會有檔案可以當作資料來源給其他的 Metro Style Apps 使用,那麼這個 App 就會是來源端 App;相反的,如果我們的 Metro Style Apps 允許接受其他 Metro Style Apps 的資料作為資料的輸入來源的話,這個 App 就是目標端 App,可以藉由 Share Target contract 來實作讓它可以透過 Share Charm 接受其他 App 的資料來源的功能。透過 Share Contract,我們就能使用 Windows 8 的 Share Charm,讓使用者更輕鬆的進行資料間的分享及傳遞了。

直接開啟 Windows 8 內建的 Share 面版的熱鍵為 Windows 鈕 + H 鍵。

Settings contract
透過 Settings contract 的實作,我們就讓使用者可以透過 Windows 8 的 Settings Charm 來針對我們開發的 Metro Style Apps 進行設定,如此一來,我們不用費心去特別設計一個設定專用的畫面,再來,整個使用者體驗也和作業系統本身更為貼近。

直接開啟 Windows 8 內建的 Settings 面版的熱鍵為 Windows 鈕 + I 鍵。

Play To contract
透過實作 Play To contract,我們可以輕鬆的將使用者在我們開發的 Metro Style Apps 中進行撥放的影片、音樂或是相片等等媒體檔案,以串流的方式,透過相容於 DLNA 的裝置進行撥放。若作業系統偵測到有支援相關功能的其他裝置,會自動將那些裝置顯示在 Devices Charm 裡,而我們就可以透過 Play To 功能,將媒體以串流的傳輸方式傳送過去。

直接開啟 Windows 8 內建的 Devices 面版的熱鍵為 Windows 鈕 + K 鍵。

App to App Picking contract
我們可以透過 App to App Picking contract 的實作,讓我們的 App 可以開啟檔案系統、網路上或是其它線上服務中的檔案,甚至使某個 App 具備能透過其他 App 進行瀏覽或是開啟特定類型檔案的能力;除此之外,使用者在開啟特定類型檔案時,也可以自行決定要使用哪一個 App 來開啟。

透過 Search Contract 實作 Metro Style Apps 的搜尋功能

要讓 Metro Style Apps 支援搜尋功能有兩種作法,第一個方法是直接透過修改專案中的 Package.appxmanifest 檔,透過設定的方式,開啟搜尋功能的支援。

不過,身為一個稱職的工程師,透過工程師的方法 (也就是寫程式啦~) 來處理這樣的需求也是再合理不過的了,我們可以直接在 App 中加入一個 Search Contract ,直接在裡面定義好相關的動作即可,實作完了 Search Contract 之後,我們的 App 就會自動支援搜尋的功能。

這邊建議有興趣的朋友們以 Grid Application 作為專案樣版,建立一個專案來作練習 (這邊我將專案名稱命名為 SearchContractSample)。

在 App 中加入 Search Contract 的詳細方法如下:

在方案總算中的專案名稱上按下滑鼠右鍵,選取 Add->New Item...

接著在新增項目視窗中找到 Search Contract 項目,將預設檔名改為 SearchResultsPage.xaml 後,按下 Add 鈕。

接著請重新建置專案 (熱鍵為 Ctrl+Shift+B),就可以看到預設的搜尋結果畫面。

在我們新增了 Search Contract 之後,Visual Studio 11 會自動幫我們在 App.xaml.cs 檔中加入以下程式碼:

protected override void OnSearchActivated( Windows.ApplicationModel.Activation.SearchActivatedEventArgs args ) { SearchContractSample.SearchResultsPage.Activate( args.QueryText ); // TODO: Move the following code to OnLaunched to speed up searches when your // application is already running: //Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted += // (sender, queryArgs) => // { // SearchContractSample.SearchResultsPage.Activate(queryArgs.QueryText); // }; }

如此一來,當有使用者透過 Search Charm 針對我們的 App 進行搜尋的動作發生的話,就會自動被引導到 SearchResultPage 來處理並呈現結果。

順帶一提,如果希望在我們的 App 正在執行時的搜尋速度的話,則可以將被註解掉的以下程式碼搬移到 OnLaunched() 方法裡頭。

Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted += ( sender , queryArgs ) => { SearchContractSample.SearchResultsPage.Activate( queryArgs.QueryText ); };

不過,預設的 SearchResultPage 並還沒真正具備針對我們 App 中的資料進行搜尋的能力,因此我們得對它動一點手腳,在裡面加入我們針對資料進行搜尋的程式碼。

因為 GridApplication 專案樣版中已經幫我們建好了一組分組過的範例資料 (在 DataModel 資料夾裡的 SampleDataSource.cs 檔),所以這邊我們就可以直接拿它來當作資料來源,以供查詢。

我們就直接在 SearchResultPage.xaml.cs 的 OnNavigatedTo 方法中寫一些簡單的程式碼,讓使用者可以針對 SampleDataSource 中的 Group Name 進行搜尋。

只要在 SearchResultPage.xaml.cs 的 OnNavigatedTo 的最後加上下面的程式碼,我們的 SearchContractSample 就具備了最基本的搜尋功能囉!!

this.DefaultViewModel[ "Results" ] = new SearchContractSample.Data.SampleDataSource().ItemGroups.Where( ig => ig.Title.ToLower().Contains( queryText.ToLower() ) );

完成之後,馬上將 App 進行重新建置並且發佈來實測看看吧!!

要將 App 進行發佈,可以透過 Visual Studio 11 功能表中的 Build->Deploy Solution 來完成。

發佈完畢之後,請直接叫出 Search Charm,應該就會發現我們的 App 出現在右下方的 Apps 清單之中囉!! 接著就點選我們的 App,並且在右上方的搜尋方塊裡輸入一些文字進行搜尋看看吧~

雖然我們很輕鬆的就實作出這樣的功能,但是關於在 Search Contract 中能運用的其他相關技巧還不少喔!! 例如提供使用者搜尋結果的飾選器 (Filter)、關鍵字建議、直接使用當前的頁面顯示搜尋結果....等等,關於這些技巧,我們就留到日後以專文來深入針對 Search Contract 的運作邏輯和其他技巧來作更詳細的介紹。

透過 Share Contract 實作 Metro Style Apps 的分享功能

如同前面提到的,分享功能分為來源端 App 及目標端 App,所以這個小練習,我們就使用 Blank Application 專案樣版來建立兩個 Metro Style App 專案,分別名為 ShareSourceSample 及 ShareTargetSample。

下面的範例,會在 ShareSourceSample 中提供一個文字輸入方塊,以讓我們把裡面的文字內容分享到 ShareTargetSample 中。

請試著修改 ShareSourceSample 中的 BlankPage.xaml 檔,實作出如下圖的使用者介面:

或是直接使用以下的 Xaml 碼:

<Page x:Class="ShareSourceSample.BlankPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:ShareSourceSample" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundBrush}"> <Grid.RowDefinitions> <RowDefinition Height="140"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock x:Name="pageTitle" Text="Share Source App" Grid.Column="1" Style="{StaticResource PageHeaderTextStyle}" Margin="20,0,40,40"/> <StackPanel Grid.Row="1" Margin="20" HorizontalAlignment="Center" VerticalAlignment="Center" Width="500"> <TextBlock FontSize="24">Content to share:</TextBlock> <TextBox Name="txtContentToShare" Margin="0,10,0,0"/> </StackPanel> </Grid> </Page>

再來要在 BlankPage.xaml.cs 中加入程式碼,讓它可以和 Share Charm 進行互動,完成後的程式碼如下:

using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.ApplicationModel.DataTransfer; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; namespace ShareSourceSample { public sealed partial class BlankPage : Page { public BlankPage() { this.InitializeComponent(); DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView(); dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager , DataRequestedEventArgs>( dataTransferManager_DataRequested ); } protected override void OnNavigatedTo(NavigationEventArgs e) { } private void dataTransferManager_DataRequested( DataTransferManager sender , DataRequestedEventArgs args ) { args.Request.Data.Properties.Title = "Text to Share"; args.Request.Data.Properties.Description = "just a simple sample"; args.Request.Data.SetText( txtContentToShare.Text ); } } }

接著,看看 ShareTargetSample 裡該怎麼去接 ShareSourceSample 要分享的文字吧!!

跟 Search Contract 一樣,在 Visual Studio 11 中提供了 Share Target Contract 樣版可以讓我們使用,所以就不用客氣的在 ShareTargetSample 專案中新增一個 ShareTargetContract,並將它的檔名改為 ShareTargetPage.Xaml 吧!

加入了 Share Target Contract 之後,我們會發現該專案的 App.xaml.cs 檔中也自動被加上了一段程式碼,用來與 Share Charm 互動:

protected override void OnShareTargetActivated( Windows.ApplicationModel.Activation.ShareTargetActivatedEventArgs args ) { var shareTargetPage = new ShareTargetSample.ShareTargetPage(); shareTargetPage.Activate( args ); }

除了上述的動作之外,我們還得再針對我們的 App 要接受哪些種類的資料來源作些設定,這個動作可以直接透過編輯 Package.appxmanifest 檔來完成。

因為我們的 ShareSourceSample 會分享出去的資料是文字格式,所以我們只需要設定 Share Target 接受 Text 格式的資料源即可,另外,我們的 ShareTargetSample 並不打算接受檔案為資料來源,所以可以直接將 Supports Any File Types 取消勾選 (如下圖所示),修改完畢後,請記得存檔喔!!

接下來,又是需要動手寫點程式的時候了,請開啟我們剛才新增的 ShareTargetPage.xaml 檔,將原來的

<TextBlock Text="Sharing&#x2026;" Visibility="{Binding Sharing, Converter={StaticResource BooleanToVisibilityConverter}}" HorizontalAlignment="Left" Margin="25,0,0,0" Style="{StaticResource ItemTextStyle}"/>

加上 Name 屬性,好讓我們可以在 Code-Behind 對它進行操作,也順便把文字大小作個調整:

<TextBlock Name="txtContentFromSource" Text="Sharing&#x2026;" Visibility="{Binding Sharing, Converter={StaticResource BooleanToVisibilityConverter}}" HorizontalAlignment="Left" Margin="25,0,0,0" Style="{StaticResource ItemTextStyle}" FontSize="36"/>

再來要來對 ShareTargetPage.xaml.cs 檔動點手腳,請將 ShareButton_Click 這個 EventHandler 的程式碼改為如下:

private async void ShareButton_Click( object sender , RoutedEventArgs e ) { this.DefaultViewModel[ "Sharing" ] = true; this._shareOperation.ReportStarted(); string contentFromSource = await _shareOperation.Data.GetTextAsync(); txtContentFromSource.Text = contentFromSource; //請務必記得將下面這行 Mark 掉,否則會看不到分享的結果喔!! //this._shareOperation.ReportCompleted(); }

完成了上述動作之後,請分別針對 ShareSourceSample 與 ShareTargetSample 兩個專案進行建置與發佈,並且執行 ShareSourceSample。

執行之後請叫出 Share Charm,這時候就會看到我們的 ShareTargetSample 出現在可以分享的目標 Apps 清單當中:

再來請在 ShareSourceSample 中的文字方塊裡輸入任意文字,再點選 Share Charm 中的 ShareTargetSample。

再按下 Share Charm 中 ShareTargetSample 的 Share 按鈕~~我們就可以看到,我們在文字方塊裡輸入的文字,跑到 ShareTargetSample 裡去了!!

當然,我們這個小範例一樣只是要對 Share Contract 作個初步的體驗和了解,所以作了很多的簡化。一般而言,在 Share Target App 裡面,是會去實作出自己儲存來自 Share Source App 的資料的機制,然後再由 Share Target App 中既有的頁面來作呈現的喔!!

透過 Settings Charm 與 Metro Style Apps 進行互動

某些 Apps 會提供自己專屬的一些屬性讓使用者進行設定,例如決定 Apps 的配色方式、外觀、或是儲存一些使用者的偏好屬性值等等。通常,我們得針對每個 Apps 去設計、實作出每個 Apps 自己的設定畫面、行為和機制。不過,在 Metro Style Apps 裡,我們就可以藉由 Settings Contract,來與 Windows 8 的 Settings Charm 進行互動,讓使用者可以透過 Settings Charm 來對 Apps 進行設定。

不過,要透過 Settings Charm 和我們的 App 溝通,可就不像前面介紹的兩個 Contract 一樣,都有樣版可以套用了喔!! 因為「設定」這個動作,在 Windows 8 裡面有對它的使用者體驗特別訂定了一些指導方針,比較難去實作出一個可以符合所有 Metro Style Apps 使用的樣版,所以,我們就還是自己來動手作看看吧!!

首先,請以 Visual Studio 11 的 Blank Application 專案樣版建立一個名為 SettingsContractSample 的專案。

接著我們要來修改一下 BlankPage.xaml,讓它可以跟 Settings Charm 作些互動。

我們就簡單的實作以下的使用者介面,讓使用者可以藉由點選 Settings Charm 中的項目,來改變目前 App 的前景顏色。

XAML Code 如下:

<Page x:Class="SettingsContractSample.BlankPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:SettingsContractSample" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundBrush}"> <TextBlock Text="Settings Contract Sample" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="72"/> <Button Name="btnShowSettings" Content="Show Settings Panel" Click="btnShowSettings_Click" HorizontalAlignment="Center" Margin="0,200,0,0"/> </Grid> </Page>

再來一樣得在 BlankPage.xaml.cs 檔裡面加點工,

using System; using System.Collections.Generic; using System.IO; using System.Linq; using Windows.Foundation; using Windows.Foundation.Collections; //記得加入Windows.UI.ApplicationSettings命名空間的引用 using Windows.UI.ApplicationSettings; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; namespace SettingsContractSample { public sealed partial class BlankPage : Page { public BlankPage() { this.InitializeComponent(); //註冊 Settings Charm 中的命令被請求時相對應的 Event Handler SettingsPane.GetForCurrentView().CommandsRequested += new TypedEventHandler<SettingsPane , SettingsPaneCommandsRequestedEventArgs>( SettingsPane_CommandsRequested ); } protected override void OnNavigatedTo(NavigationEventArgs e) { } private void btnShowSettings_Click( object sender , RoutedEventArgs e ) { //透過這行程式就可以呼叫出 Settings Charm SettingsPane.Show(); } //將命令註冊到 Settings Charm 中,並指定命令被呼叫時的對應事件,這會在 Settings Charm 每次被開啟的時候被呼叫 private void SettingsPane_CommandsRequested( SettingsPane sender , SettingsPaneCommandsRequestedEventArgs args ) { SettingsCommand redCommand = new SettingsCommand( "Red" , "Red" , new Windows.UI.Popups.UICommandInvokedHandler( onCommandInvoked ) ); args.Request.ApplicationCommands.Add( redCommand ); SettingsCommand whiteCommand = new SettingsCommand( "White" , "White" , new Windows.UI.Popups.UICommandInvokedHandler( onCommandInvoked ) ); args.Request.ApplicationCommands.Add( whiteCommand ); } //當命令被呼叫時,作出相對應的反應 public void onCommandInvoked( Windows.UI.Popups.IUICommand command ) { SettingsCommand settingsCommand = ( SettingsCommand ) command; switch( settingsCommand.Label ) { case "Red": this.Foreground = new SolidColorBrush( Windows.UI.Colors.Red ); break; case "White": this.Foreground = new SolidColorBrush( Windows.UI.Colors.White ); break; } } }

到這邊為止,我們就完成這個範例了~直接按下 F5 鈕來執行看看吧!!

執行畫面如下:

而當我們按下 Show Settings Panel 按鈕時,Windows 8 的 Settings Charm 就會被呼叫出來。

接著我們就可以去點選我們加入的 Red 或是 White 兩個命令,去切換 App 的前景顏色。

關於 Windows 8 中的 Contracts 基本介紹就先到這邊告一段落。

更多關於 Contracts 相關的資訊,可以參考以下網站:

本文中的範例專案原始碼如下: