Windows8。契約「検索」の詳細

アプリケーション内の検索は、Windows 8の新しい、最も重要で興味深い機能の1つです。検索は、デバイス上のファイルやドキュメントだけでなく、インストールされているアプリケーション内の検索も可能にします。



この記事では以下について説明します。

1.メトロアプリケーションでの検索の統合

2.コンテキストプロンプト(提案)。

3.データの入力時にリクエストを処理します。

4.検索コントラクトの不注意な使用(一般的な統合エラー)。



1.メトロアプリケーションでの検索の統合



デフォルトでは、アプリケーションは検索コントラクトをサポートしていません。 この記事では、アプリケーション内に検索を追加する方法について説明します。



検索コントラクトのサポートを追加する最も簡単な方法は、スタジオで既製のテンプレートを使用することです。







VS2012には、対応するエントリをマニフェストに追加するビルトインSearchContractテンプレートがあり(まだ行われていない場合)、app.xaml.csにエントリを追加し(まだ行われていない場合はOnSearchActivatedメソッドをオーバーライドします)、最小限の処理ロジックで検索クエリを受け入れるページを追加します。



このテンプレートの使用については詳しく説明せず、検索コントラクトのサポートを追加することを検討します。



まず、アプリケーションマニフェスト(Package.appxmanifestファイル)で、アプリケーションが検索コントラクトをサポートしていることを示す必要があります。 これを行うには、スタジオでこのマニフェストを開き、「宣言」タブで検索コントラクトを追加します。





さらに、アプリケーションクラス「app.xaml.cs」では、検索コントラクトを介してアプリケーションアクティベーションアルゴリズムをオーバーライドし、必要なロジックを指定できます。 簡単にするために、検索コントラクトの下でアクティブ化されるときは、常に別のページ(SearchPage.xaml)を開くようにします。



protected override void OnSearchActivated(SearchActivatedEventArgs args) { var frame = Window.Current.Content as Frame; if(frame==null) { frame=new Frame(); Window.Current.Content = frame; } frame.Navigate(typeof(SearchPage), args.QueryText); Window.Current.Activate(); }
      
      







このメソッドでは、検索クエリがパラメーターとして指定されているSearchPageページにユーザーをリダイレクトします。



アプリケーションが起動されなかった場合、アプリケーションはOnSearchActivatedメソッドを介して起動されることに注意してください。 この点に関して、現在のフレームはまだ作成されていない可能性があります。 アプリケーションの初回起動時に、nullチェックが実行されてフレームが初期化されます。



SearchPageページで、渡されたパラメーターから検索クエリを受け取ることにより、検索結果を表示できるようになりました。

  protected override void OnNavigatedTo(NavigationEventArgs e) { var query = (string)e.Parameter; SearchByQuery(query); } private void SearchByQuery(string queryText) { pageTitle.Text = "Search result for \"" + queryText + "\":"; //    }
      
      







2.コンテキストプロンプト(提案)。



検索コントラクトAPIを使用すると、検索フレーズを入力するときにコンテキストヒントを追加できます。

アプリケーションのコンテキストヒントは、ユーザーが検索するアプリケーションを選択(アクティブ化)した場合にのみ機能します。





2. 1.テキストプロンプト



サポートの追加は非常に簡単です。ページデザイナーでは、コンテキストプロンプト要求要求イベントにサブスクライブできます。



  public SearchPage()        {            this.InitializeComponent();            SearchPane.GetForCurrentView().SuggestionsRequested += SearchPage_SuggestionsRequested;        }
      
      







さらにSearchPage_SuggestionsRequestedメソッドでは、必要なコンテキストヒントを追加できます。



  void SearchPage_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)        {            var products=new[] { "apple", "cheese", "bread", "onion", "orange", "potato"}            args.Request.SearchSuggestionCollection.AppendQuerySuggestions(products);        }
      
      







ここで、コンストラクターでクエリ選択イベントをサブスクライブする場合:



SearchPane.GetForCurrentView()。QueryChanged + = SearchPage_QueryChanged;



プロンプトからユーザーの選択を処理できます。

  void SearchPage_QueryChanged(SearchPane sender, SearchPaneQueryChangedEventArgs args)        {            SearchByQuery(args.QueryText);        }
      
      







2.2。 挑戦的なヒント



SearchContract APIを使用すると、より複雑なタイプのコンテキストプロンプトを実装できます。









フィールドを持つ製品を返す特定のロジック層(LogicLayer)があるとします。

  public class Product    {        public string Name { get; set; }        public string Image { get; set; }        public string Description { get; set; }        public string Id { get; set; }    }
      
      







SearchPage_SuggestionsRequestedメソッドで、args.Request.SearchSuggestionCollection.AppendResultSuggestionメソッドを使用して、より複雑なヒントを追加する必要があります。

  void SearchPage_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)        {            foreach (var product in LogicLayer.SearchProduct(args.QueryText))            {                var image = RandomAccessStreamReference.CreateFromUri(newUri(product.Image));                args.Request.SearchSuggestionCollection.AppendResultSuggestion(product.Name, product.Description, product.Id, image, String.Empty);            }        }
      
      







ここでは、製品IDをタグとして渡します。 ユーザーが複雑なプロンプトを選択すると、QueryChangedイベントは発生しません。 複雑なプロンプトを処理するために、特別なものがあります

ResultSuggestionChosenイベント。



