Search Contract in Windows 8

0
366

How to implement the Search Contract in WindowsRT applications, using the native Windows 8 APIs

One of the most interesting features of the new runtime of Windows 8 is represented by a series of contracts that the Windows Store applications can join, committing to expose certain features (search, sharing, etc.) to the operating system or other applications, the which can therefore access the contents and functionalities exhibited without requiring prior knowledge of the internal functioning mechanisms of the “target” application.

Through the implementation of the contract of Search , in particular, it is possible for the user to perform searches within the application at any time, even if the application is not running, simply by accessing the search charm . The latter allows you to search for content within the system, whether files, applications, websites, control panel settings, elements within user libraries such as photos or videos, or – and this is the case taken examined in this article – in other applications (those that, in fact, implement the related contract of Search).

For example, in the following image we have searched for the text “learn” among the applications installed on the machine (a bit like in Windows 7 via the search box in the Start menu):

Search results

In the previous image you can see that under Apps, Settings and Files, there are a number of applications. These applications have been registered to the search engine of Windows 8 through the implementation of the relative contract.

For example, we could search for a text (in our case “thinkahead”) inside the Store, which is the locally installed application for viewing the Windows Store. The operating system will ask the local application to perform a search and present the results.

Search Contract in Windows 8 - 02

In order for our application to be used as a search target, the search contract must be implemented . In this introductory article, we retrace the steps to follow to get a simple searchable application.

First of all, in Visual Studio 2012 we create a new Windows 8 project. In the dialog window, we select the Windows Store to access the list of templates proposed by Visual Studio for Windows applications 8. Choose Blank App (XAML) as template, assign to project the name you prefer and select the directory on disk where to save the solution:

New Windows Store project

Before going any further, we populate our application with some sample data on which to perform simple searches. In this example we will not have any graphic pretension nor will we use architectural patterns to stay on the piece.

Add to the project a new class, called Bike, which represents, let’s say, some mountain bike models (a very popular pastime here in Tuscany), and a class <code>Biz</code> whose only method <code>GetAllBikes()</code>, return a collection of … bicycles, in fact. The following is the relevant code:

<pre class=”brush: php; html-script: true”>
public List GetAllBikes()
{
return new List()
{
new Bike() { BikeName = “Specialized Stumpjumper” },
new Bike() { BikeName = “Scott Spark” },
new Bike() { BikeName = “Kona Abra Cadabra” },
new Bike() { BikeName = “Cannondale Jekill” },
new Bike() { BikeName = “Rocky Mountain Altitude” },
new Bike() { BikeName = “Bianchi Metanol” },
new Bike() { BikeName = “Santacruz Tallboy” },
new Bike() { BikeName = “Canyon Torque” }
};
}
</pre>

We attach the data to <code>MainPage</code> our application now. First, let’s modify the XAML page by adding a ListView control to show the list of our entities (highlighted in bold in the following list):

<pre class=”brush: php; html-script: true”>
<Page
x:Class=”Html.it.Demo.SearchContractSample.MainPage”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:local=”using:Html.it.Demo.SearchContractSample”
xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
mc:Ignorable=”d”>
<Grid Background=”{StaticResource ApplicationPageBackgroundThemeBrush}”>
<ListView x:Name=”list” DisplayMemberPath=”BikeName” />
</Grid>
</Page>
</pre>

In the code behind (
<code>MainPage.xaml.cs
</code>) we bind the control just created with our list of bicycles (the lines to be added are highlighted in bold):

<pre class=”brush: php; html-script: true”>
public MainPage()
{
this.InitializeComponent();
var biz = new Biz();
list.ItemsSource = biz.GetAllBikes();
}
</pre>

If we run our application by pressing F5, here’s what we get:

Search Contract in Windows 8 - 04

Now that we have some data with which to test the examples, to implement the search functionality we need to declare its functionality in the application manifest of our application.

To do so, simply open the file
<code>Package.appxmanifest
</code> within our project and, in the Declarations tab, select the functionality of Search from the options available in the dropdown list called Available Declarations.

