Click here to Skip to main content
15,879,474 members
Articles / Web Development / HTML

Google Maps in WPF with WebBrowser and Google Maps API v3

Rate me:
Please Sign up or sign in to vote.
4.69/5 (15 votes)
13 Mar 2017CPOL5 min read 125.2K   13.3K   51   23
You can show a map in your WPF application with the Google Maps API v3.

Introduction

Google provides a JavaScript API for include maps with the same functions of maps.google.com in an HTML page.

The page where Google explains this API is here.

On the version v2, you need to register to obtain an API key for using the library, with the version v3 it's optional but it's recommended because the API has a limitation, you can only generate 25,000 maps per day, if you need more you need to pay so you need register and if you register you can:

  • Obtain statistics of the maps generated per day
  • Pay for additional maps (more than 25,000 per day)
  • Restrict the use of your key to prevent use on unauthorized sites

To create your API key, visit the APIs Console and log in with your Google Account.

Background

The most basic example is the next:

HTML
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" 
src="http://maps.google.com.mx/maps/api/js?sensor=true&language=es"></script>
<script src='http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js'>
</script><script type="text/javascript">
  function initialize() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
      zoom: 8,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  }

</script>
</head>
<body onload="initialize()">
  <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>  

With the first line, you enables the HTML local file to fully test their compatibility with users' security settings.

You need 5 elements:

  1. The label <meta> specifies that the map should show in full screen and the user can't modify the size.
    HTML
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> 
  2. The apis of Google:
    HTML
    <script src='http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js'></script>   
    <script type="text/javascript" 
    src="http://maps.google.com.mx/maps/api/js?sensor=true&language=es&key=your_key"></script> 

    For this example, I use a marker Cluster, with this marker you can display a large number of locations or markers for example 300 markers and the markers are grouped by zones.

    The second script is the script for Google maps, the parameter sensor = true indicates that the application uses a sensor to indentify the location of the user. The parameter of the language specifies the language for the instructions. And in the parameter of the key, you should include your API.

  3. You need include a location for including the map. Generally it is a div. In this example, the size of the map is the size of the page.

     

    HTML
    <div id="map_canvas" style="width:100%; height:100%"></div>  
  4. The function for initializing and showing the map:
    1. For ubicate a map, you need the latitude and the longitude for the place that you want to show
    2. The options for the map, like the zoom, the map type:
      • ROADMAP displays the default map of Google Maps
      • SATELLITE displays the photographic map
      • HYBRID displays a mix of photographic and default map
      • TERRAIN displays physical relief tiles for displaying elevation and water features (mountains, rivers, etc.)
  5. For guaranteeing that the map shows after the page is created and shows correctly, you need load the map in the event load of the page.
    HTML
    <body onload="initialize()">   

If the map doesn't show maybe the latitude and the longitude, it's a location in the sea or you could have a JavaScript error.

You can personalize a lot of things of the map, the style of the map, put a marker and an information window for the marker, the directions between 2 points by bicycle, auto, walk, the traffic.

For adding a marker, you can include the following code:

JavaScript
 function addMarker( Lat, Long)
{   
   var latLng = new google.maps.LatLng(Lat, Long);            
   marker = new google.maps.Marker({
      position:   latLng,
      icon:       'down2.png',
      draggable:  true,
      animation:  google.maps.Animation.DROP,
      title:"Click for show the data of the client"
  });
   markers.push(marker);
   marker.setMap(map);
 }

 //add the Drag end event to send the dragEvent to cs
  google.maps.event.addListener(marker, 'dragend', function()
  {
       eventEndDragMarker(marker)
  });
 function eventEndDragMarker(shape)
  {
    var pos = new google.maps.LatLng;
    pos = shape.getPosition();
    endDragMarkerCS(pos.lat(), pos.lng());
  }

You can specify an image for the marker, the animation, and the text that shows when the mouse is over the image. The option draggable : true means that the user can move the marker to another location.

Next, I add a Listener for the marker to notify when the user end Drag the marker. With this event, I sent the new position to WPF Application.

