地图数据和版式数据联动

在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

  }

}

 

你可能感兴趣的:(数据)