我想实现在一个树下工具节点名称找到节点的编号,属于skyline的二次开发,但整个过程应该主要是递归逻辑不清的问题,代码如下,我在100标记行判断是否找到目标,如果知道,则退出所以递归,将找到的对象的对应的ID返回,可是怎么调试都跳不出来,return之后还在循环体内,不知道逻辑哪里有错误,我将return改为break,试图用break终止循环,可似乎只终止本次调用的函数,完了之后还在循环体内。问题在哪呢,我是初学者,麻烦哪位大虾多指点一下,非常感谢!!!
/// <summary>
            /// 根据父节点号及子节点名称返回子节点ID
            /// </summary>
            /// <param name="iParentID">父节点ID</param>
            /// <param name="sObjectNM">子节点名称</param>
            /// <returns>子节点ID</returns>
            private static int _TraverseBranch(int iParentID, string sObjectNM)
            {
                try
                {
                    //Get the first child item of this group.
                    int iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.CHILD);
                    if (iChildID == 0)
                        return 0;                    //Start with the first child item and traverse
                    //all of the sibling items in that group.                    while (iChildID != 0)
                    {
                        if (InformationTree5.IsGroup(iChildID) > 0)
                        {
                            //If we are here, this tree item is a group.   
                            //A recursive call - traverse all of the tree items under this group.
                            _TraverseBranch(iChildID, sObjectNM);
                        }
                        else
                        {
                            //If we are here, this tree item is an object.                            //Get an interface to the object that this is its ID.
                            TerraExplorerX.ITerrainColoredObject5 pITEObject =
                                InformationTree5.GetObjectEx(iChildID, "") as TerraExplorerX.ITerrainColoredObject5;
                            string tmp = getItemName(iChildID); 100:                           if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
                                return iChildID;
                        }
                        iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.NEXT);
                    }
                    return iChildID;
                }
                catch (Exception ex)
                { return 0; }
            }

