Einführung
In meinen vorherigen Blog-Beiträgen (Microsoft Bing Maps for Enterprise, BingMaps GeocodeService und BingMaps RouteService) zu dem Thema BingMaps, habe ich über die Darstellung von Punkten oder Routen auf einer BingMaps-Karte gesprochen. Im Gegensatz zu dem ersten Blog-Beitrag wurde bei den anderen die Webservices “GeocodeService” und “RouteService” mit eingebunden, die sich über die Webservices die Koordinaten der gesuchten Orte/Punkte holen bzw. die Route dazwischen berechnen.
Microsoft bietet aber 3 verschiedene WebServices für die Darstellung von Punkten, Linien oder Bereichen auf Karten an. Diese wären:
- GeocodeService (Punkte)
- RouteService (Punkte, Linien)
- SearchService (Punkte)
In diesem Blog Beitrag möchte ich die Verwendung des SearchService in BingMaps erläutern.
Wozu verwende ich den SearchService?
Mit Hilfe des SearchService wird eine Abfrage an den Webservice gestellt, der die Koordinaten (Längen- und Breitengrad im Format WGS84) der Adressen für einen bestimmten Suchbegriff (z.B. Pizza in Frankfurt) zurückliefert. Als Ergebnis erhält man eine Liste von Pizzerien in Frankfurt.
Der SearchService bietet sich besonders an, wenn man einen bestimmten Ort (z.B. die nächstgelegene Postfiliale) in seiner Nähe sucht.
Voraussetzungen
- BingMaps-Key
- Visual Studio
- Silverlight
Falls Sie noch keinen BingMaps-Key haben, können Sie sich hier einen erstellen.
Silverlight-Applikation
Als erster Schritt wird eine neue Silverlight-Applikation erstellt und der SearchService als Service Reference hinzugefügt. Hierzu klicken Sie mit der rechten Maustaste auf das Projekt und wählen Add Service Reference. Geben Sie als Adresse http://dev.virtualearth.net/webservices/v1/SearchService/SearchService.svc ein und klicken auf Go. Nennen Sie den Namespace SearchService.
Im nächsten Schritt werden eine Textbox zum Eingeben der Suchparameter und ein Button zum Starten der Suche erstellt. Des Weiteren erstellen wir noch einen Textblock in dem wir ausgeben, wie viele Treffer gefunden wurden und eine Karte zum Darstellen der Suchergebnisse.
1: <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
2: <Grid.RowDefinitions>
3: <RowDefinition Height="auto"/>
4: <RowDefinition Height="*"/>
5: </Grid.RowDefinitions>
6: <StackPanel Grid.Row="0">
7: <TextBlock TextWrapping="Wrap"/>
8: <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="12,0,12,0">
9: <TextBox x:Name="strParameter" Width="500" KeyDown="strParameter_KeyDown" GotFocus="strParameter_GotFocus" HorizontalAlignment="Stretch"/>
10: <Button Content="Suchen" Click="Button_Click"/>
11: <TextBlock x:Name="outResults" Margin="14,0,0,0" VerticalAlignment="Center"/>
12: </StackPanel>
13: </StackPanel>
14: <map:Map Name="searchMap" CredentialsProvider="<Your Key>" Grid.Row="1">
15: <map:MapLayer x:Name="SearchResultLayer"/>
16: <map:MapLayer x:Name="ContentTooltipLayer">
17: <Canvas x:Name="ContentTooltip" Visibility="Collapsed" Opacity=".85" MouseEnter="ContentPopup_MouseEnter" MouseLeave="ContentPopup_MouseLeave">
18: <Rectangle x:Name="ContentTooltipRectangle" Fill="White" Canvas.Left="0" Height="100" Width="300" RadiusX="20" RadiusY="20"/>
19: <StackPanel Canvas.Left="10" Canvas.Top="10">
20: <TextBlock x:Name="ContentTooltipText"/>
21: <TextBlock x:Name="ContentTooltipDescription"/>
22: </StackPanel>
23: </Canvas>
24: </map:MapLayer>
25: </map:Map>
26: </Grid>
In den nächsten beiden Methoden (ExecuteSearch und searchClient_searchCompleted) übergeben wir den Suchbegriff aus unserer Textbox an den Webservice. Dieser gibt eine Liste von Suchergebnissen zurück.
1: private void ExecuteSearch(string query)
2: {
3: //Set up the search request
4: SearchService.SearchServiceClient searchClient;
5:
6: // OutOfBrowser is currently supported on the MapControl only for http pages
7: bool httpsUriScheme = !Application.Current.IsRunningOutOfBrowser && HtmlPage.Document.DocumentUri.Scheme.Equals(Uri.UriSchemeHttps);
8: BasicHttpBinding binding = new BasicHttpBinding(httpsUriScheme ? BasicHttpSecurityMode.Transport : BasicHttpSecurityMode.None);
9: binding.MaxReceivedMessageSize = int.MaxValue;
10: binding.MaxBufferSize = int.MaxValue;
11: UriBuilder serviceUri = new UriBuilder("http://dev.virtualearth.net/webservices/v1/SearchService/SearchService.svc");
12: if (httpsUriScheme)
13: {
14: //For https, change the UriScheme to https and change it to use the default https port.
15: serviceUri.Scheme = Uri.UriSchemeHttps;
16: serviceUri.Port = -1;
17: }
18:
19: //Create the Service Client
20: searchClient = new SearchService.SearchServiceClient(binding, new EndpointAddress(serviceUri.Uri));
21: searchClient.SearchCompleted += new EventHandler<SearchService.SearchCompletedEventArgs>(searchClient_SearchCompleted);
22:
23: var request = new SearchService.SearchRequest
24: {
25: Culture = searchMap.Culture,
26: Query = query,
27: ExecutionOptions = new SearchService.ExecutionOptions { SuppressFaults = true }
28: };
29:
30: //Set up the Map View bounds for the request
31: LocationRect mapControlView = searchMap.BoundingRectangle;
32:
33: LocationRect mapBounds = new LocationRect(mapControlView);
34: request.UserProfile = new SearchService.UserProfile();
35: request.UserProfile.MapView = mapBounds;
36:
37: searchMap.CredentialsProvider.GetCredentials(
38: (Credentials credentials) =>
39: {
40: //Pass in credentials for web services call. Replace with your own Credentials.
41: request.Credentials = credentials;
42:
43: //execute the request
44: searchClient.SearchAsync(request);
45: });
46: }
1: private void searchClient_SearchCompleted(object sender, SearchService.SearchCompletedEventArgs e)
2: {
3: string outputString;
4: try
5: {
6: if (e.Result.ResponseSummary.StatusCode == SearchService.ResponseStatusCode.Success)
7: {
8: outputString = string.Format(CultureInfo.InvariantCulture, "{0} Treffer", e.Result.ResultSets[0].Results.Count);
9: IList<Location> locations = new List<Location>();
10:
11: if ((e.Result != null) && (e.Result.ResultSets.Count > 0))
12: {
13: foreach (SearchService.SearchResultBase result in e.Result.ResultSets[0].Results)
14: {
15: searchResults.Add(result.Id, result);
16:
17: if (result.LocationData.Locations.Count > 0)
18: {
19: Location location = new Location(result.LocationData.Locations[0]);
20: //Create a pushpin
21: var pushpin = new Pushpin
22: {
23: Location = location,
24: Tag = result.Id
25: };
26:
27: SearchResultLayer.Children.Add(pushpin);
28: locations.Add(location);
29:
30: //Set up events for the pushpin
31: pushpin.MouseEnter += new MouseEventHandler(Pushpin_MouseEnter);
32: pushpin.MouseLeave += new MouseEventHandler(Pushpin_MouseLeave);
33:
34: }
35: }
36:
37: if (locations.Count > 0)
38: {
39: //If Search results were found, use the bounding area of the results
40: searchMap.SetView(new LocationRect(locations));
41: }
42: else
43: {
44: //Otherwise, if the SearchRegion is set from the service response, go ahead use that
45: LocationRect boundingArea = e.Result.ResultSets[0].SearchRegion.BoundingArea as LocationRect;
46: if (boundingArea != null)
47: {
48: searchMap.SetView(new LocationRect(boundingArea));
49: }
50: }
51: }
52: }
53: else
54: {
55: outputString = "error searching... status <" + e.Result.ResponseSummary.StatusCode.ToString() + ">";
56: }
57: }
58: catch (Exception)
59: {
60: outputString = "Exception Raised";
61: }
62:
63: outResults.Text = outputString;
64: }
Damit wir auch wissen um wen es sich bei den Suchergebnissen handelt, erstellen wir noch zwei Events, die ausgeführt werden, wenn man einen Punkt mit der Maus berührt (Pushpin_MouseEnter) und wieder verlässt (Pushpin_MouseLeave). Beim Berühren eines Punktes mit der Maus sollen Informationen wie Name, Adresse und Telefonnummer in der Box angezeigt werden.
1: void Pushpin_MouseLeave(object sender, MouseEventArgs e)
2: {
3: //Hide the popup
4: UIElement content = sender as UIElement;
5: Canvas.SetZIndex(content, 100);
6: ContentTooltip.Visibility = Visibility.Collapsed;
7: }
8:
9: void Pushpin_MouseEnter(object sender, MouseEventArgs e)
10: {
11: //Show the popup
12: Pushpin pushpin = sender as Pushpin;
13: Canvas.SetZIndex(pushpin, 500);
14: Point point = e.GetPosition(searchMap);
15: string resultId = pushpin.Tag as string;
16: SearchService.SearchResultBase searchResult = searchResults[resultId];
17: Location location = new Location(searchResult.LocationData.Locations[0].Latitude, searchResult.LocationData.Locations[0].Longitude);
18: MapLayer.SetPosition(ContentTooltip, location);
19: MapLayer.SetPositionOffset(ContentTooltip, new Point(25, -50));
20:
21: SearchService.SearchResultBase result = searchResults[resultId];
22: if (result != null)
23: {
24: ContentTooltipText.Text = result.Name;
25: SearchService.BusinessSearchResult businessResult = result as SearchService.BusinessSearchResult;
26: if (businessResult != null)
27: {
28: ContentTooltipDescription.Text = string.Format("{0} {1} ", businessResult.Address.FormattedAddress, businessResult.PhoneNumber);
29: }
30: ContentTooltip.Visibility = Visibility.Visible;
31: }
32: }
33:
34: private void ContentPopup_MouseEnter(object sender, MouseEventArgs e)
35: {
36: //Show the popup if mouse is hovering over it
37: ContentTooltip.Visibility = Visibility.Visible;
38: Canvas.SetZIndex(ContentTooltip, 10);
39: }
40:
41: private void ContentPopup_MouseLeave(object sender, MouseEventArgs e)
42: {
43: //Hide the popup if mouse leaves it
44: ContentTooltip.Visibility = Visibility.Collapsed;
45: }
Zum Schluss müssen wir noch eine Methode zum Ausführen der Suche erstellen, die ausgeführt wird, wenn der Button gedrückt wird.
1: private void strParameter_KeyDown(object sender, KeyEventArgs e)
2: {
3: if (e.Key == Key.Enter)
4: {
5: StartSearch();
6: }
7: }
8:
9: private void strParameter_GotFocus(object sender, RoutedEventArgs e)
10: {
11: strParameter.SelectAll();
12: }
13:
14: private void Button_Click(object sender, RoutedEventArgs e)
15: {
16: StartSearch();
17: }
18:
19: private void StartSearch()
20: {
21: ClearSearch();
22:
23: searchMap.Focus();
24:
25: string query = strParameter.Text;
26: if (!string.IsNullOrEmpty(query))
27: {
28: ExecuteSearch(query);
29: }
30: }
31:
32: private void ClearSearch()
33: {
34: foreach (UIElement pin in SearchResultLayer.Children)
35: {
36: pin.MouseEnter -= Pushpin_MouseEnter;
37: pin.MouseLeave -= Pushpin_MouseLeave;
38: }
39:
40: SearchResultLayer.Children.Clear();
41: searchResults.Clear();
42: }
Ergebnis
Starten Sie nun die Solution und geben einen Suchbegriff ein. Klicken Sie anschließend auf Suchen um den SearchService anzusprechen.
Gesamtfazit
Abschließend kann man sagen, dass die unterschiedlichen Services (GeocodeService, RouteService und SearchService), die ich in dieser BlogSerie beschrieben habe, eine gute Ergänzung für die Entwicklung von BingMaps-Applikation sind.
Durch das frei verfügbare Bing Maps Silverlight Control SDK und Bing Maps Silverlight Control Interactive SDK werden dem Entwickler hilfreiche Tipps und Beispiele zur Verfügung gestellt.
BingMaps bietet mit den Services Unternehmen in den unterschiedlichsten Branchen eine gute Möglichkeit seine Daten geovisualisiert darzustellen. Durch die Sicht auf die geographische Lage können die Daten auf eine weitere Art analysiert werden.
Insbesondere der GeocodeService bietet dem Unternehmen eine gute Hilfe für die geovisualisierte Analyse seiner Daten.
Sie sehen gerade einen Platzhalterinhalt von Facebook. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr InformationenSie sehen gerade einen Platzhalterinhalt von Instagram. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr InformationenSie sehen gerade einen Platzhalterinhalt von X. Um auf den eigentlichen Inhalt zuzugreifen, klicken Sie auf die Schaltfläche unten. Bitte beachten Sie, dass dabei Daten an Drittanbieter weitergegeben werden.
Mehr Informationen