Ajouter du Charm à votre appli Metro (Partie II) (Release Preview)

Tags: .NET, Metro, Contract, Windows 8, WinRT, Charms, Search, Release Preview

MISE A JOUR POUR LA RELEASE PREVIEW

Avant tout : Ces articles ont été écrit avec la version Consumer Preview. Il n’y a pas de garanties que cela fonctionnera avec les autres versions.

Ajouter du Charm à votre appli Metro (Partie I) : Settings pane.
Ajouter du Charm à votre appli Metro (Partie II) : Search Contract.  
Ajouter du Charm à votre appli Metro (Partie III) : Share Contract.
Ajouter du Charm à votre appli Metro(Partie IV) : File Open Picker Contract.

Les Contrats sont des types de Charm spéciaux. C’est une façon standard pour les applications de communiquer. Elles ne doivent plus se connaitre, il suffit juste d’intégrer un Contrat, et l’OS s’occupe de la communication entre les applications.

Il y a différents types de Contrats (Search, Share et Pick). Ce post parle du Search Contract.

J’ai créé une petite application, appelée POTUS qui permet de chercher les présidents US. La source est à la fin du post. Je vais l’utiliser comme exemple d’implémentation du search contract.

Ajouter le Search Contract

La manière la plus facile est d’ajouter un item Search Contract. Ajoutez un item à votre projet, et sélectionnez Search Contract.

VS va faire pas mal de plomberie pour vous (Regardez App.xaml.cs, vous verrez que la méthode OnSearchActivated est apparue) et à crée une page de résultat basique (SearchResultPage.xaml).

Il va aussi mettre à jour le manifeste de l’application, en rajoutant la déclaration Search :

La recherche

 

Quand vous tapez Enter dans le textbox du Search Pane, la méthode Activate de la page de résultat est appelée.

C’est dans cette méthode que vous faites votre recherche, suivant la requête de l’utilisateur et que vous afficherez les résultats. Il y a un paramètre SearchActivatedEventArgs qui contient la requête..

Exemple dans POTUS:

 public void Activate(SearchActivatedEventArgs args)
{
    var queryText = args.QueryText.ToLower();

    //Search the president list
    Results = ViewModelLocator.PresidentList.Where(d => d.FirstName.ToLower().Contains(queryText) || d.LastName.ToLower().Contains(queryText)).ToList();


    // Prepare bindable content
    var bindableProperties = new PropertySet();
    bindableProperties["QueryText"] = '"' + queryText + '"';
    bindableProperties["AllFilter"] = "All (" + Results.Count + ")";
    bindableProperties["Results"] = Results;
    this.DataContext = bindableProperties;

    // Display the results
    this.PreviousContent = Window.Current.Content;
    Window.Current.Content = this;
    Window.Current.Activate();
}

 

C’est tout! Le Contrat Search est implémenté.

Mais…On peut faire beaucoup plus.

Résultats en temps réel

Si vous voulez que votre page résultat soit mise à jour au fur et a mesure que l’utilisateur entre sa requête, vous devez vous registrer à l’évènement QueryChanged du search pane :

 _searchpane = SearchPane.GetForCurrentView();

 _searchpane.QueryChanged += new TypedEventHandler<SearchPane, SearchPaneQueryChangedEventArgs>(pane_QueryChanged);

Alors, dans votre méthode, vous faites juste votre recherché normalement et affichez les résultats. Quasiment comme dans la méthode Activate (La principale différence est qu’on ne met pas le focus sur la page résultat, car ça aurait pour effet de faire disparaitre le search pane)

 

void pane_QueryChanged(SearchPane sender, SearchPaneQueryChangedEventArgs args)
{
    var queryText = args.QueryText.ToLower();

    //Search the presidents list
    Results = ViewModelLocator.PresidentList.Where(d => d.FirstName.ToLower().Contains(queryText) || d.LastName.ToLower().Contains(queryText)).ToList();


    // Prepare bindable content
    var bindableProperties = new PropertySet();
    bindableProperties["QueryText"] = '"' + queryText + '"';
    bindableProperties["AllFilter"] = "All (" + Results.Count + ")";
    bindableProperties["Results"] = Results;
    this.DataContext = bindableProperties;

    // Display the results
    this.PreviousContent = Window.Current.Content;
    Window.Current.Content = this;
   
}

 

Les suggestions du Chef

