通常,节点被组织为树状结构。 基本上,在这种情况下需要编写递归代码来访问的所有节点。 XtraTreeList 提供了 节点迭代器 技术,允许避免编写递归代码,并使遍历节点成为平凡的任务。 本主题提供了 节点迭代器 的概述和几个使用示例。
节点迭代器概述
节点迭代器 是一个可以通过树状列表的 TreeList.NodesIterator 属性访问的对象。 此对象可以遍历已经排列为树的节点 (它执行递归代码来完成此任务)。 因此您不需要编写任何代码来实现此目的。 您需要做的唯一事情是处理被访问的每个节点。 需要执行下列步骤:
- 创建一个操作类 —— TreeListOperation 类的子类。 在创建操作类时要做的主要事情是重写 TreeListOperation.Execute 方法,每次当节点被访问时都自动调用此方法。 然后把被访问的节点作为参数传递到此方法。
- 调用 节点迭代器 的 TreeListNodesIterator.DoOperation 或 TreeListNodesIterator.DoLocalOperation 方法,并传递操作对象作为其参数。 这两个方法处理节点的范围不同。 第一个方法扫描控件中的所有节点; 第二个方法只扫描由调用参数所指定父节点的子树节点。
稍后在本主题中描述由 节点迭代器 提供的更多功能。
示例
下面的示例展示了如何使用 节点迭代器 获取位于指定嵌套层级上的节点数目。 在本示例中,创建了一个用于计算节点数目的 CustomNodeOperation 对象。 这个操作类包含一个内部计数器,每次当位于指定嵌套层级上的节点被访问时,此计数器都会被递增 1。
为了获取位于指定嵌套层级上的节点总数,创建了 CustomNodeOperation 类的一个实例,并传递给 TreeListNodesIterator.DoLocalOperation 方法。 在此方法执行完毕之后,读取 CustomNodeOperation.NodeCount 属性来获得节点数目。
C# | 复制代码 |
---|---|
using DevExpress.XtraTreeList.Nodes; using DevExpress.XtraTreeList.Nodes.Operations; // Declaring the custom operation class. class CustomNodeOperation : TreeListOperation { int level; int nodeCount; public CustomNodeOperation(int level) : base() { this.level = level; this.nodeCount = 0; } public override void Execute(TreeListNode node) { if(node.Level == level) nodeCount++; } public int NodeCount { get { return nodeCount; } } } // ... CustomNodeOperation operation = new CustomNodeOperation(2); treeList1.NodesIterator.DoLocalOperation(operation, treeList1.Nodes); int totalNodesAtSecondLevel = operation.NodeCount; |
Visual Basic | 复制代码 |
---|---|
Imports DevExpress.XtraTreeList.Nodes Imports DevExpress.XtraTreeList.Nodes.Operations ' Declaring the custom operation class. Class CustomNodeOperation Inherits TreeListOperation Private level As Integer Private nodeCount As Integer Public Sub New(ByVal level As Integer) Me.level = level Me.nodeCount = 0 End Sub 'New Public Overrides Sub Execute(ByVal node As TreeListNode) If node.Level = level Then nodeCount += 1 End If End Sub 'Execute Public ReadOnly Property NodeCount() As Integer Get Return nodeCount End Get End Property End Class '... Dim operation As CustomNodeOperation = New CustomNodeOperation(2) TreeList1.NodesIterator.DoLocalOperation(operation, TreeList1.Nodes) Dim totalNodesAtSecondLevel As Integer = operation.NodeCount |
节点迭代器的扩展功能
在创建操作类时,也可以重写其他 TreeListOperation 的属性和方法,以实现额外的功能:
TreeListOperation 成员 | 说明 |
---|---|
TreeListOperation.NeedsFullIteration 属性 |
如果此属性返回 false,则只访问有子节点的节点。 否则 节点迭代器 访问给定范围内的所有节点。 在 TreeListOperation 类中已经实现此属性并返回 true。 因此如果需要遍历节点而不考虑它们是否有子节点,则不需要重写它。 在重写 TreeListOperation.Execute 方法时,也可以人工检查被处理的节点是否有子节点。 在这种情况下,会需要更多的时间来完成操作,这是因为迭代器仍然访问每个节点,并为每个节点调用 TreeListOperation.Execute 方法。 但是,如果需要执行只处理父节点的操作 (例如展开和折叠特定的节点),则重写 TreeListOperation.NeedsFullIteration 属性可以提升性能。 |
TreeListOperation.NeedsVisitChildren 方法 |
每次访问包含子节点的节点时都调用此方法。 然后把被父节点作为参数传递到 TreeListOperation.NeedsVisitChildren 方法,此方法在执行检查之后返回一个 Boolean 值。 返回值取决于 TreeListOperation.NeedsFullIteration 属性值。 如果此属性值被设置为 true,则此方法返回一个值指明是否需要访问指定节点的所有子节点。 否则,此方法返回一个值指明父节点及其子节点是否应被处理。 重写 TreeListOperation.NeedsVisitChildren 方法可以提升应用程序的性能。 例如,可能只需要处理位于前两个层级中的节点。 在这种情况下,TreeListOperation.NeedsVisitChildren 方法为每个位于第二层级中的父节点返回 false,从而不处理更低层级的节点。 |
TreeListOperation.CanContinueIteration 方法。 |
在 TreeListOperation.Execute 方法中实现的操作被执行之前调用本方法。 在 TreeListOperation 类中实现了 TreeListOperation.CanContinueIteration 方法并返回 true。 意思是在所有节点都被处理之后停止迭代。 如果此方法返回 false,则停止迭代处理。 重写此方法是很有用的,例如,当实现节点搜索时。 |
TreeListOperation.FinalizeOperation 方法。 |
可以重写此方法来执行最后的操作,以及释放所分配的资源。 |
示例
下面的示例展示了如何创建一个操作类,折叠子节点中不包含指定节点的所有节点。 结果只有该节点的父节点被展开。
这个操作类接受节点作为它的构造函数的参数,并把节点存储到一个内部字段中。 Execute 方法检查被处理的节点是否包含指定的节点作为子节点。 如果不包含,则折叠被处理的节点。 在操作类中也重写了 TreeListOperation.NeedsFullIteration 属性,仅处理有子节点的节点。 当使用大型而复杂的节点结构时,这样处理能提升性能。
下面的插图展示了在执行示例代码之前和之后的树状列表:
C# | 复制代码 |
---|---|
using DevExpress.XtraTreeList.Nodes; using DevExpress.XtraTreeList.Nodes.Operations; public class CollapseExceptSpecifiedOperation : TreeListOperation { TreeListNode visibleNode; public CollapseExceptSpecifiedOperation(TreeListNode visibleNode) : base() { this.visibleNode = visibleNode; } public override void Execute(TreeListNode node) { if (!visibleNode.HasAsParent(node)) node.Expanded = false; } public override bool NeedsFullIteration { get { return false; } } } //... treeList1.NodesIterator.DoOperation(new CollapseExceptSpecifiedOperation(treeList1.FocusedNode)); |
Visual Basic | 复制代码 |
---|---|
Imports DevExpress.XtraTreeList.Nodes Imports DevExpress.XtraTreeList.Nodes.Operations Public Class CollapseExceptSpecifiedOperation Inherits TreeListOperation Private visibleNode As TreeListNode Public Sub New(ByVal visibleNode As TreeListNode) Me.visibleNode = visibleNode End Sub 'New Public Overrides Sub Execute(ByVal node As TreeListNode) If Not visibleNode.HasAsParent(node) Then node.Expanded = False End If End Sub 'Execute Public Overrides ReadOnly Property NeedsFullIteration() As Boolean Get Return False End Get End Property End Class '... TreeList1.NodesIterator.DoOperation(New CollapseExceptSpecifiedOperation(TreeList1.FocusedNode)) |