Search Contract in Windows 8 - 05

In doing so, we have registered our application as a search provider , or as an application able to respond at any time to the searches made by the user, providing the contents that the app itself manages.

To see what happened after registration, right-click on the project and select Deploy to install the application on your PC. Go back to the Windows 8 Start Page (Windows key), activate the Charms Bar (press
<code>Windows+C
</code> or move the mouse in the lower right corner of the screen) and select Charm Search . The new application now appears in the list of applications in which you can search:

Search Contract in Windows 8 - 06

Since we have not yet implemented the search contract, if we tried to click on our application and insert a text to search, we would not get any results.

Implement the search contract

The second step is therefore to implement the contract. For this it is sufficient to add a new Search Contract to our project (consisting of a XAML page and its code behind).

Search Contract in Windows 8 - 07

Visual Studio will ask you to automatically import a set of files (helper classes, converter, style collections, etc.) necessary for the proper implementation of the contract. Press OK to confirm. The addition of the contract from Visual Studio automatically inserts the declaration in the manifest we have seen before.

Here is how the content of the project appears at the end of our operation:

Search Contract in Windows8 - 08

In addition to creating the page in which the search results will be shown (by default
<code>SearchResultPage1.xaml
</code>) and to add the necessary files, Visual Studio also modifies the class by <code>App.cs</code> adding the handler (asynchronous, as you can see) in charge of managing the event. activation of the search by the user. The method code is shown below:

