Treeview控件的Node节点延迟加载
Treeview控件是一个很常用的控件,用于展示资源或者组织结构的时候很方便,通常会在系统启动时进行资源的加载和节点目录的初始化,但在资源较多和层级较深的情况下,所有节点加载出来会耗费太多时间,影响体验,而用户并非每次都关注所有节点,于是想到了一个简单的优化方法:节点的延迟加载...
解决思路:
1.在节点加载时,对于下级资源(下级节点)较多的父节点,不必立即添加所有子节点,只需要添加一个无关的空节点,同时显示一个“虚假的”加号(+)效果;
2.待用户双击该父节点或者是点击节点前的+号,展开该节点的时候,立即去刷新和加载该节点的下级资源。
实现代码摘录:
1 List<smBusinessDB> allList = smBusinessDB.GetAll(); 2 resourcePad.DataTree.BeginUpdate(); 3 foreach (smBusinessDB businessDB in allList) 4 { 5 //根据业务库属性来决定是否延迟加载 6 bool IsToLoadAll = !businessDB.BusinessDBInfo.IsLazyLoad; 7 businessDB.LoadSubResource(IsToLoadAll); 8 resourcePad.AddNode(null, businessDB as IDataResource); 9 } 10 resourcePad.DataTree.EndUpdate(); 11 12 /// <summary> 13 /// 添加资源节点(自动递归添加下级资源节点) 14 /// </summary> 15 /// <param name="parentNode">父节点</param> 16 /// <param name="resource">资源对象</param> 17 public void AddNode(TreeNode parentNode, IDataResource resource) 18 { 19 if (resource == null) 20 return; 21 //在资源节点中不显示图层和图层目录 22 if (resource is smMapLayerDirectory || resource is smMapLayer || resource is smMapBookmark) 23 return; 24 //如果不是成果数据源(过程数据源或历史数据源),也不在面板中显示 25 if (resource is smDatasource && (resource as smDatasource).IsProdectDatasource == false) 26 return; 27 TreeNode oNode = CreateNode(resource); 28 if (parentNode == null) 29 this.tvResource.Nodes.Add(oNode); 30 else 31 parentNode.Nodes.Add(oNode); 32 foreach (IDataResource sub in resource.SubResource) 33 { 34 AddNode(oNode, sub); 35 //展开第一级节点 36 if (parentNode == null) 37 oNode.Expand(); 38 } 39 //-------- 如果节点未加载下级资源,则添加空节点,以形成“虚假的”+号效果 ---------- 40 if (resource.SubResource.Count == 0 && resource.IsLoadTopChild == false) 41 { 42 TreeNode emptyNode = new TreeNode(); 43 oNode.Nodes.Add(emptyNode); 44 } 45 } 46 47 .... 48 //节点展开事件(如果下级未加载,则加载并刷新) 49 this.tvResource.BeforeExpand += new TreeViewCancelEventHandler(tvResource_BeforeExpand); 50 51 void tvResource_BeforeExpand(object sender, TreeViewCancelEventArgs e) 52 { 53 TreeNode selNode = e.Node; 54 IDataResource nodeResource = selNode.Tag as IDataResource; 55 if (nodeResource == null) 56 return; 57 if (!nodeResource.IsLoadTopChild) 58 { 59 nodeResource.LoadSubResource(false); 60 RefreshNode(nodeResource, true); 61 selNode.Expand(); 62 } 63 }
效果截图:
1.节点展开前
2.节点展开后
以上截图示例中,Treeview控件的第一个root节点是普通加载,第二个root节点是延迟加载。
问题和待改进之处:
1.这样的解决方法,在本身无下级节点的时候,也会显示一个“虚假的”+号在节点前面,当用户点击的一瞬间才会消失,有点儿被“欺骗”的感觉,哈哈,但似乎也只能这样,否则不符合延迟加载;
2.在特别大的数据量的时候,如果某个节点下的子节点非常多,仍然会使加载和刷新该节点时候系统开销增大,影响流畅性,可考虑使用异步或者多线程。
欢迎补充和拍砖:)