解决方案 »

  1.   

    直接用Find函数就行了,哪有那么麻烦啊
      

  2.   

                /// <summary>
                /// 根据父节点号及子节点名称返回子节点ID
                /// </summary>
                /// <param name="iParentID">父节点ID</param>
                /// <param name="sObjectNM">子节点名称</param>
                /// <returns>子节点ID</returns>
                private static int _TraverseBranch(int iParentID, string sObjectNM)
                {
                    try
                    {
                        //Get the first child item of this group.
                        int iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.CHILD);
                        if (iChildID == 0)
                            return 0;                    //Start with the first child item and traverse
                        //all of the sibling items in that group.                    if (iChildID != 0)
                        {
                            if (InformationTree5.IsGroup(iChildID) > 0)
                            {
                                //If we are here, this tree item is a group.   
                                //A recursive call - traverse all of the tree items under this group.
                                return _TraverseBranch(iChildID, sObjectNM);
                            }
                            else
                            {
                                //If we are here, this tree item is an object.                            //Get an interface to the object that this is its ID.
                                TerraExplorerX.ITerrainColoredObject5 pITEObject =
                                    InformationTree5.GetObjectEx(iChildID, "") as TerraExplorerX.ITerrainColoredObject5;
                                string tmp = getItemName(iChildID);                            if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
                                    return iChildID;
                            }
                            
                        }
                        
                    }
                    catch (Exception ex)
                    { return 0; }
                }
    递归相当于一个循环,你这里又使用了while,肯定有问题,上面的代码我没测试,我觉得思路没什么问题,你试试看
      

  3.   

    怎么不可以编辑的,最后一个分支漏了一句
    iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.NEXT);
    return _TraverseBranch(iChildID, sObjectNM);
    就是把这段if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
                                    return iChildID;
    改成if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
    {
           return iChildID;
    }else
    {
           iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.NEXT);
    return _TraverseBranch(iChildID, sObjectNM);}
      

  4.   

    谢谢各位,特别谢谢楼上的朋友;
    如此改了之后还是不行,为什么要用while呢,主要是只知道节点名称,需要不断的循环来查找到对象,如下图所示的节点图
      

  5.   

    把这个 if (iChildID == 0)
           return 0; 写在后面 如: else {return 0;} //while (iChildID != 0) 换成 if iChildID != 0 调试一下看看 
      

  6.   

    要实现找到一个匹配的节点就退出整个递归过程,可能需要改下面代码:       //If we are here, this tree item is a group.   
           //A recursive call - traverse all of the tree items under this group.
           int iFoundID = _TraverseBranch(iChildID, sObjectNM);
           if (iFoundID != 0) return iFoundID;
      

  7.   

    我这样变通处理了下,定义了属性,查到的话把查到的值付给这个属性。暂时凑合下解决一下问题,但愿能搞清楚这个地方逻辑到底是什么问题。再次感谢楼上的朋友。
    private static int iObjectID
                { get; set; }            /// <summary>
                /// 根据父节点号及子节点名称返回子节点ID
                /// </summary>
                /// <param name="iParentID">父节点ID</param>
                /// <param name="sObjectNM">子节点名称</param>
                /// <returns>子节点ID</returns>
                private static int _TraverseBranch(int iParentID, string sObjectNM)
                {
                    try
                    {
                        //Get the first child item of this group.
                        int iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.CHILD);
                        if (iChildID == 0)
                            return 0;                    //Start with the first child item and traverse
                        //all of the sibling items in that group.                    while (iChildID != 0)
                        {
                            if (InformationTree5.IsGroup(iChildID) > 0)
                            {
                                //If we are here, this tree item is a group.   
                                //A recursive call - traverse all of the tree items under this group.
                                _TraverseBranch(iChildID, sObjectNM);
                            }
                            else
                            {
                                //If we are here, this tree item is an object.                            //Get an interface to the object that this is its ID.
                                TerraExplorerX.ITerrainColoredObject5 pITEObject =
                                    InformationTree5.GetObjectEx(iChildID, "") as TerraExplorerX.ITerrainColoredObject5;
                                string tmp = getItemName(iChildID);                            if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
                                {
                                    iObjectID= iChildID;
                                    break;
                                }
                            }
                            iChildID = InformationTree5.GetNextItem(iChildID, ItemCode.NEXT);
                        }
                        return iChildID;
                    }
                    catch (Exception ex)
                    { return 0; }
                }
      

  8.   


    这个差不多了,lz试试看/// <summary>
            /// 根据父节点号及子节点名称返回子节点ID
            /// </summary>
            /// <param name="iParentID">父节点ID</param>
            /// <param name="sObjectNM">子节点名称</param>
            /// <returns>子节点ID</returns>
            private static bool _TraverseBranch(int iParentID, string sObjectNM, ref int resultID)
            {
                try
                {
                    if (InformationTree5.IsGroup(iParentID) > 0)
                    {
                        int iChildID = InformationTree5.GetNextItem(iParentID, ItemCode.CHILD);                     while (iChildID != 0)
                         {
                             bool isFound=_TraverseBranch(iChildID, sObjectNM,ref resultID);
                             if (isFound)
                             {
                                 return true;
                             }
                             else
                             {
                                 iChildID = InformationTree5.GetNextItem(iChildID, ItemCode.NEXT);
                             }
                         }
                    }
                    else
                    {
                        TerraExplorerX.ITerrainColoredObject5 pITEObject =
                                InformationTree5.GetObjectEx(iParentID, "") as TerraExplorerX.ITerrainColoredObject5;
                        string tmp = getItemName(iParentID);                    if ((tmp.Remove(tmp.Length - 1, 1)).Trim() == sObjectNM.Trim())
                        {
                            resultID = iParentID;
                            return true;
                        }               
                    }
                    return false;
                }
                catch (Exception ex)
                { return false; }
            }
      

  9.   

    非常感谢楼上的朋友,这样处理后,是对了。呵呵还是不太明白逻辑关系,调试时发现找到对象后,return true, 然后又执行了if(lFond)里执行了两次return true,不知道是怎么回事?
    好,分全给你了,再次谢谢啊!
      

  10.   

    这样啊,我再给你解释一下。
    首先第一个参数,iParentID,你的注释是父节点ID,这里我觉得没有必要是父节点,就是树中任意的一个节点,因为递归下去以后肯定要到叶子节点。
    然后第一个If就是判断该节点是否是叶子节点,如果是进行比较,匹配返回true,不匹配返回false,这个是递归结束条件,比较简单。
    如果不是叶子节点,那么对该节点的所有子节点进行递归,这里注意几个方面。因为要在所有子节点查找,所以要有while循环,同时如果已经找到不希望继续查找。
    对第一个子节点进行递归,找到返回true,这里就是你提到的为什么会几次执行return true,就是你递归几层就返回几层,一直到最上层,函数调用才结束。
    没有找到对下一个子节点进行递归,直到所有子节点结束,没有找到返回false,一直返回到最上层。递归本质也是函数调用,你可以自己把具体执行的堆栈画出来,这样对理解递归很有帮助。