.net中显示的树形结构,每次打开页面都遍历一边,输入的节点越多,IE占用的内存就越大,速度也就越慢。应该用什么方法可以解决呢?怎么限制遍历深度?谢谢!

解决方案 »

  1.   

    引用 4 楼 ustbwuyi 的回复:
    用异步加载,一次不要将所有的节点都遍历,只要遍历一级菜单即可,点击某个一级菜单的时候再用异步加载它下面的二级菜单 用递归。
      

  2.   

    一次性加载要用递归, 如果要分批加载就不用递归了。分批加载:
    1 先加载第一级节点, 并订阅SelectNodeChanged事件
    2 在SelectNodeChanged事件中, 检查子节点是否已经加载, 如果没有加载, 加载子节点, 订阅SelectNodeChanged事件。如果已经加载, 就无需重新加载。
      

  3.   

    楼上正解,我估计windows的浏览器也是这么做的。我所在公司的产品就用了类似的技术
    【签名】每个月总有那么几天,您的网络会受到黑客的攻击?坐立不安,烦躁无力,使用我和human开发的“月月舒”防火墙,超轻超薄,易于携带,提供由内到外的全方位保护,即使流量再大,也可以冲浪自如,再也不用担心侧漏啦。
    http://webtrados.008.net 网络小筑,常来坐坐。
      

  4.   

    TreeView 异步逐层加载就是异步加载吗?用到递归了吗?和一次性加载什么关系?
      

  5.   


    严格来说, 不应该叫做异步加载, 异步加载跟多线程有关。 
    我们所讨论的只是延迟加载, 就是,用到的时候再加载。
    省市联动的做法跟加载TreeView基本类似, 因为两个带有父子关系的列表框其实跟TreeView没有很大区别。区别是: 联动列表的子列表每次都要变化, 而TreeView不用。 如果要求好的用户体验, 可以用Ajax处理联动列表。
      

  6.   


    哦我这里省市是用TreeView做的,想问下gentle_wolf 省市联动的做法跟加载TreeView基本类似是什么意思?难道不是用TreeView?
      

  7.   

    好久不做Asp.net了。 代码应该不难。 自己写不行吗?
      

  8.   

    你的TreeView节点数据来自哪里?数据库么?那你把数据库的表加一个节点深度的字段,判断这个字段的值,如果大于你规定的深度,这个节点就不加载到TreeView
    这不就解决了
      

  9.   

    就是想看下大致是什么样子的代码
    恩是来自SQL
      

  10.   

    不用绑定  做成动态的就好了 
    绑定的话很限制灵活性的
    你OVERWRITE  TREEVIEW
    定义好每个节点就OK了
      

  11.   

    我把递归加载的代码给你, 延迟加载比递归加载简单多了。自己试验一下吧。using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using System.Web.UI.WebControls;
    using EastWind.Exceptions;namespace Web.Common.Utility
    {
        public delegate void TreeNodeLoadEventHandler(TreeNode tnCurrent, DataRow drCurrent);
        public delegate void TreeNodeViewEventHandler(TreeNode tnCurrent, params object[] userData);    public static class TreeHelper
        {
            /// <summary>
            /// 展开父辈节点
            /// </summary>
            public static void ExpandAncestor(TreeNode tnCurrent)
            {
                while (tnCurrent.Parent != null)
                {
                    tnCurrent.Expand();
                    tnCurrent = tnCurrent.Parent;                
                }
            }        /// <summary>
            /// 遍历树的节点
            /// </summary>
            /// <param name="treeView"></param>
            public static void IterateTreeNode(TreeView treeView,TreeNodeViewEventHandler hanlder,object[] userData)
            {
                foreach (TreeNode tnRoot in treeView.Nodes)
                {
                    hanlder(tnRoot,userData);
                    IterateTreeNode(tnRoot, hanlder, userData);
                }
            }        /// <summary>
            /// 设置树节点的行为
            /// </summary>
            /// <param name="treeView"></param>
            /// <param name="tnsa"></param>
            public static void SetTreeViewSelectAction(TreeView treeView, TreeNodeSelectAction tnsa)
            {
                IterateTreeNode(treeView, new TreeNodeViewEventHandler(SetSelectTreeNodeAction), new object[] { tnsa });
            }        /// <summary>
            /// 设置树节点的行为
            /// </summary>
            /// <param name="node"></param>
            /// <param name="data"></param>
            private static void SetSelectTreeNodeAction(TreeNode node, object[] data)
            {
                node.SelectAction = (TreeNodeSelectAction)data[0];
            }        /// <summary>
            /// 遍历当前节点的子节点
            /// </summary>
            /// <param name="tnCurrent"></param>
            /// <param name="hanlder"></param>
            public static void IterateTreeNode(TreeNode tnCurrent, TreeNodeViewEventHandler hanlder, object[] userData)
            {
                foreach (TreeNode child in tnCurrent.ChildNodes)
                {
                    hanlder(child,userData);
                    IterateTreeNode(child, hanlder,userData);
                }
            }        /// <summary>
            /// 加载数据到树视图中,value存放节点ID,text存放节点名称
            /// </summary>
            /// <param name="treeView">将被加载数据的树视图</param>
            /// <param name="dtSource">源数据表</param>
            /// <param name="parentColName">父列的名称</param>
            /// <param name="childColName">子列的名称</param>
            /// <param name="nodeNameCol">节点名称列名称</param>
            /// <param name="rootID">跟节点的父节点id</param>
            /// <param name="loaded">节点加载后调用用户方法</param>
            public static void LoadData2TreeView(TreeView treeView, DataTable dtSource, string parentColName, string childColName, string nodeNameCol, object rootID, TreeNodeLoadEventHandler loaded)
            {
                DataRow[] layer1Nodes = SelectDataRow(dtSource.DefaultView, parentColName , rootID);
                foreach (DataRow layer1Node in layer1Nodes)
                {
                    TreeNode tnRoot = new TreeNode();                tnRoot.Value = layer1Node[childColName].ToString();
                    tnRoot.Text = layer1Node[nodeNameCol].ToString();                treeView.Nodes.Add(tnRoot);                if (loaded != null)
                    {
                        loaded(tnRoot, layer1Node);
                    }                LoadData2TreeNode(layer1Node[childColName],tnRoot, dtSource, parentColName, childColName, nodeNameCol, loaded);
                }
            }        /// <summary>
            /// 加载数据到树节点中,value存放节点ID,text存放节点名称
            /// </summary>
            /// <param name="parentID">父节点id对象</param>
            /// <param name="tnParent">父节点名称</param>
            /// <param name="dtSource">源数据表</param>
            /// <param name="parentColName">父列的名称</param>
            /// <param name="childColName">子列的名称</param>
            /// <param name="nodeNameCol">节点名称列名称</param>
            /// <param name="loaded">节点加载后调用用户方法</param>
            public static void LoadData2TreeNode(object parentID, TreeNode tnParent, DataTable dtSource, string parentColName, string childColName, string nodeNameCol,TreeNodeLoadEventHandler loaded)
            {
                DataRow[] childRows = SelectDataRow(dtSource.DefaultView, parentColName ,parentID);
                foreach (DataRow childRow in childRows)
                {
                    TreeNode tnChild = new TreeNode();                tnChild.Value = childRow[childColName].ToString();
                    tnChild.Text = childRow[nodeNameCol].ToString();                tnParent.ChildNodes.Add(tnChild);                if (loaded != null)
                    {
                        loaded(tnChild, childRow);
                    }                LoadData2TreeNode(childRow[childColName], tnChild, dtSource, parentColName, childColName, nodeNameCol, loaded);
                }
            }        /// <summary>
            /// 加载数据到树视图中,value存放节点ID,text存放节点名称
            /// </summary>        
            /// <param name="treeView">将被加载数据的树视图</param>
            /// <param name="dtSource">源数据表</param>
            /// <param name="parentColName">父列的名称</param>
            /// <param name="childColName">子列的名称</param>
            /// <param name="nodeNameCol">节点名称列名称</param>
            /// <param name="rootID">跟节点的父节点id</param>
            public static void LoadData2TreeView(TreeView treeView, DataTable dtSource, string parentColName, string childColName, string nodeNameCol, object rootID)
            {
                LoadData2TreeView(treeView, dtSource, parentColName, childColName, nodeNameCol, rootID, null);
            }        /// <summary>
            /// 加载数据到树节点中,value存放节点ID,text存放节点名称
            /// </summary>
            /// <param name="tnParent">父节点名称</param>
            /// <param name="dtSource">源数据表</param>
            /// <param name="parentColName">父列的名称</param>
            /// <param name="childColName">子列的名称</param>
            /// <param name="nodeNameCol">节点名称列名称</param>
            public static void LoadData2TreeNode(object parentID, TreeNode tnParent, DataTable dtSource, string parentColName, string childColName, string nodeNameCol)
            {
                LoadData2TreeNode(parentID, tnParent, dtSource, parentColName, childColName, nodeNameCol, null);
            }        /// <summary>
            /// 从数据视图中选择数据行
            /// </summary>
            /// <param name="view">源视图</param>
            /// <param name="colName">条件列名称</param>
            /// <param name="value">值</param>
            /// <returns>复合条件的数据行</returns>
            public static DataRow[] SelectDataRow(DataView view, string colName, object value)
            {
                return SelectDataRow(view, new string[] { colName }, new object[] { value });
            }        /// <summary>
            /// 从数据视图中选择数据行
            /// </summary>
            /// <param name="view">源视图</param>
            /// <param name="colName">条件列名称</param>
            /// <param name="value">值</param>
            /// <returns>复合条件的数据行</returns>
            public static DataRow[] SelectDataRow(DataTable dtSource, string colName, object value)
            {
                return SelectDataRow(dtSource, new string[] { colName }, new object[] { value });
            }        /// <summary>
            /// 从数据表中选择数据行
            /// </summary>
            /// <param name="dtSource">源数据表</param>
            /// <param name="colNames">条件列名称列表</param>
            /// <param name="values">值列表</param>
            /// <returns>复合条件的数据行</returns>
            public static DataRow[] SelectDataRow(DataTable dtSource, string[] colNames, object[] values)
            {
                return SelectDataRow(dtSource.DefaultView, colNames, values);
            }        /// <summary>
            /// 从数据表中选择数据行
            /// </summary>
            /// <param name="view">源视图</param>
            /// <param name="colNames">条件列名称列表</param>
            /// <param name="values">值列表</param>
            /// <returns>复合条件的数据行</returns>
            public static DataRow[] SelectDataRow(DataView view, string[] colNames, object[] values)
            {
                if (colNames.Length != values.Length)
                {
                    throw new EastWindException("列与值必须一一对应");
                }            List<DataRow> rowList = new List<DataRow>();
                for (int i = 0, count = view.Count; i < count; i++)
                {
                    bool suit = true;
                    for (int j = 0; j < colNames.Length; j++)
                    {
                        if (!view[i][colNames[j]].Equals(values[j]))
                        {
                            suit = false;
                        }
                    }                if (suit)
                    {
                        rowList.Add(view[i].Row);
                    }
                }            return rowList.ToArray();
            }
        }
    }
      

  12.   

    谢谢gentle_wolf啊
    我想知道下代码里怎么控制递归的深度呢?
      

  13.   

    public static void LoadData2TreeNode(object parentID, TreeNode tnParent, DataTable dtSource, string parentColName, string childColName, string nodeNameCol,TreeNodeLoadEventHandler loaded, int depth
            { 
                if( ++depth > 100)
                {
                    throw new Exception("递归深度超过限制");
                }

                DataRow[] childRows = SelectDataRow(dtSource.DefaultView, parentColName ,parentID); 
                foreach (DataRow childRow in childRows) 
                { 
                    TreeNode tnChild = new TreeNode();                 tnChild.Value = childRow[childColName].ToString(); 
                    tnChild.Text = childRow[nodeNameCol].ToString();                 tnParent.ChildNodes.Add(tnChild);                 if (loaded != null) 
                    { 
                        loaded(tnChild, childRow); 
                    }                 LoadData2TreeNode(childRow[childColName], tnChild, dtSource, parentColName, childColName, nodeNameCol, loaded, depth); 
                } 
            } 
      

  14.   

    这是AJAX主要解决的问题。.NET里的TreeView,本来已经带了这个功能。
      

  15.   

    十分感谢gentle_wolf
    想问下在.NET里TreeView哪里有这个功能?