项目中需要利用登记的区域和地址在百度地图上定位,并获取该地址的经纬度。
本次功能对我来说主要难点如下:
1、百度地图API的基本使用方法,请首选使用百度地图的JavaScript大众版(PS:之前使用WebAPI会导致WebBrowser浏览出现很多问题);
JavaScript大众版网址:http://developer.baidu.com/map/index.php?title=jspopular
2、WPF WebBrowser控件中的JavaScript与WPF的交互;
3、WPF WebBrowser中IE缓存问题,导致开发调试时间增加;
4、WPF WebBrowser中如何禁止JS报错弹窗提示;
项目可以到百度云盘下载:http://pan.baidu.com/s/1o6MHxSA
主要代码如下:
ViewBaiduMapByLoaction.cs代码
public partial class ViewBaiduMapByLoaction : Window { /// <summary> /// IP地址 /// </summary> public string IP {// TODO : 设置IP(IIS) get { return "192.168.1.215"; } } /// <summary> /// 端口 /// </summary> public string Port {// TODO : 设置端口(IIS) get { return "34322"; } } /// <summary> /// 百度API Key (AK) /// </summary> public string BaiduAK { get { return "yRnTso4E6HW32nxqHEY82wXi"; } } public BaiduMapByLoactionViewModel ViewModel; public ViewBaiduMapByLoaction() { InitializeComponent(); this.initUI(); this.initEvent(); } private void initUI() { this.ViewModel = new BaiduMapByLoactionViewModel(); this.DataContext = this.ViewModel; } private void initEvent() { this.wbBaiduMap.LoadCompleted += new LoadCompletedEventHandler(webBrowser_LoadCompleted); // JavaScript 与 WPF 交互 this.wbBaiduMap.Navigated += (a, b) => { this.hideScriptErrors(this.wbBaiduMap, true); }; // 阻止JS报错弹窗(可以注释) this.btnSearch.Click += this.btnSearch_Click; this.btnGetAddressFromWeb.Click += this.btnGetAddressFromWeb_Click; } /// <summary> /// 阻止JS报错弹窗(建议不使用) /// </summary> /// <param name="wb"></param> /// <param name="hide"></param> private void hideScriptErrors(WebBrowser wb, bool hide) { var fiComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic); if (fiComWebBrowser == null) return; var objComWebBrowser = fiComWebBrowser.GetValue(wb); if (objComWebBrowser == null) { wb.Loaded += (o, s) => hideScriptErrors(wb, hide); //In case we are to early return; } objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { hide }); Cursor = Cursors.Arrow; } private void btnSearch_Click(object sender, RoutedEventArgs e) { if (string.IsNullOrEmpty(this.ViewModel.CityOrProvince) && string.IsNullOrEmpty(this.ViewModel.Address)) { MessageBox.Show("请输入城市 / 地址。。。", "错误"); return; } try { Cursor = Cursors.Wait; this.getGPSInfoByAddress(); } catch (Exception ex) { MessageBox.Show(ex.Message, "错误"); } } /// <summary> /// 访问ASPX显示地图 /// </summary> private void getGPSInfoByAddress() { try { // 清除IE缓存 foreach (string strFileName in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Cookies))) { if (strFileName.ToLower().IndexOf("index.dat") == -1) { File.Delete(strFileName); } } string uri = string.Format("http://{0}:{1}/WebServer/ViewMapByAddress.aspx?{2}{3}{4}", this.IP, this.Port, !string.IsNullOrEmpty(this.ViewModel.Address) ? string.Format("address={0}", this.ViewModel.Address) : string.Empty, !string.IsNullOrEmpty(this.ViewModel.CityOrProvince) ? string.Format("&city={0}", this.ViewModel.CityOrProvince) : string.Empty, !string.IsNullOrEmpty(this.BaiduAK) ? string.Format("&ak={0}", this.BaiduAK) : string.Empty ); this.wbBaiduMap.Navigate(uri); } catch (Exception ex) { MessageBox.Show(ex.Message, "错误"); } } /// <summary> /// Web控件 与 JavaScript交互 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void webBrowser_LoadCompleted(object sender, NavigationEventArgs e) { this.wbBaiduMap.ObjectForScripting = new JSCallback(this); } /// <summary> /// 从浏览器控件中复制经纬度信息到WPF界面中 /// JS 与 WPF 交互 /// </summary> /// <param name="lng"></param> /// <param name="lat"></param> public void SetLongitudeAndLatitude(string lng, string lat) { this.ViewModel.Lng = lng; this.ViewModel.Lat = lat; } /// <summary> /// WPF 与 JS 交互 获取浏览器控件中的值到WPF中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void btnGetAddressFromWeb_Click(object sender, RoutedEventArgs e) { try { this.wbBaiduMap.InvokeScript("setAddress"); } catch (Exception ex) { MessageBox.Show(ex.Message, "错误"); } } } #region JSCallBack [ComVisible(true)] public class JSCallback { private ViewBaiduMapByLoaction Main { get; set; } public JSCallback(ViewBaiduMapByLoaction main) { this.Main = main; } public void SetLongitudeAndLatitude(string lng, string lat) { this.Main.SetLongitudeAndLatitude(lng, lat); } public void SetAddress(string address) { if (!string.IsNullOrEmpty(address)) { this.Main.ViewModel.AddressFromWeb = address; } } } #endregion
ViewMapByAddress.aspx代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ViewMapByAddress.aspx.cs" Inherits="BaiduMap_DEMO.WebServer.ViewMapByAddress" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> html { width: 100%; height: 100%; margin: 0; font-family: "微软雅黑"; } body { width: 100%; height: 100%; margin: 0; font-family: "微软雅黑"; } #allmap { height: 100%; width: 100%; } #r-result { width: 100%; } </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=yRnTso4E6HW32nxqHEY82wXi"></script> <title>地址解析</title> </head> <body> <div id="allmap"> </div> </body> </html> <script type="text/javascript"> // 百度地图API功能 var map = new BMap.Map("allmap"); var point = new BMap.Point(0, 0); var geoPoint = new BMap.Point(0, 0); var myZoomLevel = <%=ZoomLevel %>; var addressString = ""; // map.centerAndZoom(point, myZoomLevel); map.enableScrollWheelZoom(); // 创建地址解析器实例 var myGeo = new BMap.Geocoder(); // 将地址解析结果显示在地图上,并调整地图视野 myGeo.getPoint("<%=Address %>", function (_point) { if (_point) { geoPoint = _point; map.centerAndZoom(geoPoint, myZoomLevel); // ******** 添加自定义控件 ******** // 定义一个控件类,即function function ZoomControl() { // 默认停靠位置和偏移量 this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT; this.defaultOffset = new BMap.Size(10, 10); } // 通过JavaScript的prototype属性继承于BMap.Control ZoomControl.prototype = new BMap.Control(); // 自定义控件必须实现自己的initialize方法,并且将控件的DOM元素返回 // 在本方法中创建个div元素作为控件的容器,并将其添加到地图容器中 ZoomControl.prototype.initialize = function (map) { // 创建一个DOM元素 var div = document.createElement("div"); // 添加文字说明 div.appendChild(document.createTextNode("获取经纬度")); // 设置样式 div.style.cursor = "pointer"; div.style.border = "1px solid gray"; div.style.backgroundColor = "red"; // 绑定事件 div.onclick = function (e) { setLongitudeAndLatitude(); } // 添加DOM元素到地图中 map.getContainer().appendChild(div); // 将DOM元素返回 return div; } // 创建控件 var myZoomCtrl = new ZoomControl(); // 添加到地图当中 map.addControl(myZoomCtrl); // ******** End of 添加自定义控件 ******** // ******** 添加 BMap.Marker (红点) ******** addressString = "<%=Address %>"; var diyMarker = new BMap.Marker(_point); diyMarker.setTitle("<%=Address %>"); var label = new BMap.Label("<%=Address %>"+ "(" + geoPoint.lng + ", " + geoPoint.lat + ")", { offset: new BMap.Size(20, -10) }); diyMarker.setLabel(label); map.addOverlay(diyMarker); // ******** End of 添加 BMap.Marker (红点) ******** } else { alert("警告:您输入的街道没有解析到结果。"); geoPoint = ""; } }, "<%=City %>"); // ******** 添加导航栏 ******** // 添加带有定位的导航控件 var navigationControl = new BMap.NavigationControl({ // 靠左上角位置 anchor: BMAP_ANCHOR_TOP_RIGHT, // LARGE类型 type: BMAP_NAVIGATION_CONTROL_LARGE, // 启用显示定位 enableGeolocation: true }); map.addControl(navigationControl); // ******** 单击地图事件 ******** map.addEventListener("click", function (e) { map.clearOverlays(); var pt = e.point; myGeo.getLocation(pt, function (rs) { if (!!rs.addressComponents) { var addComp = rs.addressComponents; // addressComponents 有多个属性 // 省(Province);市(City);区(District);街(Street);房号(StreetNumber) geoPoint = pt; var diyMarker = new BMap.Marker(pt); // 创建百度地图红点 addressString = addComp.city + addComp.district + addComp.street + addComp.streetNumber; diyMarker.setTitle(addressString); var label = new BMap.Label(addressString + "(" + geoPoint.lng + ", " + geoPoint.lat + ")", { offset: new BMap.Size(20, -10) }); // 创建标注,并设置标注位置 diyMarker.setLabel(label); map.addOverlay(diyMarker); } }); }); function setAddress() // 获取地址信息 { if(!!addressString) { window.external.SetAddress(addressString); } else { alert("警告:请点击地图获取设置查询地点。"); } } function setLongitudeAndLatitude() // 获取经纬度信息 { if(!!geoPoint) { window.external.SetLongitudeAndLatitude(geoPoint.lng, geoPoint.lat); } else { alert("警告:请点击地图获取设置查询地点。"); } } </script>
ViewMapByAddress.aspx.cs 代码如下:
public partial class ViewMapByAddress : System.Web.UI.Page { /// <summary> /// 城市 /// </summary> public string City { get; set; } /// <summary> /// 地址 /// </summary> public string Address { get; set; } /// <summary> /// 百度地图缩放层级 /// </summary> public int ZoomLevel { get; set; } protected void Page_Load(object sender, EventArgs e) { this.City = this.Request["city"]; this.Address = this.Request["address"]; this.ZoomLevel = 18; if (string.IsNullOrEmpty(this.Address) && !string.IsNullOrEmpty(this.City)) { this.Address = this.City; this.ZoomLevel = 8; } } }