地图数据和版式数据联动

在ArcGIS二维中有数据视图和版式视图两种模式。两种视图可以切换显示。笔者在开始做Engine二次开发时,每次在数据和视图切换时,都拷贝数据,或者两个视图同事加载同一份数据。在切换时速度很慢,特别是数据量较大的时候。用户体验很差。

但当仔细看ArcEngine自带的例子时,里面的例子中就有一个数据视图和版式视图数据同步的例子,我们可以参考ArcEngine提供的例子来写我们自己的同步代码。

既然我们要做数据视图数据和版式视图数据的同步,我们首先要确定我们要同步那些信息,也就是公用哪些信息。两个视图模式公用的就是地图,也就是Layer的几何。不包含各各自的Element等信息。

ArcGIS的二维地图数据的配置文件是Mxd文件,Mxd文件中存储着版式和数据视图所包含的信息。而且我们也要清楚版式视图是可以包含多个地图的,除了多个地图之外还包括对应的智能图饰,如指北针、图例、比例尺等。但只能一个地图时当前激活的,而当前激活的地图就是数据视图要显示的地图。首先我们打开一个Mxd文件。代码如下:

View Code
public override void OnClick()
        {
            base.OnClick();
            OpenFileDialog myOpenFileDialog = new OpenFileDialog();
            myOpenFileDialog.Filter = "Mxd文档|*.mxd";
            if (myOpenFileDialog.ShowDialog()!=true)
            {
                return;
            }
            string myMxdFilePath = myOpenFileDialog.FileName;
            MapDocumentClass myMapDocument = new MapDocumentClass();
            myMapDocument.Open(myMxdFilePath,"");
            this._mapApplication.MapDocument = myMapDocument;

            this._mapApplication.MapControl.Refresh(esriViewDrawPhase.esriViewNone, null, null) ;
        }


/// <summary>
        /// 地图文档对象
        /// </summary>
        public IMapDocument MapDocument
        {
            get { return this._mapDocument; }
            set
            {
                this._mapDocument = value;
                if (this._mapDocument != null)
                {
                    this._controlsSynchronizer.PageLayoutControl.PageLayout = this._mapDocument.PageLayout;
                    List<IMap> myMapList = new List<IMap>();
                    for (int i = 0; i < this._mapDocument.MapCount; i++)
                    {
                        myMapList.Add(this._mapDocument.get_Map(i));
                    }
                    this._controlsSynchronizer.ReaplaceMaps(myMapList);
                    this.LayerTree.SetActiveView(this.ActiveView);
                }
            }
        }


/// <summary>
        /// 替换当前显示的地图
        /// </summary>
        /// <param name="pMap"></param>
        public void ReaplaceMaps(List<IMap> pMaps)
        {
            IMaps myMaps = new Maps();
            foreach (IMap myMap in pMaps)
            {
                myMaps.Add(myMap);
            }

            MapActivePattern myActivePattern = this._activePattern;

            //只有当在PageLayoutControl被激活时,才能调用ReplaceMap方法。
            this.ActivatePageLayout();
            this.PageLayoutControl.PageLayout.ReplaceMaps(myMaps);

            //把map传递给mapControl
            this.MapControl.Map = this.PageLayoutControl.ActiveView.FocusMap;

            //保证一个处于激活状态
            if (myActivePattern == MapActivePattern.Map)
            {
                this.ActivateMap();
                this.MapControl.ActiveView.Refresh();
            }
            else
            {
                this.ActivatePageLayout();
                this.PageLayoutControl.ActiveView.Refresh();
            }
        }

从上面的代码中,我们可以看到,打开一个地图文件,并保证两个视图地图数据同步需要三个步骤。
1.打开Mxd文件,得到MapDocument对象。

2.把读取到的地图对象中的版式对象PageLayout赋值给版式对象PageLayoutControl。

3.第三步就是同步地图数据了。先从MapDocument中把地图对象都取出来,组成一个地图列表对象。然后调用PageLayout的ReplaceMaps函数替换当前版式中的地图,然后把当前版式数据中激活的地图赋给数据视图MapControl的Map。

这样就保证了打开一个地图文件后,版式视图中激活的地图和数据视图展示的地图时一个对象,当我们对当前激活的地图有什么操作时,两者都可以响应。

但有一点,数据视图和版式视图当前只能有一个被激活。所以一般我们在项目中都把数据视图UI和版式视图UI放在两个Tab页面中,当切换时分别调用二者的激活函数,代码如下:

/// <summary>
        /// 激活map
        /// </summary>
        public void ActivateMap()
        {
            try
            {
                if (this.PageLayoutControl.ActiveView.IsActive())
                {
                    this.PageLayoutControl.ActiveView.Deactivate();
                    this.MapControl.ActiveView.Activate(this.MapControl.hWnd);
                }
                this._activePattern = MapActivePattern.Map;
            }
            catch (Exception ex)
            {
                throw new Exception("激活地图模式错误。" + ex.Message);
            }
        }



        /// <summary>
        /// 激活版式视图
        /// </summary>
        public void ActivatePageLayout()
        {
            try
            {
                if (this.MapControl.ActiveView.IsActive())
                {
                    this.MapControl.ActiveView.Deactivate();
                    this.PageLayoutControl.ActiveView.Activate(this.PageLayoutControl.hWnd);
                }
                this._activePattern = MapActivePattern.PageLayout;
                 }
            catch (Exception ex)
            {
                throw new Exception("激活版式模式错误。" + ex.Message);
            }
        }

下面的代码是继承IMaps实现的Maps的代码,这个在PageLayout对象Replace函数会用到。Engine的例子代码中就有该类的定义。

View Code
// Copyright 2006 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See use restrictions at /arcgis/developerkit/userestrictions.

using System;
using ESRI.ArcGIS.Carto;
using System.Collections;


namespace BM.AE.Engine
{
  /// <summary>
  /// Implementation of interface IMaps which is eventually a collection of Maps
  /// </summary>
  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
  }
}
原文地址:https://www.cnblogs.com/xzbluemap/p/2848461.html