Protected Property DataSource() As Object Get Return mDataView End Get
Set(ByVal Value As Object) If Value Is Nothing Then Else mDataView = Value cm = CType(Me.BindingContext(mDataView), CurrencyManager) UpdateTreeView() End If End Set End Property
Protected Property PidMember() As String Get Return mPidMember End Get Set(ByVal Value As String) mPidMember = Value End Set End Property
Protected Property DisplayMember() As String Get Return Join(mDisplayMember, SplitChar) End Get Set(ByVal Value As String) mDisplayMember = Split(Value, SplitChar) End Set End Property
'注意,这几个属性都是保护成员,必须在Init事件中设置:
Public Sub Init(ByVal dispmember As String, ByVal valuemember As String, ByVal pidmember As String, ByVal cptrmember As String, ByVal datasource As DataView) Me.ValueMember = valuemember Me.DisplayMember = dispmember Me.PidMember = pidmember Me.CPtrMember = cptrmember Me.DataSource = datasource '取value最大值,新增时将value+1,保证关健值唯一。 Me.mDataView.Sort = Me.ValueMember Me.m_MaxID = Me.GetValue(Me.mDataView.Count - 1) End Sub
Protected Overridable Function GetDisplay(ByVal Index As Integer) As Object Dim i As Integer Dim temp As String = "" For i = 0 To mDisplayMember.Length - 1 temp = temp & IIf(i > 0, LinkChar, "") & mDataView(Index)(mDisplayMember(i)) Next Return temp End Function
Private Sub FillTree(ByRef pnode As myTreeNode, Optional ByVal filter As String = "") mDataView.RowFilter = filter Dim i As Integer, icol As Integer Dim newnode As myTreeNode RemoveHandler cm.PositionChanged, AddressOf cm_PositionChanged Me.BeginUpdate() For i = 0 To mDataView.Count() - 1 newnode = New myTreeNode(GetDisplay(i), GetValue(i), GetPid(i), GetCPtr(i)) '当有子结点时,为这个结点添加一个空子结点 If newnode.CPtr Then Dim nullnode As New myTreeNode() nullnode.Value = NoExpandNodeValue newnode.Nodes.Add(nullnode) End If If pnode Is Nothing Then Me.Nodes.Clear() Me.Nodes.Add(newnode) Else pnode.Nodes.Add(newnode) End If Next Me.EndUpdate() mDataView.RowFilter = "" AddHandler cm.PositionChanged, AddressOf cm_PositionChanged End Sub
在展开有子结点的结点前,删除所有子结点,再用FillTree为待展开结点新增子结点。
Private Sub dbTreeView_BeforeExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles MyBase.BeforeExpand '当是新增结点引起BeforeExpand事件时,直接退出。 If ExpandWhenAddNode Then Exit Sub '在展开结点前更新子结点 Dim currentnode As myTreeNode = CType(e.Node, myTreeNode) With currentnode .Nodes.Clear() FillTree(currentnode, mPidMember & "= " & CInt(.Value)) End With End Sub
4、实现数据与绑定控件的同步
要实现两个方面的同步:
1、 其它绑定控件(如textbox等)应与TreeView当前结点所指向的记录位置一致。
Private Sub dbTreeView_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles MyBase.AfterSelect
If e.Node Is Nothing Then Exit Sub '定位到position cm.Position = GetPosition(CType(e.Node, myTreeNode).Value) If AllowEdit Then oldNode = e.Node oldPos = cm.Position End If End Sub
Public Sub cm_PositionChanged(ByVal sender As Object, ByVal e As System.EventArgs) If CType(Me.SelectedNode, myTreeNode).Value <> GetValue(cm.Position) Then Debug.WriteLine("Current node isn't correct point to currencymanager.position!") Me.SelectedNode = FindNodeByValue(GetValue(cm.Position), Me.Nodes) End If If AllowEdit Then If Me.SelectedNode Is Nothing AndAlso cm.Position = cm.Count - 1 Then '当新增记录时,新增树结点 If CType(cm.Current, DataRowView).IsNew Then Me.SelectedNode = AddNode(cm.Position) Exit Sub End If End If If Not oldNode Is Nothing Then If CType(oldNode, myTreeNode).Value = GetValue(oldPos) Then '更新老结点 oldNode.Text = GetDisplay(oldPos) Else End If End If End If End Sub