這個系列好久沒有更新了,時間拖得太久了,一來是工作確實忙,出差比較多;二來,最近公司有點動盪,部門獨立出來成立一個公司,有些其他事情耽擱了;三來,懶。這篇文章將介紹一下圖層樹,圖層樹的英文簡寫是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,具體的右鍵菜單功能根據需求進行開發。
