基于sharpdevelop核心和ArcEngine打造插件式桌面GIS应用之五——图层树
这个系列好久没有更新了,时间拖得太久了,一来是工作确实忙,出差比较多;二来,最近公司有点动荡,部门独立出来成立一个公司,有些其他事情耽搁了;三来,懒。这篇文章将介绍一下图层树,图层树的英文简写是Toc,全程Table of content。
ArcMap的TOC功能很强大,基本上我在实现TOC的时候,也是照虎画猫(我实现的这个和ArcMap比起来就是一只小猫,蛮丑的小猫)。闲话少扯,进入正题。
  Toc的功能包括:
  1、显示(调整)图层组织结构
  2、对图层的显示/隐藏状态进行控制
  3、提供针对图层的特殊操作,包括数据导出、选择集管理、属性设置等
Toc控件本身较为简单,继承了UserControl的一个用户自定义控件,增加了图层顺序拖动调整的功能。通过与右键菜单的结合,展示出了丰富的功能。

在实现右键菜单时,首先要获取在Toc中选中的对象类型及状态,比如:如果选中的是FeatureLayer,那就可以进行数据导出、选择集操作,如果选中的FeatureLayer对应的FeatureClass的GeometryType是Polygon,就显示“设置为工作区域”菜单……
要达到这个目的,就需要在Toc控件中对外公开一个当前选中对象的属性—SelectItem。具体的定义如下:
public partial class TocControl : UserControl
{
	..........
		#region 属性定义
        public object BuddyControl
        {
            get
            {
                return this.axTOCControl1.Buddy;
            }
            set
            {
                this.axTOCControl1.SetBuddyControl(value);
            }
        }
        /// <summary>
        /// 获取当前图层
        /// </summary>
        public ESRI.ArcGIS.Carto.ILayer CurrentLayer
        {
            get
            {
                return m_layer;
            }
        }
        private SelectItem selectedItem = null;
        /// <summary>
        /// 当前选中的对象
        /// </summary>
        public SelectItem SeletedItem
        {
            get
            {
                return this.selectedItem;
            }
        }
        #endregion
		private void GetSelectItem(int x,int y)
        {
            esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
            ILayer layer = null;
            IBasicMap map = null;
            this.axTOCControl1.HitTest(x, y, ref item, ref map, ref layer, ref m_other, ref m_index);
            switch (item)
            {
                case esriTOCControlItem.esriTOCControlItemLayer:
                    this.selectedItem = new SelectItem(item, layer);                    
                    break;
                case esriTOCControlItem.esriTOCControlItemMap:
                    this.selectedItem = new SelectItem(item, map);
                    break;
                case esriTOCControlItem.esriTOCControlItemLegendClass:
                    this.selectedItem = new SelectItem(item, m_other);
                    break;
                case esriTOCControlItem.esriTOCControlItemHeading:
                    this.selectedItem = new SelectItem(item, null);
                    break;
                case esriTOCControlItem.esriTOCControlItemNone:
                    this.selectedItem = null;
                    break;
                default:
                    this.selectedItem = null;
                    break;
            }
        }
		public class SelectItem
        {
            public SelectItem(esriTOCControlItem type,object obj)
            {
                this.itemType = type;
                this.itemObject = obj;
            }
            private esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemLayer;
            public esriTOCControlItem ItemType
            {
                get { return itemType; }
                set { itemType = value; }
            }
            private object itemObject = null;
            public object ItemObject
            {
                get { return itemObject; }
                set { itemObject = value; }
            }
        }
		
