Implementing Search Contract in Windows 8 application

The Search Contract feature helps improve the accessibility of your application. When a user is trying to search for something through the charms, you see a bunch of apps that get listed below.

imageYou see that Store, Howzzat Book and Live Reader apps have implemented this feature. So a user types in some text and clicks on one of these apps and this text is passed to the app where you can show the results of this search directly. Let’s see how to get this implemented.

I have created a Blank App named SearchContractTest. Open the Package.appmanifest file and under the Declarations tab, add the Search contract. I’m sorry, VS2012’s default theme does not make it very obvious that I’m in the Declarations tab.

image

Just run the app and when you go to the Search feature the Charms, you’ll see SearchContractTest app listed in here.

image

Now let’s do the plumbing to make sure the application actually gets the text that was typed in the textbox.

In my App.xaml.cs file, there’s a method called OnLaunched. I’m going to extract the body of this method to a new method called EnsureAppActivated as I’ll need the body of the OnLaunched method in other places as well. This is what it looks for me now.

   1:  protected override void OnLaunched(LaunchActivatedEventArgs args)
   2:  {
   3:      EnsureAppActivated(args);
   4:  }
   5:   
   6:  private static void EnsureAppActivated(IActivatedEventArgs args)
   7:  {
   8:      Frame rootFrame = Window.Current.Content as Frame;
   9:   
  10:      // Do not repeat app initialization when the Window already has content,
  11:      // just ensure that the window is active
  12:      if (rootFrame == null)
  13:      {
  14:          // Create a Frame to act as the navigation context and navigate to the first page
  15:          rootFrame = new Frame();
  16:   
  17:          if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
  18:          {
  19:              //TODO: Load state from previously suspended application
  20:          }
  21:   
  22:          // Place the frame in the current Window
  23:          Window.Current.Content = rootFrame;
  24:      }
  25:   
  26:      if (rootFrame.Content == null)
  27:      {
  28:          // When the navigation stack isn't restored navigate to the first page,
  29:          // configuring the new page by passing required information as a navigation
  30:          // parameter
  31:          if (!rootFrame.Navigate(typeof(MainPage)))
  32:          {
  33:              throw new Exception("Failed to create initial page");
  34:          }
  35:      }
  36:      // Ensure the current window is active
  37:      Window.Current.Activate();
  38:  }

Next I’ll override the OnSearchActivated method. This is the method that gives me with the query text and the language.

image

I’ll switch gears to our MainPage.xaml page where I have a very simple UI.

   1:  <StackPanel Margin="100, 80, 0, 0">
   2:    <TextBlock Text="Implementing Search Contract" FontSize="32"/>
   3:    <TextBlock x:Name="QueryText" FontSize="20"/>
   4:    <TextBlock x:Name="Language" FontSize="20"/>
   5:  </StackPanel>

In the code-behind, I have introduced a static field for the MainPage, named Current that is getting set in the constructor. There is also a ProcessSearchQuery method that gets the query text and the language.

   1:  public sealed partial class MainPage : Page
   2:  {
   3:    public static MainPage Current;
   4:    public MainPage()
   5:    {
   6:      this.InitializeComponent();
   7:      Current = this;
   8:    }
   9:   
  10:    internal void ProcessSearchQuery(string queryText, string language)
  11:    {
  12:      QueryText.Text = queryText;
  13:      Language.Text = language;
  14:    }
  15:  }

Returning to the App.xaml.cs page, I now have to override the OnSearchActivated method.

   1:  protected override void OnSearchActivated(SearchActivatedEventArgs args)
   2:  {
   3:    EnsureAppActivated(args);
   4:    MainPage.Current.ProcessSearchQuery(args.QueryText, args.Language);
   5:  }

That’s it. I can just run this app and see it working.

imageimage

Now that we’ve nailed down how to get the search contract implemented, let’s look at a couple more add-ons around this feature.

Say a user is in your app and goes to the Search settings. You now have the ability to give some real-time suggestions as the user starts typing in the text field. For this, I need to get an instance of the SearchPane (in the Windows.ApplicationModel.,Search namespace) in my MainPage, handle its SuggestionsRequested event and then populate the SearchSuggestionCollection.

In my MainPage.xaml.cs file, I am getting a reference to the SearchPane through the GetForCurrentView() method. I also have a list of names to show as suggestions.

   1:  private SearchPane _searchPane;
   2:  private static readonly string[] _suggestedNames =
   3:  {
   4:    "Arun", "Arvind", "Arjun", "Aryan", "Arnav", 
   5:    "Armugam", "Sanjeev", "Sangeeta", "Sanjay", 
   6:    "Girish", "Girija",
   7:  };
   8:   
   9:  public MainPage()
  10:  {
  11:      this.InitializeComponent();
  12:      Current = this;
  13:      _searchPane = SearchPane.GetForCurrentView();
  14:  }

Once the user navigates to this page, I provide a handle to the SuggestionsRequested event.

   1:  protected override void OnNavigatedTo(NavigationEventArgs e)
   2:  {
   3:      _searchPane.SuggestionsRequested += SearchPane_SuggestionsRequested;
   4:  }
   5:   
   6:  void SearchPane_SuggestionsRequested(SearchPane sender, 
   7:                                       SearchPaneSuggestionsRequestedEventArgs args)
   8:  {
   9:      var queryText = args.QueryText;
  10:      var request = args.Request;
  11:   
  12:      IEnumerable<string> names = from suggestion in _suggestedNames
  13:                                  where suggestion.StartsWith(queryText, 
  14:                                                             StringComparison.CurrentCultureIgnoreCase)
  15:                                  select suggestion;
  16:   
  17:      // Take(5) is implemented because the SearchPane 
  18:      // can show a maximum of 5 suggestions
  19:      // passing a larger collection will only show the first 5
  20:      request.SearchSuggestionCollection.AppendQuerySuggestions(names.Take(5));
  21:  }
  22:   

Now when I try to search while running the app, I get some suggestions.

image

So that’s how you can get the suggestions from the search settings.

There is one more thing that can make the application experience slightly better. When I’m running the app, how about if I just start typing to search something right on the application itself instead of having to go to the Search setting and then typing it there? Yes, you can set up your Windows 8 application to be responsive to your keyboard input on any page. You just need to set the ShowOnKeyboardInput property to true.

   1:  protected override void OnNavigatedTo(NavigationEventArgs e)
   2:  {
   3:      _searchPane.SuggestionsRequested += SearchPane_SuggestionsRequested;
   4:      _searchPane.ShowOnKeyboardInput = true;
   5:  }
   6:   
   7:  protected override void OnNavigatedFrom(NavigationEventArgs e)
   8:  {
   9:      _searchPane.ShowOnKeyboardInput = false;
  10:  }

Now I can just start typing on the page and the Search pane opens up automatically showing the keys I have typed in. I have a couple of concerns with this feature.

  • How would a user know such a feature exists? Users of computers, both casual and advanced, have some kind of desktop / web experience and follow that usage pattern.They are not accustomed to just start typing on a page / screen outside a control and expect to see something happen. So this will be something to get used to and will have a learning curve.
  • I’m not sure how tablet users can make use of this as the virtual keyboard appears only when the an input control gets focus.

Search Contract is a powerful feature that makes your application more ‘like’able, see if you can get it implemented.

5 Comments

Comments have been disabled for this content.