今天终于大概把树形的图层目录给解决了。前面一直卡壳卡在鼠标选择的矢量图层pTocFeatureLayer没有办法转换为IGroupLayer,一直都在提示pTocFeatureLayer为null。

但是无意间,也可能是逐渐理解了图层栏AxTOCControl和图层组的含义,网上没有现成的代码,于是我就自己摸索了一下。首先图层栏中的数据框Map是一个关键,这个可以通过axMapcontrol.Map获取Map对象,然后可以通过axMapcontrol.Map.AddLayer()方法来添加图层,于是可以实例化一个groupLayer对象:

IGroupLayer groupLayer = new GroupLayerClass();

然后通过axMapcontrol.Map.AddLayer(groupLayer)就在Map下面添加了一个图层组。有木有很简单,但是刚刚开始做的时候是一点头绪都没有。

紧接着,可以在groupLayer下面添加自己想要的图层:

groupLayer.Add(getLayer);

简单来说,要想在map中添加一个图层组,图层组中添加图层:

IGroupLayer groupLayer = new GroupLayerClass();
axMapcontrol.Map.AddLayer(groupLayer);
groupLayer.Add(Layer);

 

但是我在想啊,我是直接读取的shp文件然后加载显示啊,不能直接获取layera啊,这样的话图层栏里面会先加载出不是图层组的layer,但是这不在图层组下面啊,我想要的是把他搞到图层组下面去。就像下面

Arcengine图层栏制作图层树,把想显示的图层放在图层组中显示-LMLPHP

于是我又想啊,groupLayer对象有没有直接根据文件路径和文件名直接加载显示的方法呢。嘿嘿嘿,不好意思没有。于是就只能把通过读取文件显示的layer转移到图层组下面去。脑洞造起来~

我是这样解决的:首先直接通过文件路径和文件名加载图层,然后写了一个方法,遍历图层下面的layer,把想要显示的图层名传进去,如果在图层栏中找到了这个图层,就返回它。

 private ILayer GetLayersByName(string IN_Name)
            {
                IEnumLayer Temp_AllLayer = axMapcontrol.Map.Layers;
                ILayer Each_Layer = Temp_AllLayer.Next();
                while (Each_Layer != null)
                {
                    if (Each_Layer.Name.Contains(IN_Name))
                        return Each_Layer;
                    Each_Layer = Temp_AllLayer.Next();
                }
                return null;
            }

于是乎,我拿到了layer,使用groupLayer.Add(getLayer);就可以显示了。但出现问题了:这样单独的,不是图层组那个layer还在啊,所以还要考虑把它删掉。

我又写了一个DeleteLyersByName()方法,传想删除的图层名进去,遍历Map下面的layer,但是如果碰到的layer不是图层组的话,并且它的名字和图层组下面的那个layer的名字相同就删去。

 //根据图层名删除图层
            private void DeleteLyersByName(string IN_Name)
            {
                ILayer pL = null;
                for (int i = 0; i < axMapcontrol.LayerCount; i++)
                {
                    pL = axMapcontrol.get_Layer(i);
                    if (pL as IGroupLayer==null)
                    {
                        if (pL.Name.Contains(IN_Name))
                           axMapcontrol.Map.DeleteLayer(pL);
                    }
                }
            }

于是乎,这样就只剩下图层组了。但是问题又来了:怎么执行之后,图层栏中的图层没变勒??点图层前的+号刷新一下,可以了。但是直接添加一句:axTOCControl.Update();图层栏就正常显示了。

问题源源不断:我重复添加一个文件的时候,它会在图层栏重复的添加显示。。。。于是我又写了一个方法,哎,真的人艰不拆。

isLoadSameLayer(string IN_Name)方法,把图层名传进去,又遍历一下Map下面的图层,

 //遍历判断图层中是否已经加载了相应的图层
            private bool isLoadSameLayer(string IN_Name)
            {
                ILayer pL = null;
                string name = "";
                if (axMapcontrol.LayerCount != 0)
                {
                    for (int i = 0; i < axMapcontrol.LayerCount;i++ )
                    {
                        pL = axMapcontrol.get_Layer(i);//获取图层组和图层
                        if (pL is IGroupLayer)
                        {
                            ICompositeLayer pGroupLayer = pL as ICompositeLayer;
                            for (int j = 0; j < pGroupLayer.Count; j++)
                            {
                                name = pGroupLayer.get_Layer(j).Name;
                                if (IN_Name == name)
                                    return true;
                            }
                        }
                        else//如果不是图层组
                        {
                            name = pL.Name;
                            if (IN_Name == name)
                                return true;
                        }
                    }
                }
                return false;//默认没有加载相同的图层
            }

