程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB.NET >> VB.NET中層次數據綁定TreeView的實現

VB.NET中層次數據綁定TreeView的實現

編輯:VB.NET

提要:在VB6中,常將TreeView用來表示層次數據,但相關的與數據庫進行交互的代碼,需要大量的采用手工編碼;在VB.net中,由於數據綁定功能的加強及語言特性的增強,可以很容易的實現TreeView與層次數據的綁定,本文將首先建立一個繼承自TreeView的 dbTreeView,然後用一個單位(部門)的層次數據與dbTreeView進行數據綁定,並提供了與數據庫進行交互的代碼。

1、從層次數據的表達方式開始

在本例中,部門表(department)中有五個字段,如下表:

字段名 字段 類型說明 ID 自動編號 Key Code String 編碼 Name String 名稱 PID Int 父結點的ID CPtr boolean 是否有子結點   

2、繼承自TreeNode的myTreeNode

在myTreeNode中,新增了三個屬性,如下表:

屬性名 類型 說明 Value Object Key PID Object 父結點的ID CPtr Boolean 是否有子結點   

在Init事件中,根據傳入的四個參數,設置這三個屬性和Text屬性。

3、將dbTreeView綁定到數據源

屬性名 類型 說明 Datasource dataview dbTreeVIew的數據源使用dataview,而不是object Value Member string值成員(數據源[dataview]的列名) Display Member string顯示(在Text中)成員 Pid Member string父ID成員 CPtr Member string是否有子結點   

後四個屬性對應myTreeNode的value,text,pid,cptr。

相關代碼如下:

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

設置DisplayMember屬性的格式如:字段1;字段2;字段3…

在設置屬性時,將傳來的參數轉換為字符串數組mDisplayMember,在檢索值時返回數據如:值1 值2 值3.…

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

其它檢索值的函數請參見源程序。

生成樹

UpdateTreeView調用私有方法FillTree來生成樹,需要注意的,FillTree只是生成指定結點的子結點並將其添加到指定結點,而不是一次就將所有結點添加到樹中,如果未指定結點(第一次填充時),只是添加頂層結點。

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

2、在其它綁定控件改變了數據源後,更新樹結點,這個工作在觸發CurrencyManager的PositionChanged事件時進行。

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

使用dbTreeView

程序運行後界面如下:

相關代碼請參見源程序,這裡不做詳述,

需要注意的是刪除操作並沒有刪除子結點,只是刪除當前結點而已,刪除子結點的工作應該在存儲過程中遞歸實現,而不應放在前端。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved