最近一直在使用DevExpress的TreeList控件,以按设计需求展示企业的供应商层级结构,但该企业集中了整个亚太地区的需求,有的市场中表示层级关系的数据达百万级。
且各个市场存在不同特性的层级,例如有的市场分区这一层很多,有几千甚至上万条数据,而这一层在其他市场上仅有几个节点。
而且即便在同一个市场区域,树中节点的分布极不均衡,同一子层,有的节点下仅几个数据,而有的节点下上万个子节点。
同时需求要求动态加载层级,即可通过设置将某些层设为不展示。这导致不便使用DataTable加载树的数据源。
并且在加载节点时还需根据其他数据对该节点做图片、状态、行为等的设置。
因此只有使用AppendNode()加载节点,使用过程中发现了性能上的一些区别。
注意点:
1. 在某一层次上做加载时,应在AppendNode之前做TreeList.BeginUnboundLoad()动作,并在这一批节点加载之后,再调用TreeList.EndUnboundLoad()。这对动作不宜过于频繁,但必须在加载该新节点的子节点前调用,确保该新节点加载到了树上,否则它的子节点不一定能找到这个父节点。
2. 另外要注意TreeList.AppendNode(object nodeData, int parentNodeId)和TreeList.AppendNode(object nodeData, TreeListNode parentNode)这两个函数的性能差异。
在较少节点加载的情况下,它们差异不明显。而在大数据量节点的加载过程中,它们的性能差异就很明显了。
其中根据parentNodeId加载耗时要明显高于直接通过parentNode加载耗时。
例如同样2000个节点的加载和相同的节点处理,前者可能耗时达千毫秒左右,而后者仅为十毫秒级别。
试想父层即有几千上万个节点的情况,然后循环父层节点加载同样可能部分节点多达几千个的情况,性能差异就放大更多了。
还没有仔细研究DevExpress中两个方法的差异。我猜测前者可能还需要通过parentNodeId去遍历节点找到这个父节点。
在这个过程中有多余时间损耗。因此推荐尽可能使用后者方法。
至于其他绑定DataTable前需解绑数据源,将其DataSource置为空等就不多说了,仅仅稍作记录,以备后需。