このイベントの処理をコンストラクターに追加できます。



SearchPane.GetForCurrentView()。ResultSuggestionChosen + = SearchPage_ResultSuggestionChosen;



これで、製品識別子へのリンクを取得して処理できます。

  void SearchPage_ResultSuggestionChosen(SearchPane sender, SearchPaneResultSuggestionChosenEventArgs args)        {            var id = args.Tag;            SearchById(query);        }
      
      





2.3。 すべてのページのコンテキストヘルプ。



小規模なアプリケーションでは、ページごとに個別のコンテキストヒントを作成するのではなく、アプリケーション全体に対して1つのヒントを作成する方が簡単です。



アプリケーションインスタンスの検索イベントにサブスクライブできます。 同時に、アプリケーションは数回アクティブ化できるため、1回だけサブスクライブするようにする必要があります。



SubscribeToSearchEventsメソッドをApp.xaml.csに追加します



  private bool isSubscribed; public void SubscribeToSearchEvents() { if (!isSubscribed) { isSubscribed = true; SearchPane.GetForCurrentView().SuggestionsRequested += SearchPage_SuggestionsRequested; SearchPane.GetForCurrentView().ResultSuggestionChosen += SearchPage_ResultSuggestionChosen; SearchPane.GetForCurrentView().QueryChanged += SearchPage_QueryChanged; } }
      
      









OnLaunchedおよびOnSearchActivatedメソッドで呼び出すだけです



  protected override void OnLaunched(LaunchActivatedEventArgs args) { SubscribeToSearchEvents(); ... }
      
      









  protected override void OnSearchActivated(SearchActivatedEventArgs args) { SubscribeToSearchEvents(); }
      
      









3.データの入力時にリクエストを処理します。



さらに複雑なヒントスクリプトを実装する必要がある場合、またはクエリをすばやく処理して、入力が完了する前に検索クエリの結果をすぐに表示できる場合は、検索クエリのイベント(QueryChanged)をサブスクライブできます。



これを行うには、コンストラクタに次のメソッドを追加できます。



SearchPane.GetForCurrentView()。QueryChanged + = SearchPage_QueryChanged;



他のイベントと同様に、検索リクエストを処理できます。

  void SearchPage_QueryChanged(SearchPane sender, SearchPaneQueryChangedEventArgs args) { SearchByQuery(args.QueryText); }
      
      









4.一般的な検索統合エラーを修正します。



ここで説明する推奨事項は、Windows 8 RPのバージョンに適用され、リリースでは確実に修正されます。 ただし、現在では、ほとんどすべてのアプリケーション(Peopleなどの組み込みシステムアプリケーションを含む)に固有の「症状」がいくつかあります。



4.1。 メインページにアクセスする機会が失われます。



アプリケーションが以前に起動されていなかった場合、アプリケーションが検索コントラクトで初めて起動されたときに、検索ページが開きます。 これで、ユーザーがメインメニューに移動してアプリケーションを再度起動すると、検索ページが再度表示され、アプリケーションが検索前に起動された場合にのみ戻るボタンが検索ページに表示されるため、メインメニューに移動できません。 メインページにアクセスする唯一の方法は、アプリケーションを閉じて再起動することです。



この問題を修正するのは非常に簡単です。 フレームを初期化するときに検索アプリケーションをアクティブ化する方法(OnSearchActivated)では、メインページに追加のトランジションも追加します。

  protected override void OnSearchActivated(SearchActivatedEventArgs args)        {            var frame = Window.Current.Content as Frame;            if(frame==null)            {                frame=new Frame();                Window.Current.Content = frame;
      
      





  //                  frame.Navigate(typeof(MainPage));            }                       frame.Navigate(typeof(SearchPage), args.QueryText);            Window.Current.Activate();        }
      
      





4.2。 複数の検索ページインスタンス



複数の検索フレーズを連続して入力すると、ページのコピーが毎回作成され、戻るボタンを使用してメインページにアクセスしようとすると、前の検索ページに移動します。 おそらくこれはバグではなく機能です。この場合、作成された各インスタンスで検索イベントがトリガーされ、複数のインスタンスからのリクエストを処理すると深刻なパフォーマンス問題が発生する可能性があることに注意してください。

個人的には、私の意見はバグです。メインページに戻るために戻るボタンを数回押す必要があることに悩まされることが非常に多いからです。



1つの解決策は非常に簡単です。 検索アプリケーションをアクティブにするとき、現在のページが検索ページであるかどうかを確認し、この場合に戻ります。

  protected override void OnSearchActivated(SearchActivatedEventArgs args)        {           RemoveSearchPage();            var frame = Window.Current.Content as Frame;            if(frame==null)            {                frame=new Frame();                Window.Current.Content = frame;                frame.Navigate(typeof(MainPage));            }                        frame.Navigate(typeof(SearchPage), args.QueryText);            Window.Current.Activate();        }
      
      







したがって、RemoveSearchPageメソッドの実装:

  private void RemoveSearchPage() { var frame = Window.Current.Content as Frame; if (frame== null) { return; } var page=frame.Content as Page; if (page == null) { return; } if (page.GetType()==typeof(SearchPage)) { frame.GoBack(); } }
      
      







ソースコード(288.51 kb)



PS記事を準備する際に貴重なコメントをいただいたhabrazer Stas Pavlovに感謝します。



All Articles