MapControl与PageLayoutControl同步二

本文介绍如何使用ArcGIS实现MapControl和PageLayoutControl两种视图的同步。通过自定义类实现地图文档的打开、新建和视图切换等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2、新建Maps类

在同步类中,要用到Maps类,用于管理地图对象。与新建同步类ControlsSynchronizer类似,我们新建一Maps类,其所有代码如下所示:

 using System;

using System.Collections;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

using ESRI.ArcGIS.Carto;

namespace _sdnMap

{

    [Guid("f27d8789-fbbc-4801-be78-0e3cd8fff9d5")]

    [ClassInterface(ClassInterfaceType.None)]

    [ProgId("_sdnMap.Maps")]

    public class Maps : IMaps, IDisposable

    {

        //class member - using internally an ArrayList to manage the Maps collection

        private ArrayList m_array = null;

        #region class constructor

        public Maps()

        {

            m_array = new ArrayList();

        }

        #endregion

        #region IDisposable Members

        /// <summary>

        /// Dispose the collection

        /// </summary>

        public void Dispose()

        {

            if (m_array != null)

            {

                m_array.Clear();

                m_array = null;

            }

        }

        #endregion

        #region IMaps Members

        /// <summary>

        /// Remove the Map at the given index

        /// </summary>

        /// <param name="Index"></param>

        public void RemoveAt(int Index)

        {

            if (Index > m_array.Count || Index < 0)

                throw new Exception("Maps::RemoveAt:\r\nIndex is out of range!");

            m_array.RemoveAt(Index);

        }

        /// <summary>

        /// Reset the Maps array

        /// </summary>

        public void Reset()

        {

            m_array.Clear();

        }

        /// <summary>

        /// Get the number of Maps in the collection

        /// </summary>

        public int Count

        {

            get

            {

                return m_array.Count;

            }

        }

        /// <summary>

        /// Return the Map at the given index

        /// </summary>

        /// <param name="Index"></param>

        /// <returns></returns>

        public IMap get_Item(int Index)

        {

            if (Index > m_array.Count || Index < 0)

                throw new Exception("Maps::get_Item:\r\nIndex is out of range!");

            return m_array[Index] as IMap;

        }

        /// <summary>

        /// Remove the instance of the given Map

        /// </summary>

        /// <param name="Map"></param>

        public void Remove(IMap Map)

        {

            m_array.Remove(Map);

        }

        /// <summary>

        /// Create a new Map, add it to the collection and return it to the caller

        /// </summary>

        /// <returns></returns>

        public IMap Create()

        {

            IMap newMap = new MapClass();

            m_array.Add(newMap);

            return newMap;

        }

        /// <summary>

        /// Add the given Map to the collection

        /// </summary>

        /// <param name="Map"></param>

        public void Add(IMap Map)

        {

            if (Map == null)

                throw new Exception("Maps::Add:\r\nNew Map is mot initialized!");

            m_array.Add(Map);

        }

        #endregion

    }

}

3、新建打开文档类OpenNewMapDocument

由于从工具栏自带的打开按钮打开地图文档的时候,不会自动进行两种视图之间的同步,所以我们要自己派生一个OpenNewMapDocument类,用于打开地图文档。

 右击项目名,选择“添加|类”,再选择ArcGIS类别中的BaseCommand模板,输入类名为“OpenNewMapDocument.cs”。

首先添加引用:

using System.Windows.Forms;

using ESRI.ArcGIS.Carto;

再添加如下成员变量:

 private ControlsSynchronizer m_controlsSynchronizer = null;

修改默认的构造函数如下所示:

 //添加参数

public OpenNewMapDocument(ControlsSynchronizer controlsSynchronizer)

        {

            //

            // TODO: Define values for the public properties

            //

//设定相关属性值

            base.m_category = "Generic"; //localizable text

            base.m_caption = "Open";  //localizable text

            base.m_message = "This should work in ArcMap/MapControl/PageLayoutControl"; //localizable text

            base.m_toolTip = "Open";  //localizable text

            base.m_name = "Generic_Open";   //unique id, non-localizable (e.g. "MyCategory_MyCommand")

   //初始化m_controlsSynchronizer

            m_controlsSynchronizer = controlsSynchronizer;

            try

            {

                //

                // TODO: change bitmap name if necessary

                //

                string bitmapResourceName = GetType().Name + ".bmp";

                base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);

            }

            catch (Exception ex)

            {

                System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");

            }

        }

再在OnClick函数中添加如下代码:

 public override void OnClick()

        {

            // TODO: Add OpenNewMapDocument.OnClick implementation

            OpenFileDialog dlg = new OpenFileDialog();

            dlg.Filter = "Map Documents (*.mxd)|*.mxd";

            dlg.Multiselect = false;

            dlg.Title = "Open Map Document";

            if (dlg.ShowDialog() == DialogResult.OK)

            {

                string docName = dlg.FileName;

                IMapDocument mapDoc = new MapDocumentClass();

                if (mapDoc.get_IsPresent(docName) && !mapDoc.get_IsPasswordProtected(docName))

                {

                    mapDoc.Open(docName, string.Empty);

                    IMap map = mapDoc.get_Map(0);

                    m_controlsSynchronizer.ReplaceMap(map);

                    mapDoc.Close();

                }

            }

        }