For adding an info window that shows a text and images for the marker, you can include the following code:

JavaScript
 var contentString = '<div id="content">'+
                       '<h1>[Client]</h1>'+
                       '<img src="/images/image.jpg width="200" 
                       height="200" style="margin: 0 auto; display:block"/>'+
                       '<br/><br/>[Direction]'+            
                     '</div>';
 var infowindow = new google.maps.InfoWindow({
        content: contentString
});

You can view the live example here.

You can show the directions between 2 points, for this you need the <div> for the map and optionally, you can include a <div> for the directions. The JavaScript function is:

JavaScript
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var origin = new google.maps.LatLng(37.7699298, -122.4469157);
var destination = new google.maps.LatLng(37.7683909618184, -122.51089453697205);

function initialize() {
  directionsDisplay = new google.maps.DirectionsRenderer();
  var myOptions = {
    zoom: 5,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    center: origin
  }
  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  directionsDisplay.setMap(map);
  calcRoute();
  directionsDisplay.setPanel(document.getElementById("directionsPanel"));
}

function calcRoute() {
  var selectedMode = document.getElementById("mode").value;
  var request = {
      origin: origen,
      destination: destino,
      travelMode: google.maps.TravelMode[selectedMode]
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      directionsDisplay.setDirections(response);
    }
  });
}

You can view the live example here.

For including the map on WPF, I use a WebBrowser Control, and I load an HTML file that I previously create, and I read the file and replace the latitudes and longitudes, and the text for the info Window.

The application of the demo shows the data of a client, the location of the client on the map, and other option to show the directions for arriving at the location of the client from the location of the company.

In the demo, I use a DockPanel to automatically resize the map when the windows changes the size. I read the HTML page and find and replace the text like latLng and origin and destination from the example. I set a short Uri because with long path, the WPF shows an error.

C#
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "html\\map.html"))
{
     StreamReader objReader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "html\\map.html");
     string line = "";
     line = objReader.ReadToEnd();
     objReader.Close();
     line = line.Replace("[Location]", tbLocation.Text);
     line = line.Replace("[Client]", "25.520581,-105.40607");
     line = line.Replace("[Image]", "client" + tbID.Text + ".png");
     line = line.Replace("[Direction]", tbDirection.Text + 
     "<br />" + tbCity.Text + "," + tbState.Text);
     StreamWriter page = File.CreateText(AppDomain.CurrentDomain.BaseDirectory + "html\\map2.html");
     page.Write(line);
     page.Close();
     Uri uri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "html\\map2.html");
     webBrowser1.Navigate(uri);
}

Call a JavaScript Function from WPF Application

With the WPF Browser, you can invoke a JavaScript function in your HTML. Here is an example. You can pass parameter to a function in an array of objects.

