[WPF] 浏览百度地图并获取经纬度地址信息

项目中需要利用登记的区域和地址在百度地图上定位,并获取该地址的经纬度。

本次功能对我来说主要难点如下:
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;
            }
        }
    }
原文地址:https://www.cnblogs.com/howesdomo/p/4452782.html