Professional, Software

Part 2: Live Search using Silverlight (Live Search Call and Progress)

In Part 2, I wanted to add support for communicating with Live Search APIs. These APIs are allowed to be called cross domain. The way I made sure is http://soap.search.live.com/crossdomain.xml. Here is the link to documentation of this APIs.

Getting basic service integrated is very straight forward, thanks to VS integration for web services. Right Click on References and clicked on “Add Service Reference”. It adds all the necessary client wrappers that let you call web service like any other objects in your app. I set the namespace to be SearchService so all these wrapper classes are available in Search.SearchService, Search being the root namespace for the application.

Code for talking to webservice looks something like this….

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Windows;
   5: using System.Windows.Controls;
   6: using System.Windows.Documents;
   7: using System.Windows.Input;
   8: using System.Windows.Media;
   9: using System.Windows.Media.Animation;
  10: using System.Windows.Shapes;
  11: using Search.SearchService;
  12: using System.Collections.ObjectModel;
  13: using System.ServiceModel;
  14: using System.Net;
  15: using System.Xml;
  16: using System.IO;
  17:  
  18: namespace Search
  19: {
  20:     public class SearchResultCollection : ObservableCollection<SearchService.Result>
  21:     {
  22:     }
  23:  
  24:     public partial class Page : UserControl
  25:     {
  26:         private Storyboard _progress;
  27:         private SearchResultCollection _imagesearchresultcollection;
  28:         Result[] _imageresults;
  29:         Boolean _searchcompleted;
  30:  
  31:  
  32:         public Page()
  33:         {
  34:             InitializeComponent();
  35:             _progress = LayoutRoot.FindName("SearchProgressAnimation") as Storyboard;
  36:             _progress.Completed += new EventHandler(_progress_Completed);
  37:         }
  38:  
  39:         void _progress_Completed(object sender, EventArgs e)
  40:         {
  41:             if (_searchcompleted == true)
  42:             {
  43:                 _progress.Stop();
  44:             }
  45:             else
  46:             {
  47:                 _progress.Begin();
  48:             }
  49:         }
  50:  
  51:         private void Button_Click(object sender, RoutedEventArgs e)
  52:         {
  53:             _searchcompleted = false;
  54:             _progress.Begin();
  55:             GetLiveData();
  56:         }
  57:  
  58:  
  59:  
  60:         private void GetLiveData()
  61:         {
  62:             try
  63:             {
  64:                 //Initialize web service
  65:                 string searchquery = txtSearch.Text;
  66:                 BasicHttpBinding binding = new BasicHttpBinding();
  67:                 EndpointAddress address = new EndpointAddress("http://soap.search.msn.com/webservices.asmx");
  68:                 MSNSearchPortTypeClient searchservice = new MSNSearchPortTypeClient(binding, address);
  69:                 SearchRequest searchrequest = new SearchRequest();
  70:                 SourceRequest[] sr = new SourceRequest[3];
  71:  
  72:                 sr[0] = new SourceRequest();
  73:                 sr[0].Source = SourceType.Image;
  74:                 sr[0].ResultFields = ResultFieldMask.Url | ResultFieldMask.Title | ResultFieldMask.Description | ResultFieldMask.Image;
  75:                 sr[0].Count = 50;
  76:  
  77:                 searchrequest.Query = searchquery;
  78:                 searchrequest.Requests = sr;
  79:                 searchrequest.AppID = "Enter your key here";
  80:                 searchrequest.CultureInfo = "en-US";
  81:                 searchservice.SearchCompleted += new EventHandler<Search.SearchService.SearchCompletedEventArgs>(searchservice_SearchCompleted);
  82:                 searchservice.SearchAsync(searchrequest);
  83:             }
  84:             catch (WebException webx)
  85:             {
  86:                 txtSearch.Text = webx.ToString();
  87:                 _searchcompleted = true;
  88:             }
  89:         }
  90:  
  91:         void searchservice_SearchCompleted(object sender, Search.SearchService.SearchCompletedEventArgs e)
  92:         {
  93:             if (e.Error != null)
  94:                 txtSearch.Text = e.Error.Message;
  95:             else
  96:             {
  97:                 _imagesearchresultcollection = new SearchResultCollection();
  98:                 _imageresults = e.Result.Responses[0].Results;
  99:                 for (int counter = 0; counter < _imageresults.Length; counter++)
 100:                 {
 101:                     if (_imageresults[counter].Image.ImageURL.Contains("jpg") || _imageresults[counter].Image.ImageURL.Contains("png"))
 102:                         _imagesearchresultcollection.Add(_imageresults[counter]);
 103:                 }
 104:             }
 105:             _searchcompleted = true;
 106:         }
 107:     }
 108: }