C#
   private void Button_Click_1(object sender, RoutedEventArgs e)<br />        {
            webBrowser1.InvokeScript("addMarker", new Object[] { 25.520581, -103.40607);          
}  

Call a WPF Function from JavaScript

With the instruction windows.external you can invoke a WPF function from JavaScript, you need create a class with a COMVisibleAttribute to true and add the Object to the WPFBrowser.

Here is an example in the HTML JavaScript:

JavaScript
function endDragMarkerCS(lat, long)  {
     window.external.endDragMarkerCS( lat, long);
  } 

In the WPF application:

C#
 <WebBrowser DockPanel.Dock="Right" 
Loaded="setupObjectForScripting" Name="webBrowser1" />
 private void setupObjectForScripting(object sender, RoutedEventArgs e)
        {
         ((WebBrowser)sender).ObjectForScripting = new HtmlInteropInternalTestClass(); 
        } 
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class HtmlInteropInternalTestClass
{
public void endDragMarkerCS(Decimal Lat, Decimal Lng)
{ ((MainWindow)Application.Current.MainWindow).tbLocation.Text = Math.Round(Lat,5) + "," +Math.Round(Lng,5);            
 }
 } 

Points of Interest

With the new API V3 of Google maps and a WebBrowser on .NET, you can Add Maps in your applications. The API provides a lot of configuration and with CSS, you can add more design to the maps for integrating in your WPF or Winforms applications. I prefer WPF because I'm learning WPF but it's similar on Winforms.

You can save the data of Latitude and Longitude of your clients in your database and it will be useful to add a map to location, a project of building or for sending articles to your clients.

Also, if you want, you can use the Bing Maps WPF Control with this component you can add the markers with .NET code without JavaScript and HTML page.

License

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


Written By
Software Developer armheSistemas
Mexico Mexico
I'm a software developer. I like to develop web pages and desktop systems. I'm learning unity, xamarin, swift, android, security, UX

Comments and Discussions

 
Questiondirection is not work Pin
alihim1-Jan-21 6:38
alihim1-Jan-21 6:38 
QuestionBug in Getting Directions Pin
PellucidWombat4-Nov-17 19:59
PellucidWombat4-Nov-17 19:59 
GeneralMy vote of 5 Pin
Member 45164529-Jul-17 22:59
Member 45164529-Jul-17 22:59 
BugException on Add Marker Pin
Member 1285050114-Nov-16 16:23
Member 1285050114-Nov-16 16:23 
GeneralRe: Exception on Add Marker Pin
apis34458-Mar-17 8:53
professionalapis34458-Mar-17 8:53 
BugNot WORK. Unable to get display property Pin
Atrano19-Feb-15 1:00
Atrano19-Feb-15 1:00 
GeneralRe: Not WORK. Unable to get display property Pin
Atrano19-Feb-15 2:01
Atrano19-Feb-15 2:01 
AnswerRe: Not WORK. Unable to get display property Pin
apis344519-Feb-15 18:32
professionalapis344519-Feb-15 18:32 
Generalhelpful Pin
Member 1062595826-Feb-14 18:54
Member 1062595826-Feb-14 18:54 
QuestionThink twice before using this in your applications Pin
Robert Rohde21-Feb-14 10:35
Robert Rohde21-Feb-14 10:35 
AnswerRe: Think twice before using this in your applications Pin
apis344521-Feb-14 12:29
professionalapis344521-Feb-14 12:29 
AnswerRe: Think twice before using this in your applications Pin
apis344527-Feb-14 4:45
professionalapis344527-Feb-14 4:45 
QuestionVery good article! Pin
Volynsky Alex21-Feb-14 7:49
professionalVolynsky Alex21-Feb-14 7:49 
QuestionWhy use map, when you can use earth Pin
Sacha Barber21-Feb-14 4:45
Sacha Barber21-Feb-14 4:45 
AnswerRe: Why use map, when you can use earth Pin
apis344521-Feb-14 5:20
professionalapis344521-Feb-14 5:20 
Questionmore google api stuff Pin
Member 972333818-Feb-14 3:10
Member 972333818-Feb-14 3:10 
I am looking to hire someone with Google maps API experience to help develop a WPF project that we are porting from a web app.

If you are available for hire and can do something like this, let's talk.

Regards,
Rick
AnswerRe: more google api stuff Pin
apis344518-Feb-14 3:40
professionalapis344518-Feb-14 3:40 
GeneralMy vote of 4 Pin
Frankidoze3-Jul-13 11:56
Frankidoze3-Jul-13 11:56 
QuestionCould you make map1.html available for download? Pin
Frankidoze3-Jul-13 11:55
Frankidoze3-Jul-13 11:55 
AnswerRe: Could you make map1.html available for download? Pin
PellucidWombat4-Nov-17 19:50
PellucidWombat4-Nov-17 19:50 
Questionstill stuck in webBrowser? Pin
radioman.lt1-Feb-12 2:57
radioman.lt1-Feb-12 2:57 
AnswerRe: still stuck in webBrowser? Pin
apis34454-Feb-12 16:00
professionalapis34454-Feb-12 16:00 
GeneralRe: still stuck in webBrowser? Pin
Member 999290328-Apr-13 4:43
Member 999290328-Apr-13 4:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.