Click here to Skip to main content
15,881,413 members
Articles / Programming Languages / C#

WinRT: Asynchronous Code in SearchPane.SuggestionsRequested

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
4 Mar 2014CPOL1 min read 12.3K   2  
WinRT: Asynchronous Code in SearchPane.SuggestionsRequested

As part of something a lot larger that I am currently working on, I wanted to implement the Search charm logic in Windows 8.

Now being the model citizen that I am, I have read all the good technical bumpg around Windows 8, and I paid particular attention to the fact that we really need to keep the UI free, as anything more than 30/300ms (can’t recall which) on a touch system just feels broken.

So what does that mean? Well, it means I have been a good chat and played nice and used Async/Await where needed. All good so far.

So now onto the Search charm. I obviously enabled this in the manifest file. Then I wrote the following code which I expected to work:

C#
sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        ....
        ....
        ....
        ....

        SetupSearch();
    }

    private async void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await SuspensionManager.SaveAsync();
        deferral.Complete();
    }

    private void SetupSearch()
    {
        var searchPane = SearchPane.GetForCurrentView();
        searchPane.SuggestionsRequested += searchPane_SuggestionsRequested;
        searchPane.ResultSuggestionChosen += searchPane_ResultSuggestionChosen;
    }

    void searchPane_ResultSuggestionChosen(SearchPane sender,
        SearchPaneResultSuggestionChosenEventArgs args)
    {
        MessageDialog dialog = new MessageDialog(string.Format("You picked {0}",args.Tag));
        dialog.ShowAsync();
    }

    async void searchPane_SuggestionsRequested(SearchPane sender,
        SearchPaneSuggestionsRequestedEventArgs args)
    {
        var suggestions = Enumerable.Range(1, 2).Select(x => new
        {
            Desc = string.Format("{0}_{1}", args.QueryText, x.ToString()),
            Id = x
        });

        //To simulate waiting on something more meaningful (such as a webservice etc etc)
        await Task.Delay(2000);

        var imageUri = new Uri("ms-appx:///Assets/search40.png");
        var imageSource = Windows.Storage.Streams.
              RandomAccessStreamReference.CreateFromUri(imageUri);
        args.Request.SearchSuggestionCollection.
              AppendSearchSeparator("Demo Suggestions");

        foreach (var suggestion in suggestions)
        {
            args.Request.SearchSuggestionCollection.AppendResultSuggestion(
                 "Suggestion",
              suggestion.Desc,
                suggestion.Id.ToString(),
                imageSource, "");
        }
    }
}

That looked fair enough to me. But when I ran this code, I got this Exception:

Most strange.

Turns out this is an issue for which there is a solution, that is just rather poorly documented. In fact, it borrows a lot from the jQuery Deferred pattern (which you can read more about here).

So what is the solution. Well, as I say WinRT has certainly borrowed from the jQuery Deferral / Promise idea. Where we ask for a Deferrable object, do some work, and then complete the Deferrable object.

So here is the code above refactored to use a WinRT Deferrable object. This technique can be used with most of the charms.

C#
sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    protected override async void OnLaunched(LaunchActivatedEventArgs args)
    {
        ....
        ....
        ....
        ....

        SetupSearch();
    }

    private async void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        await SuspensionManager.SaveAsync();
        deferral.Complete();
    }

    private void SetupSearch()
    {
        var searchPane = SearchPane.GetForCurrentView();
        searchPane.SuggestionsRequested += searchPane_SuggestionsRequested;
        searchPane.ResultSuggestionChosen += searchPane_ResultSuggestionChosen;
    }

    void searchPane_ResultSuggestionChosen(SearchPane sender,
        SearchPaneResultSuggestionChosenEventArgs args)
    {
        MessageDialog dialog = new MessageDialog(string.Format("You picked {0}",args.Tag));
        dialog.ShowAsync();
    }

    async void searchPane_SuggestionsRequested(SearchPane sender,
        SearchPaneSuggestionsRequestedEventArgs args)
    {
        var suggestions = Enumerable.Range(1, 2).Select(x => new
        {
            Desc = string.Format("{0}_{1}", args.QueryText, x.ToString()),
            Id = x
        });

        //FIXED CODE : Use args.Request.GetDeferral() / deferral.Complete

        var deferral = args.Request.GetDeferral();

        await Task.Delay(2000);

        var imageUri = new Uri("ms-appx:///Assets/search40.png");
        var imageSource = Windows.Storage.Streams.
                RandomAccessStreamReference.CreateFromUri(imageUri);
        args.Request.SearchSuggestionCollection.
                AppendSearchSeparator("Demo Suggestions");

        foreach (var suggestion in suggestions)
        {
            args.Request.SearchSuggestionCollection.AppendResultSuggestion(
                "Suggestion",
                suggestion.Desc,
                suggestion.Id.ToString(),
                imageSource, "");
        }

        deferral.Complete();
    }

}

As always, here is a small demo project (requires Windows 8 / Visual Studio 2012) : AsyncSearchSuggestionDemo.zip


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
-- There are no messages in this forum --