To add the progress UI, I was thinking of writing a control but then I changed my mind and I thought it would look much cooler if the brush that is background for the page can be animated (it looks like a focus so when it animates, it looks sort of like somebody is looking with a flashlight.

I have used Blend to do everything here.

<Storyboard x:Name="SearchProgressAnimation" RepeatBehavior="1x">
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" 
                                   Storyboard.TargetProperty="(Panel.Background).

(Brush.RelativeTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"

BeginTime="00:00:00"> <SplineDoubleKeyFrame KeyTime="00:00:01" Value="90.145"/> <SplineDoubleKeyFrame KeyTime="00:00:02" Value="180.143"/> <SplineDoubleKeyFrame KeyTime="00:00:03" Value="270.128"/> <SplineDoubleKeyFrame KeyTime="00:00:04" Value="359.946"/> </DoubleAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).
(LinearGradientBrush.StartPoint)"
BeginTime="00:00:00"> <SplinePointKeyFrame KeyTime="00:00:01" Value="0.716000020503998,0.439000010490417"/> <SplinePointKeyFrame KeyTime="00:00:02" Value="0.382999986410141,0.684000015258789"/> <SplinePointKeyFrame KeyTime="00:00:03" Value="0.0759999975562096,0.231000006198883"/> <SplinePointKeyFrame KeyTime="00:00:04" Value="0.726000010967255,0.395999997854233"/> </PointAnimationUsingKeyFrames> <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Shape.Fill).
(LinearGradientBrush.EndPoint)"
BeginTime="00:00:00"> <SplinePointKeyFrame KeyTime="00:00:01" Value="0.0769999995827675,0.228000000119209"/> <SplinePointKeyFrame KeyTime="00:00:02" Value="0.409999996423721,-0.017000000923872"/> <SplinePointKeyFrame KeyTime="00:00:03" Value="0.717000007629395,0.435999989509583"/> <SplinePointKeyFrame KeyTime="00:00:04" Value="0.0670000016689301,0.270999997854233"/> </PointAnimationUsingKeyFrames> </Storyboard>

Only thing I do to run this storyboard is in Button Click event, before I make a call to webservice, I start the storyboard and when call returns (or throws exception), I stop the animation. One problem I hit was I needed to run the animation atleast once otherwise when service call returns, it looks really choppy. I am not sure if there is a better way to do this but the way I ended up doing it was I kept the animation 1x and then I keep on running it till service API returns.

   1: void _progress_Completed(object sender, EventArgs e)
   2: {
   3:     if (_searchcompleted == true)
   4:     {
   5:         _progress.Stop();
   6:     }
   7:     else
   8:     {
   9:         _progress.Begin();
  10:     }
  11: }

Here is the link to working project.

Standard

8 thoughts on “Part 2: Live Search using Silverlight (Live Search Call and Progress)

  1. Pingback: Chris Love's Official Blog - Professional ASP.NET : Links of the Week

  2. Pingback: Wrapper Counters and the rest of the world » Blog Archive » What others have been saying about wrapper counter

  3. Pingback: Wrapper Counters and the rest of the world » Blog Archive » Quick Roundup

  4. Pingback: Wrapper Counters and the rest of the world » Blog Archive » Quick scan of the net - wrapper counter

  5. Pingback: Wrapper Counters and the rest of the world » Blog Archive » ‘wrapper counter’ on the web

  6. Hey there.. thanks for this, I was just trying to write something similar. However, I get the same thing with your code as mine… I’m everything runs, but not results come back in the e.results… any ideas?

  7. This design is spectacular! You definitely know how to
    keep a reader entertained. Between your wit and your videos, I was almost moved to
    start my own blog (well, almost…HaHa!) Fantastic job.
    I really loved what you had to say, and more than that, how you presented it.

    Too cool!

Leave a comment