		..........
}
接下来做的就是需要根据Toc的SelectItem类型进行菜单显示状态控制。大家或许已经猜到了实现方法——使用IConditionEvaluator。没错,在我的框架中,为Toc控件实现了两个ConditionEvaluator,分别是TocItemSelectedConditionEvaluator和LayerFeatureSelectedConditionEvaluator。
TocItemSelectedConditionEvaluator用来判断Toc当前选中对象的具体类型,实现代码:
 /// <summary>
    /// Toc控件选择对象条件计算器
    /// Toc控件选择对象类型包括:图层:layer,feautrelayer,rasterlayer,grouplayer,地图:map,图例:legend
    /// wangyuxiang 2010-12-16
    /// </summary>
    class TocItemSelectedConditionEvaluator : IConditionEvaluator
	{
		public bool IsValid(object caller, Condition condition)
		{
			if (WorkbenchSingleton.Workbench == null) {
				return false;
			}
			
			string itemtype = condition.Properties["itemtype"];           
            GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl tocControl = null;
            foreach (PadDescriptor pad in WorkbenchSingleton.Workbench.PadContentCollection)
            {
                if (pad.PadContent != null &&  pad.PadContent.Control is GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl)
                {
                    tocControl = pad.PadContent.Control as GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl;
                    if (tocControl.SeletedItem != null)
                    {
                        if (itemtype == "*")
                        {
                            return true;
                        }
                        if (Convert.ToString(itemtype).ToLower().Equals("layer"))
                        {
                            return tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLayer;
                        }
                        else if (Convert.ToString(itemtype).ToLower().Equals("map"))
                        {
                            return tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemMap;
                        }
                        else if (Convert.ToString(itemtype).ToLower().Equals("legend"))
                        {
                            return tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLegendClass;
                        }
                        else if (Convert.ToString(itemtype).ToLower().Equals("featurelayer"))
                        {
                            return (tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLayer && tocControl.SeletedItem.ItemObject is IFeatureLayer);
                        }
                        else if (Convert.ToString(itemtype).ToLower().Equals("rasterlayer"))
                        {
                            return (tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLayer && tocControl.SeletedItem.ItemObject is IRasterLayer);
                        }
                        else if (Convert.ToString(itemtype).ToLower().Equals("grouplayer"))
                        {
                            return (tocControl.SeletedItem.ItemType == ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLayer && tocControl.SeletedItem.ItemObject is IGroupLayer);
                        }
                    }
                    break;
                }
            }
			return false;
		}
    }
LayerFeatureSelectedConditionEvaluator用来判断当前选中的FeatureLayer是否存在选择集,实现代码:
 /// <summary>
    /// 图层要素选择条件计算器    
    /// wangyuxiang 2010-12-17
    /// </summary>
    class LayerFeatureSelectedConditionEvaluator : IConditionEvaluator
	{
		public bool IsValid(object caller, Condition condition)
		{
			if (WorkbenchSingleton.Workbench == null) {
				return false;
            }
            GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl tocControl = null;
            foreach (PadDescriptor pad in WorkbenchSingleton.Workbench.PadContentCollection)
            {
                if (pad.PadContent.Control is GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl)
                {
                    tocControl = pad.PadContent.Control as GISP.Lib.ArcGIS.ArcMap.GUI.MapDisplayBinding.TocControl;
                    if (tocControl.SeletedItem != null)
                    {
                        if (tocControl.SeletedItem.ItemObject is IFeatureLayer)
                        {
                            IFeatureSelection featureSelection = tocControl.SeletedItem.ItemObject as IFeatureSelection;
                            if (featureSelection != null)
                            {
                                ISelectionSet selectionSet = featureSelection.SelectionSet;
                                return (selectionSet != null && selectionSet.Count > 0);
                            }
                        }
                    }
                    break;
                }
            }
			return false;
		}
    }