在添加类时,模板会自动添加一个名为“OpenNewMapDocument.bmp”的图标,你可以自己修改或者替换为打开的文件夹的图标。

4、两种视图的同步

在3sdnMap.cs中添加成员变量,即同步类对象:

 private ControlsSynchronizer m_controlsSynchronizer = null;

在Form1_Load函数中进行初始化工作:

 //初始化controls synchronization calss

m_controlsSynchronizer = new

ControlsSynchronizer(m_mapControl, m_pageLayoutControl);

     //把MapControl和PageLayoutControl绑定起来(两个都指向同一个Map),然后设置MapControl为活动的Control

     m_controlsSynchronizer.BindControls(true);

     //为了在切换MapControl和PageLayoutControl视图同步,要添加Framework Control

    m_controlsSynchronizer.AddFrameworkControl(axToolbarControl1.Object);

    m_controlsSynchronizer.AddFrameworkControl(this.axTOCControl1.Object);

// 添加打开命令按钮到工具条

OpenNewMapDocument openMapDoc = new OpenNewMapDocument(m_controlsSynchronizer);

axToolbarControl1.AddItem(openMapDoc, -1, 0, false, -1, esriCommandStyles.esriCommandStyleIconOnly);

因为我们自动派生了打开文档类,并自己将其添加到工具条,所以我们就不需要工具条原来的“打开”按钮了,可以ToolbarControl的属性中将其删除。

下面,我们可完成上一讲遗留的功能了。

 /// <summary>

        /// 新建地图命令

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void New_Click(object sender, EventArgs e)

        {

            //询问是否保存当前地图

            DialogResult res = MessageBox.Show("是否保存当前地图?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (res == DialogResult.Yes)

            {

                //如果要保存,调用另存为对话框

                ICommand command = new ControlsSaveAsDocCommandClass();

                if (m_mapControl != null)

                    command.OnCreate(m_controlsSynchronizer.MapControl.Object);

                else

                    command.OnCreate(m_controlsSynchronizer.PageLayoutControl.Object);

                command.OnClick();

            }

     //创建新的地图实例

            IMap map = new MapClass();

            map.Name = "Map";

            m_controlsSynchronizer.MapControl.DocumentFilename = string.Empty;

            //更新新建地图实例的共享地图文档

            m_controlsSynchronizer.ReplaceMap(map);

        }

/// <summary>

        /// 打开地图文档Mxd命令

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void Open_Click(object sender, EventArgs e)

        {

if (this.axMapControl1.LayerCount > 0)

            {

                DialogResult result = MessageBox.Show("是否保存当前地图?", "警告",

MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                if (result == DialogResult.Cancel) return;

                if (result == DialogResult.Yes) this.Save_Click(null, null);

            }

            OpenNewMapDocument openMapDoc =

new OpenNewMapDocument(m_controlsSynchronizer);

            openMapDoc.OnCreate(m_controlsSynchronizer.MapControl.Object);

            openMapDoc.OnClick();

}

 

在添加数据AddData时,我们也要进行地图共享,故在AddData_Click函数后面添加如下代码:

 IMap pMap = this.axMapControl1.Map;

this.m_controlsSynchronizer.ReplaceMap(pMap);

在另存为地图文档时,有可能会丢失数据,因此我们需要提示用户以确认操作,故需修改SaveAs_Click函数,如下所示:

 

 /// <summary>

        /// 另存为地图文档命令

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void SaveAs_Click(object sender, EventArgs e)

        {

            //如果当前视图为MapControl时,提示用户另存为操作将丢失PageLayoutControl中的设置

            if (m_controlsSynchronizer.ActiveControl is IMapControl3)

            {

                if (MessageBox.Show("另存为地图文档将丢失制版视图的设置\r\n您要继续吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)

                    return;

            }

            //调用另存为命令

            ICommand command = new ControlsSaveAsDocCommandClass();

            command.OnCreate(m_controlsSynchronizer.ActiveControl);

            command.OnClick();

        }

在切换视图时,我们要激活相关的视图,故在设计视图的属性面板中选择tabControl2控件,再选择事件按钮,找到“SelectedIndexChanged”事件双击添加之。其实现代码如下所示:

 

 /// <summary>

        /// 切换地图和制版视图

        /// </summary>

        /// <param name="sender"></param>

        /// <param name="e"></param>

        private void tabControl2_SelectedIndexChanged(object sender, EventArgs e)

        {

            if (this.tabControl2.SelectedIndex == 0)

            {

                //激活MapControl

                m_controlsSynchronizer.ActivateMap();

            }

            else

            {

                //激活PageLayoutControl

                m_controlsSynchronizer.ActivatePageLayout();

            }

        }

 

5、编译运行

按F5编译运行程序,至此我们完成了MapControl和PageLayoutControl两种视图的同步工作。

在下一讲中,我将给大家带来的是状态栏的相关操作


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值