Vous pouvez aussi ajouter quelque chose de sympa : les suggestions. Vous pouvez suggérer des mots à l’utilisateur comme celui-ci entre sa requête.

De nouveau, très simple. Se registrer à l’évènement SuggestionsRequested :

 _searchpane = SearchPane.GetForCurrentView();

_searchpane.SuggestionsRequested += new TypedEventHandler<SearchPane, SearchPaneSuggestionsRequestedEventArgs>(pane_SuggestionsRequested);

Dans la méthode, vous créez vos suggestions d’après la requêté, et vous les ajoutez à la collection SearchSuggestionCollection en utilisant AppendQuerySuggestions. Vous pouvez aussi ajouter un séparateur. Le Metro Design Guideline suggère (sans jeu de mots) de montrer un maximum de 10 suggestions.

void pane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
{
    var suggestions = ViewModelLocator.PresidentList.Where(d => d.LastName.ToLower().Contains(args.QueryText.ToLower())).Select(d => d.LastName).OrderBy(d => d).ToList().Take(5);

    args.Request.SearchSuggestionCollection.AppendSearchSeparator("Suggestions");

    args.Request.SearchSuggestionCollection.AppendQuerySuggestions(suggestions);
}

 

Résultat trouvé

Vous pouvez avoir un autre type de suggestion, plus avancé. Le Metro Design Guideline suggère de l’utiliser quand vous avez une correspondance exacte entre la requête et un élément. Avec un maximum de 5 de ces super-suggestions. Vous pouvez avoir une image, et deux lignes de textes. Le tout se passe dans la même méthode SuggestionRequested, vous les ajoutez aussi à la collection SearchSuggestionCollection mais cette fois avec AppendResultSuggestion.

Exemple in POTUS, avec suggestion et correspondance exacte :

void pane_SuggestionsRequested(SearchPane sender, SearchPaneSuggestionsRequestedEventArgs args)
{
    var suggestions = ViewModelLocator.PresidentList.Where(d => d.LastName.ToLower().Contains(args.QueryText.ToLower())).Select(d => d.LastName).OrderBy(d => d).ToList().Take(5);

    args.Request.SearchSuggestionCollection.AppendSearchSeparator("Suggestions");

    args.Request.SearchSuggestionCollection.AppendQuerySuggestions(suggestions);

    var exactmatches = ViewModelLocator.PresidentList.Where(d => d.LastName.ToLower() == args.QueryText.ToLower()).OrderBy(d => d.LastName).ToList().Take(5);

    foreach (var exactmatch in exactmatches)
    {
        var fullname = exactmatch.LastName + " " + exactmatch.FirstName;
        var terms = exactmatch.TermBeginString + "->" + exactmatch.TermEndString;
        args.Request.SearchSuggestionCollection.AppendResultSuggestion(fullname, terms, exactmatch.ID, StreamReference.CreateFromUri(new Uri("ms-appx:///Images/" + exactmatch.Picture)), "no image");
    }

}

 

Le troisième paramètre d’AppendResultSuggestion est un tag. Ce tag est utilisé lorsqu’un utilisateur sélectionne une correspondance exacte. Alors, un évènement ResultSuggestionChosen est déclenché. Vous pouvez vous registrer, et vous pouvez retrouver ce tag via les paramètres de votre méthode. Vous pouvez alors faire naviguer votre application directement sur cette information.

 void _searchpane_ResultSuggestionChosen(SearchPane sender, SearchPaneResultSuggestionChosenEventArgs args)
{
    var selectedpresident = ViewModelLocator.PresidentList.Where(d => d.ID == args.Tag).FirstOrDefault();

    if (selectedpresident == null)
        return;

    var queryText = selectedpresident.FirstName + " " + selectedpresident.LastName;

    // Prepare bindable content
    var bindableProperties = new PropertySet();
    bindableProperties["QueryText"] = '"' + queryText + '"';
    bindableProperties["AllFilter"] = "All (1)";
    bindableProperties["Results"] = new List<President>{selectedpresident};
    this.DataContext = bindableProperties;

    // Display the results
    this.PreviousContent = Window.Current.Content;
    Window.Current.Content = this;
    Window.Current.Activate();
}

Dans mon exemple, j’affiche juste la correspondance dans l’écran de recherche, parce que ce n’est qu’une petite appli de démo.

Conclusion

Comme vous voyez, très simple. Mais peut donner des résultats assez sympas !

Sources POTUS

Contrat suivant : Share

Comments powered by Disqus