WP7 Contrib – Bing Maps Rest API Wrapper Part III Search

In the previous post we looked at how you can incorporate the Calculate Route service into your WP7 app, using bolier plate Rx code and a simple pattern.

Next up is Search and how to search an area of the map control programmatically. For example, there is a great deal of data out there and a lot of this can be mapped down to a Geo Coordinate, therefore it’s a great opportunity for us to provide richer experiences that layer this information onto a map allowing users to see what is near to them. A simple and effective way to do this is by using the Bing API. Just to be clear, what I am referring to is recreating the same experience that you have on WP7 when you select the search button on your handset. However we can now incorporate this directly into your application so that users don’t have to leave the experience just to use search via a map.

Now, strictly speaking the ability for you to search in a particular bounding rectangle on a map is not part of the Rest API it is in fact part of the Bing API V2 . However, in an attempt to help reduce complexity and provide a simple and consistent implementation approach we have decided for the time being, that it should live with the other API calls that we make. At this moment in time we only support search via a map and so this also feels like the right place for it to live as all the bits also are map specific services.

This is rather important, you will need to generate another key if you want to use this Bing service.

Using this service is exactly the same as the other services that we have discussed so far, and hopefully the code is starting to look more familiar. Just like the Location, Route and Imagery services we follow the same pattern; we need some types; we need a factory to build the request criterion; and we need a service method that takes the generated criterion as a parameter to be implemented using boiler plate Rx code, as seen previously. You can use the users location and then you can rock from here, or you can use the postcode; pass this to the location service which will return you a Geo Coordinate; pass this Geo Coordinate along with the bounding rectangle of the map, the Bing service will then search only within this bounding rectangle for your search term.

The search service in the sample has a UI consisting of; a map control to display results; a textbox to enter search keywords; and a button to initiate the search. The button is wired up to a command which is responsible for making the request.

The code below uses the Criterion Factory to help us build the criterion that we need to pass to the API in this particular case we call the Create Search For Services and pass it the bounding rectangle that we want the search to happen in. Once the factory has created the criterion we use the boiler plate Rx code to make the service call.

private void ExecuteBingSearchCommand()
{
    try
    {
        this.SearchResult = null;
        var criterion = CriterionFactory.CreateSearchForServices(
                new LocationRect(this.CurrentDeviceGeoCoordinate, 5, 5),
                this.SearchQuery,
                CultureInfo.CurrentCulture);

        this.bingMapsService.SearchForServices(criterion)
            .ObserveOnDispatcher()
            .Subscribe(this.ProcessBingSearchResponse, FailedSearch, CompletedSearch);
    }
    catch (Exception exn)
    {
        MessageBox.Show(string.Format("Failed! Message - '{0}", exn.Message),
         "Services Search", MessageBoxButton.OK);
    }
}

The code required to process the response.

private void ProcessBingSearchResponse(SearchResult result)
{
    if (result == null)
    {
        return;
    }

    this.SearchResult = result;
}

Again as with the other services, the root object that you need to be aware of is called the Search Result. The Xaml below show you how to plot these search results on to the map control. Here I am using the MapItemsControl and databinding its Items Source to the collection of Results that comes back from the request. For completeness I have also included the Data template that is being used to plot the map push pin.

<DataTemplate x:Key="MapPinPhoneBookDataTemplate">
    <Microsoft_Phone_Controls_Maps:Pushpin Location="{Binding Path=Location}">
        <Microsoft_Phone_Controls_Maps:Pushpin.Content>
            <Grid HorizontalAlignment="Left">
                <Border>
                    <TextBlock Text="{Binding Business}" />
                </Border>
            </Grid>
        </Microsoft_Phone_Controls_Maps:Pushpin.Content>
    </Microsoft_Phone_Controls_Maps:Pushpin>
</DataTemplate>

<Microsoft_Phone_Controls_Maps:Map x:Name="searchresultsnearbymap"
        ZoomLevel="{Binding ZoomLevel, Mode=TwoWay}"
        Center="{Binding CurrentMapSearchCenterPoint, Mode=TwoWay}"
        ZoomBarVisibility="Collapsed"
        CopyrightVisibility="Visible"
        AnimationLevel="UserInput"
        HorizontalContentAlignment="Stretch"
        VerticalContentAlignment="Stretch"
        Grid.RowSpan="2"
        Background="{StaticResource SemiOpaqueDarkBackBrush}"
        d:LayoutOverrides="GridBox"
        Grid.Row="1">

    <Microsoft_Phone_Controls_Maps:MapItemsControl x:Name="ResultsList"
        ItemTemplate="{StaticResource MapPinPhoneBookDataTemplate}"
        ItemsSource="{Binding SearchResult.Results}" />
</Microsoft_Phone_Controls_Maps:Map>

Next up is the Imagery service and this completes the lap of the WP7C Bing Wrappers.

Enjoy!

Be Sociable, Share!

Tags:


Leave a Reply