Most apps contain some sort of data that you as a developer would like exposed. That’s were the Search Contract comes into play. Say the user is on the start screen and wishes to search your app, they could just start typing and select your app from the list. If you implemented Search contract, your app will be listed in the app list and the user could just type away and hit enter to see results. That would be nice wouldn’t it ?
Lets get on with it and add search contract in a simple / easy way.
Right click on the Win8 project and select Search Contract. Name it whatever you wish and hit enter.

This does two things:
- Adds override for
OnSearchActivatedin your App.xaml.cs - Adds required page for search and display of results.
This is what the OnSearchActivated looks like
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();
Cineworld.Common.SuspensionManager.RegisterFrame(frame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
// Restore the saved session state only when appropriate
try
{
await Cineworld.Common.SuspensionManager.RestoreAsync();
}
catch //(Cineworld.Common.SuspensionManagerException)
{
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
}
frame.Navigate(typeof(SearchResults), args.QueryText);
Window.Current.Content = frame;
// Ensure the current window is active
Window.Current.Activate();
}
as you can see it is passing the search query to the Search Results page while navigating.
Now lets look at the code-behind in SearchResults.xaml.
FYI, I am loading my dataset if required in the OnNavigatedTo method. This page is a simple results display page. It contains GridView / ListView to display results. Lets look at the LoadState method
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
var queryText = navigationParameter as String;
List<SearchResult> matches = new List<SearchResult>();
foreach (var f in App.Films.Values)
{
IEnumerable<CastInfo> casts = from cast in f.FilmCast
where cast.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
select cast;
foreach (var c in casts)
{
//searchCinemas.Add(c.Name, c);
matches.Add(new SearchResult() { Name = c.Name, Subtitle = String.Format("{0} in {1}", c.Character, f.Title), SearchObject = f, Image = c.ProfilePath });
}
}
IEnumerable<FilmInfo> films = from film in App.Films.Values
where film.Title.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
select film;
searchFilms.Clear();
searchCinemas.Clear();
foreach (var f in films)
{
searchFilms.Add(f.Title, f);
matches.Add(new SearchResult() { Name = f.Title, Image = f.PosterUrl, SearchObject = f });
}
IEnumerable<CinemaInfo> cinemas = from cinema in App.Cinemas.Values
where cinema.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
select cinema;
foreach (var c in cinemas)
{
searchCinemas.Add(c.Name, c);
matches.Add(new SearchResult() { Name = c.Name, SearchObject = c, Image = new Uri("ms-appx:///Assets/Background.png") });
}
// TODO: Application-specific searching logic. The search process is responsible for
// creating a list of user-selectable result categories:
//
// filterList.Add(new Filter("<filter name>", <result count>));
//
// 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.
// Communicate results through the view model
this.DefaultViewModel["QueryText"] = '\u201c' + queryText + '\u201d';
bAllowNav = false;
this.DefaultViewModel["Results"] = matches;
bAllowNav = true;
var filterList = new List<Filter>();
filterList.Add(new Filter("All", 0, true));
//this.DefaultViewModel["Filters"] = filterList;
//this.DefaultViewModel["ShowFilters"] = filterList.Count > 1;
}
I added code to search my dataset and to add results to DefaultViewModel. I don’t use MVVM but the default code implemented basic binding etc and I thought I’d leave it at that. I accumulate the results and save them and let bindings do the rest. Let me show you how it looks
Say I got to start screen, type I ben and select my app, this is what I get.

Now you have a nice list of matched entries. Now suppose I wanted to let users click on a matched entry and to navigate them to details page ? I implemented GridView ItemClick event (SelectionChanged doesn’t work for some reason)
private void resultsGridView_ItemClick(object sender, ItemClickEventArgs e)
{
if (e.ClickedItem != null && bAllowNav)
{
SearchResult res = (SearchResult)e.ClickedItem;
if (res.SearchObject is FilmInfo)
{
FilmDetails.SelectedFilm = (res.SearchObject as FilmInfo);
this.Frame.Navigate(typeof(FilmDetails));
}
else if (res.SearchObject is CinemaInfo)
{
CinemaDetails.SelectedCinema = (res.SearchObject as CinemaInfo);
this.Frame.Navigate(typeof(CinemaDetails));
}
}
}
Hope this post is helpful to others looking to implement the search contract. Happy coding!
Pingback: Implement Search Contract the easy way #win8dev