<pre class=”brush: php; html-script: true”>
protected async override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
{
// TODO: Register the Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted
// event in OnWindowCreated to speed up searches once the application is already running
// If the Window isn’t already using Frame navigation, insert our own Frame
var previousContent = Window.Current.Content;
var frame = previousContent as Frame;
// If the app does not contain a top-level frame, it is possible that this
// is the initial launch of the app. Typically this method and OnLaunched
// in App.xaml.cs can call a common method.
if (frame == null)
{
// Create a Frame to act as the navigation context and associate it with
// a SuspensionManager key
frame = new Frame();
Html.Demo.SearchContract.Common.SuspensionManager.RegisterFrame(frame, “AppFrame”);
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore the saved session state only when appropriate
try
{
await Html.Demo.SearchContract.Common.SuspensionManager.RestoreAsync();
}
catch (Html.Demo.SearchContract.Common.SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
}
frame.Navigate(typeof(SearchResultsPage1), args.QueryText);
Window.Current.Content = frame;
// Ensure the current window is active
Window.Current.Activate();
}
</pre>

As you can see, the method receives a type object as a parameter <code>SearchActivatedEventArgs</code>. It is inside this object that the search string is typed (query string) by the user in the appropriate form.

Without going too far into the details of how the method works (which basically controls whether the application was running or not to restore its state or create the frame of contents from scratch), it is interesting to observe how the string query typed by user (and highlighted in bold in the above list) is then passed as a parameter to the search page to be managed in the most appropriate way and to show the result on video.

Let’s sum up what happened so far: the user has activated the charm of Search and typed some text to search within our application. The event triggering the search was intercepted by the method <code>OnSearchActivated</code> of our class App, which also proceeded to move the main frame of the application on the search page ( <code>SearchResultPage1.xaml</code> in our example), passing the search criterion received (args) and to activate it (<code>Window.Current.Activate()</code>) in order to show the user the results of the operation.

Data binding

But what happened to our string query in the meantime? In extreme synthesis, upon activation of the search page is invoked (passing by the method OnNavigatedTo that intercepts the triggering event of the page) the method LoadState , which receives as a parameter precisely the search string entered by the user.

Here is the complete listing of the LoadState method, proposed by default from the search contract on the SearchResultPage1 page, which is responsible for receiving the user’s request and processing the related results:

<pre class=”brush: php; html-script: true”>
protected override void LoadState(Object navigationParameter, Dictionary pageState)
{
var queryText = navigationParameter as String;
// (omissis)
var filterList = new List();
filterList.Add(new Filter(“All”, 0, true));
// Communicate results through the view model
this.DefaultViewModel[“QueryText”] = ‘u201c’ + queryText + ‘u201d’;
this.DefaultViewModel[“Filters”] = filterList;
this.DefaultViewModel[“ShowFilters”] = filterList.Count > 1;
}
</pre>

This class uses the DefaultViewModel to bind the search results and to expose some information about the search itself, such as the string query used, the list of available filters (in this case, a generic “All” filter) and the number of records found.

What we need to do is add, in Biz, a method that allows (even in a primitive way) to carry out research on the fields that interest us and gives us back the list of items that satisfy the search criterion; this method will then be recalled in the method LoadDataillustrated above, passing as a parameter the query string typed by the user.

Here is the method to add to the Biz class:

<pre class=”brush: php; html-script: true”>
public List SearchBikes(String bikeName)
{
return this.GetAllBikes().Where(m => m.BikeName.Contains(bikeName)).ToList();
}
</pre>

Now we modify the LoadData method of the search contract in order to obtain the list of entities that satisfy the search criteria entered by the user, a list that must be put in bind with the DefaultViewModel used by the page to show the results.

While we’re at it, let’s modify the default filter to show the number of records found (bikes.Count), and display it on the screen (filterList.Count> = 1). In bold the changes made to the code are highlighted:

<pre class=”brush: php; html-script: true”>
protected override void LoadState(Object navigationParameter, Dictionary pageState)
{
var queryText = navigationParameter as String;
// Ricerco le bici
var biz = new Biz();
var bikes = biz.SearchBikes(queryText);
// TODO: Application-specific searching logic. The search process is responsible for
// creating a list of user-selectable result categories:
//
// filterList.Add(new Filter(“”, ));
//
// Only the first filter, typically “All”, should pass true as a third argument in
// order to start in an active state. Results for the active filter are provided
// in Filter_SelectionChanged below.
var filterList = new List();
filterList.Add(new Filter(“All”, bikes.Count, true));
// Communicate results through the view model
this.DefaultViewModel[“Results”] = bikes;
this.DefaultViewModel[“QueryText”] = ‘u201c’ + queryText + ‘u201d’;
this.DefaultViewModel[“Filters”] = filterList;
this.DefaultViewModel[“ShowFilters”] = filterList.Count >= 1;
}
</pre>

The last modification consists of video showing the properties of the entities that interest us. To do this simply change the named GridView controlresultsGridView as follows:

<pre class=”brush: php; html-script: true”>
<GridView
x:Name=”resultsGridView”
AutomationProperties.AutomationId=”ResultsGridView”
AutomationProperties.Name=”Search Results”
TabIndex=”1″
Grid.Row=”1″
Margin=”0,-238,0,0″
Padding=”110,240,110,46″
SelectionMode=”None”
IsSwipeEnabled=”false”
IsItemClickEnabled=”True”
ItemsSource=”{Binding Source={StaticResource resultsViewSource}}”>
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text=”{Binding BikeName}” Margin=”0,20,0,0″ Foreground=”#7CFFFFFF” HorizontalAlignment=”Left” />
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemContainerStyle>
<Style TargetType=”Control”>
<Setter Property=”Height” Value=”70″/>
<Setter Property=”Margin” Value=”0,0,38,8″/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
</pre>

We carry out a new application deployment and try to activate the search charm by inserting any text to search. Here is the result:

Search Contract in Windows 8 - 09

Although in this example we are limited to returning simple text strings, there is no limit to the type of data and content to show as a result of the search (images, multimedia content, configuration settings, etc.). Not only that, but you can also take advantage of the API exposed by WinRT to provide the user with suggestions while he is typing the text to be searched.

As we have seen, implementing the research contract is very simple; if we do not consider the graphic part and the internal search logic that obviously could be very complex, it is sufficient to add the Search Contract to the project, choose a name for the search page and modify it to display the results in the most suitable way.

LEAVE A REPLY

Please enter your comment!
Please enter your name here