65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的 Google Maps 结合 WebBrowser 和 Google Maps API v3

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (14投票s)

2012 年 1 月 31 日

CPOL

5分钟阅读

viewsIcon

130089

downloadIcon

13384

您可以使用 Google Maps API v3 在 WPF 应用程序中显示地图。

引言

Google 提供了一个 JavaScript API,用于在 HTML 页面中包含具有与 maps.google.com 相同功能的地图。

Google 解释此 API 的页面在此处。

在 v2 版本中,您需要注册才能获取 API 密钥来使用该库,而在 v3 版本中,这是可选的,但仍建议这样做,因为 API 有一个限制,您每天只能生成 25,000 张地图。如果您需要更多,则需要付费,因此您需要注册,如果您注册,您可以

  • 获取每日生成地图的统计信息
  • 为额外的地图付费(每天超过 25,000 张)
  • 限制您密钥的使用,以防止在未经授权的网站上使用

要创建您的 API 密钥,请访问 APIs Console 并使用您的 Google 帐户登录。

背景

最基本的示例是下一个

<!-- 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>  

通过第一行,您启用了 HTML 本地文件来完全测试其与用户安全设置的兼容性。

您需要 5 个元素

  1. <meta> 标签指定地图应全屏显示,并且用户无法修改其大小。
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> 
  2. Google 的 API
    <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> 

    在此示例中,我使用标记集群,您可以使用此标记显示大量位置或标记,例如 300 个标记,并且这些标记按区域分组。

    第二个脚本是 Google 地图的脚本,sensor = true 参数表示应用程序使用传感器来识别用户的位置。语言参数指定指令的语言。在密钥参数中,您应该包含您的 API。

  3. 您需要包含一个位置来包含地图。通常是一个 div。在此示例中,地图的大小与页面大小相同。

     

    <div id="map_canvas" style="width:100%; height:100%"></div>  
  4. 初始化并显示地图的函数
    1. 要定位地图,您需要您想显示的地点的位置的纬度和经度
    2. 地图的选项,例如缩放、地图类型
      • ROADMAP 显示 Google Maps 的默认地图
      • SATELLITE 显示照片地图
      • HYBRID 显示照片地图和默认地图的混合
      • TERRAIN 显示用于显示高程和水体(山脉、河流等)的地形图块
  5. 为确保地图在页面创建后显示并且显示正确,您需要在页面加载事件中加载地图。
    <body onload="initialize()">   

如果地图未显示,可能是纬度和经度,它位于海上,或者您可能遇到了 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());
  }

您可以为标记指定图像、动画以及鼠标悬停在图像上时显示文本。draggable : true 选项意味着用户可以将其标记移动到另一个位置。

接下来,我为标记添加了一个监听器,以在用户结束拖动标记时发出通知。通过此事件,我将新位置发送到 WPF 应用程序。

要为标记添加一个显示文本和图像的信息窗口,您可以包含以下代码

 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
});

您可以在 此处 查看实时示例。

您可以显示两点之间的路线,为此您需要地图的 <div>,还可以选择包含一个用于路线的 <div>。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);
    }
  });
}

您可以在 此处 查看实时示例。

为了在 WPF 中包含地图,我使用了一个 WebBrowser 控件,并加载了一个我之前创建的 HTML 文件,然后读取该文件并替换纬度和经度以及信息窗口的文本。

演示应用程序显示客户数据、客户在地图上的位置,以及从公司位置前往客户位置的路线的另一个选项。

在演示中,我使用了一个 DockPanel 来在窗口大小更改时自动调整地图大小。我读取 HTML 页面并查找并替换示例中的 latLngorigindestination 等文本。我设置了一个短 URI,因为路径过长 WPF 会显示错误。

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);
}

从 WPF 应用程序调用 JavaScript 函数

使用 WPF Browser,您可以调用 HTML 中的 JavaScript 函数。这是一个示例。您可以将参数作为对象数组传递给函数。

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

从 JavaScript 调用 WPF 函数

使用 windows.external 指令,您可以从 JavaScript 调用 WPF 函数,您需要创建一个类并将其 COMVisibleAttribute 设置为 true,并将 Object 添加到 WPFBrowser

这是 HTML JavaScript 中的一个示例

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

在 WPF 应用程序中

 <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);            
 }
 } 

关注点

使用新的 Google Maps API V3 和 .NET 中的 WebBrowser,您可以在应用程序中添加地图。API 提供了大量的配置,并且通过 CSS,您可以为地图添加更多设计,以便集成到您的 WPF 或 Winforms 应用程序中。我更喜欢 WPF,因为我正在学习 WPF,但它在 Winforms 中也很相似。

您可以将客户的纬度和经度数据保存在数据库中,这将有助于添加地图来定位、用于建筑项目或发送文章给您的客户。

另外,如果您愿意,您可以使用 Bing Maps WPF 控件,有了这个组件,您就可以使用 .NET 代码添加标记,而无需 JavaScript 和 HTML 页面。

© . All rights reserved.