注意哦,使用pL = axMapcontrol.get_Layer(i)只会获取单独的图层和图层组,而不会获得图层组下面的图层。

使用ICompositeLayer pGroupLayer = pL as ICompositeLayer;获取图层组下面的图层,然后判断一下图层名和传进来的名字是不是一样的,一样的就不加载了,返回一个true,表明找到了。这样就不会重复加载了。

还有个问题(问题咋那么多呢),我删除图层得一个一个删啊,多费事啊,于是给map整个右键点击事件,添加一个移除所有图层的方法。具体如下

 // TOCControl的OnMouseDown事件
        private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
        {

            if (e.button == 2)//点击的是鼠标右键
            {
                esriTOCControlItem pItem = esriTOCControlItem.esriTOCControlItemNone;
                IBasicMap pMap = null;
                ILayer pLayer = null;
                object unk = null;
                object data = null;
                axTOCControl1.HitTest(e.x, e.y, ref pItem, ref pMap, ref pLayer, ref unk, ref data);
                pTocFeatureLayer = pLayer as IFeatureLayer;

                if (pItem == esriTOCControlItem.esriTOCControlItemLayer && pTocFeatureLayer != null)
                {
                    btnLayerSel.Enabled = !pTocFeatureLayer.Selectable;
                    btnLayerUnSel.Enabled = pTocFeatureLayer.Selectable;
                    contextMenuStrip1.Show(Control.MousePosition);
                }
                if (pItem == esriTOCControlItem.esriTOCControlItemMap)
                {
                    //btnLayerSel.Enabled = !pTocFeatureLayer.Selectable;
                    //btnLayerUnSel.Enabled = pTocFeatureLayer.Selectable;
                    contextMenuStrip2.Show(Control.MousePosition);
                }

            }

        }

在axTOCControl1_OnMouseDown事件中,如果点击的是右键,通过pItem == esriTOCControlItem.esriTOCControlItemMap判断一下是不是点击的map,是的话就把contextMenuStrip2给关联上去。

Arcengine图层栏制作图层树,把想显示的图层放在图层组中显示-LMLPHP

 private void 移除所有图层ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("是否删除所有图层", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);

            if (result == DialogResult.OK)
            {
                axMapControl1.Map.ClearLayers();
                ClearPCLayerLock();
                axTOCControl1.Update();//更新图层栏图表信息
            }
        }

然后在contextMenuStrip2新建一个移除所有图层功能,axMapControl1.Map.ClearLayers();,同样使用这句话后,图层栏是不会有任何变化的,需要添加axTOCControl1.Update();

至此这个就差不多做好了。

最后将显示的选择界面和部分代码贴上

Arcengine图层栏制作图层树,把想显示的图层放在图层组中显示-LMLPHP

public void ShowMap()
{
    ....//遍历找到了相应的文件
     if (sameFile == true)
                    {
                        string findFile = findFileName.Substring(0, findFileName.IndexOf('.'));//去除文件名中.shp字符串,目的是为了根据这个名字操作后面的图层组名字
                        //bool isFindSameLayerGroup = FindSameLyersByName(findFileName);//新建图层组
                        if (findFile == "ARESIDENTIAL" || findFile == "ASOIL" || findFile == "AVEGETATION" || findFile == "AWATER")
                        {
                            if (!isLoadSameLayer(findFile))//如果没有加载相同的图层就加载
                            {
                                IGroupLayer groupLayer = new GroupLayerClass();
                                string layerGroupName = "";//将英文要素名翻译成中文

                                axMapcontrol.Map.AddLayer(groupLayer);
                                switch (findFile)
                                {
                                    case "ARESIDENTIAL": layerGroupName = "居民地";
                                        break;
                                    case "ASOIL": layerGroupName = "土壤";
                                        break;
                                    case "AVEGETATION": layerGroupName = "植被";
                                        break;
                                    case "AWATER": layerGroupName = "水系";
                                        break;
                                    default:
                                        break;
                                }
                                groupLayer.Name = layerGroupName;

                                axMapcontrol.AddShapeFile(path, findFileName);//根据路径和名称添加图层
                                ILayer getLayer = GetLayersByName(findFile);//根据文件名获得图层栏中相应名字的图层
                                groupLayer.Add(getLayer);//在图层组中添加这个图层
                                //这里不用考虑是否需要通过改变其中某一个的图层名来进行删除,因为改变的话他们的图层名都会被改变
                                DeleteLyersByName(findFile); //删除单独的图层,留下图层组
                            }
                        }
                        else
                        {
                            axMapcontrol.AddShapeFile(path, findFileName);
                        }
                    }
}

最后成果:

Arcengine图层栏制作图层树,把想显示的图层放在图层组中显示-LMLPHP

10-07 20:03