整个右键菜单的Addin配置如下:
<!--二维地图Toc控件右键菜单--> <Path name = "/SDF/Pads/ArcMap/TocPad/ContextMenu"> <Condition name = "TocItemSelected" itemtype="layer"> <MenuItem id = "RemoveLayer" type="ContextMenu" label = "移除" icon="ArcGIS.LayerTreeDelete16" class = "GISP.Addin.ArcMap.Commands.TocCommand_RemoveSelectedLayer"/> <MenuItem id = "RemoveLayer" type="ContextMenu" label = "标注" icon="ArcGIS.LayerTreeDelete16" class = "GISP.Addin.ArcMap.Commands.TocCommand_ShowLayerLabel"/> <ComplexCondition> <And> <Condition name = "TocItemSelected" itemtype="featurelayer" action="Disable"/> </And> <MenuItem id = "ZoomToLayer" type="ContextMenu" label = "查看属性表" icon ="ArcGIS.LayerTableOpen16" class = "GISP.Addin.ArcMap.Commands.TocCommand_ShowLayerAttribute"/> </ComplexCondition> <MenuItem id = "ZoomToLayer" type="ContextMenu" label = "缩放到图层" icon="GIS.MapControl.FullScreen" class = "GISP.Addin.ArcMap.Commands.TocCommand_ZoomToSelectedLayer"/> <ComplexCondition> <And> <Condition name = "MapScaleOutOfLayerScale" action="Disable"/> </And> <MenuItem id = "ZoomToVisible" type="ContextMenu" label = "缩放到图层显示比例尺" class = "GISP.Addin.ArcMap.Commands.TocCommand_ZoomToShowLayer"/> </ComplexCondition> <ComplexCondition> <And> <Condition name = "TocItemSelected" itemtype="featurelayer" action="Disable"/> </And> <MenuItem id = "LayerSection" label = "选择集" type ="Menu"> <ComplexCondition> <And> <Condition name = "LayerFeatureSelected" action="Disable"/> </And> <MenuItem id = "ZoomToSection" type="ContextMenu" label = "缩放到选中要素" icon="ArcGIS.ScreenPosition16" class = "GISP.Addin.ArcMap.Commands.TocCommand_ZoomToSelectedFeatures"/> <MenuItem id = "PanToSection" type="ContextMenu" label = "移动到选中要素" class = "GISP.Addin.ArcMap.Commands.TocCommand_PanToSelectedFeatures"/> <MenuItem id = "ClearSelectFeatures" type="ContextMenu" label = "取消选中状态" class = "GISP.Addin.ArcMap.Commands.TocCommand_ClearFeaturelayerSelection"/> <MenuItem id = "SwtichSelectFeatures" type="ContextMenu" label = "切换选中状态" class = ""/> <MenuItem id = "AddSelectFeaturesToWorkArea" type="ContextMenu" label = "添加到工作区域" class = "GISP.Addin.ArcMap.Commands.TocCommand_SetSelectFeaturesAsWorkAreas"/> </ComplexCondition> <ComplexCondition> <And> <Condition name = "WorkAreaIsValid" action="Disable"/> </And> <MenuItem id = "selectIntersectWIthWorkArea" type="ContextMenu" label = "选择工作区域内要素" icon="ArcGIS.GenericAddGreen16" class = "GISP.Addin.ArcMap.Commands.TocCommand_SelectFeaturesIntersectsWithWorkAreas"/> </ComplexCondition> <MenuItem id = "SelectAllFeatures" type="ContextMenu" label = "全部选中" class = "GISP.Addin.ArcMap.Commands.TocCommand_SelectAllFeatures"/> </MenuItem> </ComplexCondition> <ComplexCondition> <And> <Condition name = "TocItemSelected" itemtype="featurelayer" action="Disable"/> </And> <MenuItem id = "Separator" type = "Separator" /> <MenuItem id = "FeatureLayerData" label = "数据" icon="ArcGIS.ContentsWindowDrapedLayers16" type = "Menu"> <MenuItem id = "ExportFeatureLayerData" type="ContextMenu" label = "导出" icon="ArcGIS.LayerToLayer16" class = "GISP.Addin.ArcMap.Commands.TocCommand_ExportFeatureLayer"/> </MenuItem> <MenuItem id = "SetAsWorkArea" type="ContextMenu" label = "设置为工作区域" icon ="ArcGIS.GenericOptions16" class = "GISP.Addin.ArcMap.Commands.WorkArea_SetLayerAsWorkAreaCommand"/> <MenuItem id = "Separator" type = "Separator" /> </ComplexCondition> </Condition> <Condition name = "TocItemSelected" itemtype="*"> <MenuItem id = "LayerProperties" type="ContextMenu" label = "属性" icon ="ArcGIS.GenericOptions16" class = "GISP.Addin.ArcMap.Commands.TocCommand_ShowTocItemProperty"/> </Condition> </Path>
至此Toc控件Over,具体的右键菜单功能根据需求进行开发。
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号