CurrencyManager 除存取繫結資料源外,尚可協調共用同一 DataSource 的多個控制項,確保停留在同一資料項。覆寫 OnAfterSelect,選取樹節點時設定 CurrencyManager.Position 為當前項索引。
自訂 TreeNode 類別 (TreeLeafNode/TreeGroupNode) 內建 Position 屬性儲存列表索引:
Protected Overrides Sub OnAfterSelect(ByVal e As TreeViewEventArgs)
Dim tln As TreeLeafNode
If TypeOf e.Node Is TreeGroupNode Then
tln = FindFirstLeafNode(e.Node)
RaiseEvent AfterGroupSelect(New GroupTreeViewEventArgs(e))
ElseIf TypeOf e.Node Is TreeLeafNode Then
RaiseEvent AfterLeafSelect(New LeafTreeViewEventArgs(e))
tln = CType(e.Node, TreeLeafNode)
End If
If Not tln Is Nothing AndAlso cm.Position <> tln.Position Then
cm.Position = tln.Position
End If
MyBase.OnAfterSelect(e)
End Sub
Private Function FindFirstLeafNode(ByVal currNode As TreeNode) As TreeLeafNode
If TypeOf currNode Is TreeLeafNode Then Return CType(currNode, TreeLeafNode)
If currNode.Nodes.Count > 0 Then Return FindFirstLeafNode(currNode.Nodes(0))
Return Nothing
End Function
CurrencyManager 引發三事件:PositionChanged、ItemChanged、CurrentChanged。採用 PositionChanged 變更選取節點:
Private Sub cm_PositionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles cm.PositionChanged
Dim tln As TreeLeafNode
If TypeOf Me.SelectedNode Is TreeLeafNode Then
tln = CType(Me.SelectedNode, TreeLeafNode)
Else
tln = FindFirstLeafNode(Me.SelectedNode)
End If
If tln.Position <> cm.Position Then
Me.SelectedNode = FindNodeByPosition(cm.Position)
End If
End Sub
Private Function FindNodeByPosition(ByVal index As Integer) As TreeNode
Return FindNodeByPosition(index, Me.Nodes)
End Function
Private Function FindNodeByPosition(ByVal index As Integer, ByVal NodesToSearch As TreeNodeCollection) As TreeNode
Dim i As Integer = 0
Do While i < NodesToSearch.Count
Dim currNode = NodesToSearch(i); i += 1
If TypeOf currNode Is TreeLeafNode Then
Dim tln = CType(currNode, TreeLeafNode)
If tln.Position = index Then Return currNode
Else
Dim found = FindNodeByPosition(index, currNode.Nodes)
If found IsNot Nothing Then Return found
End If
Loop
Return Nothing
End Function
建議若資料源支援 IBindingList,可改用 ListChanged 事件。