在很多的ArcEngine教程和博客中都会提到使用IMapBookmarks、ISpatialBookmark和IAOIBookmark三个接口实现书签功能。但这种实现方式存在一个很大的问题,那就是重新运行窗体时,之前创建的书签无法保存,导致每次都得重新创建。为解决这个问题,我在这里介绍一种利用XML实现书签功能的方法。本文的示例代码已分享至云盘:
链接:https://pan.baidu.com/s/1ehUMX6JJskwB0xrCENCg_g
提取码:agbl

1、搭建主窗体

主窗体的搭建就不多介绍了,我这里搭建的主窗体如下图所示:

ArcEngine中利用XML实现书签定位功能_ArcEngine

主窗体代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class FrmMain : Form
    {
        private FrmCreateBookmark frmCreateBookmark;
        private FrmManageBookmarks frmManageBookmarks;

        // 构造函数
        public FrmMain()
        {
            InitializeComponent();
            axMapControl1.AddShapeFile(Application.StartupPath + "\\数据", "data.shp");
        }

        // 创建书签
        private void btnCreateBookmark_Click(object sender, EventArgs e)
        {
            frmCreateBookmark = new FrmCreateBookmark();
            frmCreateBookmark.XMin = axMapControl1.ActiveView.Extent.XMin;
            frmCreateBookmark.YMin = axMapControl1.ActiveView.Extent.YMin;
            frmCreateBookmark.XMax = axMapControl1.ActiveView.Extent.XMax;
            frmCreateBookmark.YMax = axMapControl1.ActiveView.Extent.YMax;
            frmCreateBookmark.MapScale = axMapControl1.Map.MapScale;
            frmCreateBookmark.ShowDialog();
        }

        // 管理书签
        private void btnManageBookmarks_Click(object sender, EventArgs e)
        {
            if (frmManageBookmarks == null || frmManageBookmarks.IsDisposed)
            {
                frmManageBookmarks = new FrmManageBookmarks();
                frmManageBookmarks.CurrentMapControl = axMapControl1.Object as IMapControlDefault;
                frmManageBookmarks.Show();
            }
            else
            {
                frmManageBookmarks.Focus();
            }
        }
    }
}

2、创建XML文件

在Debug目录下新建一个XML文件,我们待会儿把所有的书签信息都存到里面去,XML文件主要保存书签名称、左下角X、左下角Y、右上角X、右上角Y、地图比例尺等信息,其结构如下图所示:

ArcEngine中利用XML实现书签定位功能_Text_02

3、创建书签

新建一个窗体文件,命名为FrmCreateBookmark,该窗体主要是让用户创建书签,如下图所示:

ArcEngine中利用XML实现书签定位功能_书签_03


创建书签代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace WindowsFormsApplication1
{
    public partial class FrmCreateBookmark : Form
    {
        /// <summary>
        /// 左下角X
        /// </summary>
        public double XMin { get; set; }

        /// <summary>
        /// 左下角Y
        /// </summary>
        public double YMin { get; set; }

        /// <summary>
        /// 右上角X
        /// </summary>
        public double XMax { get; set; }

        /// <summary>
        /// 右上角Y
        /// </summary>
        public double YMax { get; set; }

        /// <summary>
        /// 比例尺
        /// </summary>
        public double MapScale { get; set; }

        // 构造函数
        public FrmCreateBookmark()
        {
            InitializeComponent();
        }

        // 确定
        private void btnOk_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(txtBookmarkName.Text))
            {
                MessageBox.Show("请输入书签名称", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // 加载XML
            XmlDocument document = new XmlDocument();
            document.Load(Application.StartupPath + "\\Bookmarks.xml");

            // 获取节点
            XmlNode root = document.SelectSingleNode("Bookmarks");
            XmlNodeList childs = root.ChildNodes;

            // 遍历节点
            foreach (XmlNode child in childs)
            {
                if (child.Attributes["Name"].Value == txtBookmarkName.Text)
                {
                    MessageBox.Show("该书签已经存在", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
            }

            // 左下角X
            XmlElement xmin = document.CreateElement("XMin");
            xmin.InnerText = XMin.ToString();

            // 左下角Y
            XmlElement ymin = document.CreateElement("YMin");
            ymin.InnerText = YMin.ToString();

            // 右上角X
            XmlElement xmax = document.CreateElement("XMax");
            xmax.InnerText = XMax.ToString();

            // 右上角Y
            XmlElement ymax = document.CreateElement("YMax");
            ymax.InnerText = YMax.ToString();

            // 比例尺
            XmlElement scale = document.CreateElement("MapScale");
            scale.InnerText = MapScale.ToString();

            // 创建节点
            XmlElement element = document.CreateElement("Bookmark");
            element.SetAttribute("Name", txtBookmarkName.Text);
            element.AppendChild(xmin);
            element.AppendChild(ymin);
            element.AppendChild(xmax);
            element.AppendChild(ymax);
            element.AppendChild(scale);
            root.AppendChild(element);

            // 保存XML
            document.Save(Application.StartupPath + "\\Bookmarks.xml");
            this.Close();
        }
    }
}

4、管理书签

新建一个窗体文件,命名为FrmManageBookmarks,该窗体主要是让用户选择书签进行地图定位,如下图所示:

ArcEngine中利用XML实现书签定位功能_System_04


管理书签代码如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Output;
using ESRI.ArcGIS.SystemUI;

namespace WindowsFormsApplication1
{
    public partial class FrmManageBookmarks : Form
    {
        public IMapControlDefault CurrentMapControl { get; set; }

        // 构造函数
        public FrmManageBookmarks()
        {
            InitializeComponent();
        }

        // Load事件
        private void FrmManageBookmarks_Load(object sender, EventArgs e)
        {
            // 加载XML
            XmlDocument document = new XmlDocument();
            document.Load(Application.StartupPath + "\\Bookmarks.xml");

            // 获取节点
            XmlNode root = document.SelectSingleNode("Bookmarks");
            XmlNodeList childs = root.ChildNodes;

            // 加载书签名称
            foreach (XmlNode child in childs)
            {
                lstBookmarks.Items.Add(child.Attributes["Name"].Value);
            }
        }

        // 定位
        private void btnLocate_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(lstBookmarks.SelectedItem.ToString()))
            {
                MessageBox.Show("请选择书签", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            // 加载XML
            XmlDocument document = new XmlDocument();
            document.Load(Application.StartupPath + "\\Bookmarks.xml");

            // 获取节点
            XmlNode root = document.SelectSingleNode("Bookmarks");
            XmlNode node = null;

            // 查找书签
            foreach (XmlNode child in root.ChildNodes)
            {
                if (child.Attributes["Name"].Value == lstBookmarks.SelectedItem.ToString())
                {
                    node = child;
                    break;
                }
            }

            // 创建包络框
            IEnvelope pEnvelope = new Envelope() as IEnvelope;
            pEnvelope.XMin = double.Parse(node.SelectSingleNode("XMin").InnerText);
            pEnvelope.YMin = double.Parse(node.SelectSingleNode("YMin").InnerText);
            pEnvelope.XMax = double.Parse(node.SelectSingleNode("XMax").InnerText);
            pEnvelope.YMax = double.Parse(node.SelectSingleNode("YMax").InnerText);
            pEnvelope.SpatialReference = CurrentMapControl.SpatialReference;

            // 刷新地图
            CurrentMapControl.ActiveView.Extent = pEnvelope;
            CurrentMapControl.ActiveView.Refresh();
        }
    }
}

利用XML实现书签的好处就在于:当用户每次加载窗体时都能读取到之前创建的书签,避免每次都重复创建书签。