提要:在VB
中
常將TreeView用來表示層次數據
但相關的與數據庫進行交互的代碼
需要大量的采用手工編碼;在中
由於數據綁定功能的加強及語言特性的增強
可以很容易的實現TreeView與層次數據的綁定
本文將首先建立一個繼承自TreeView的 dbTreeView
然後用一個單位(部門)的層次數據與dbTreeView進行數據綁定
並提供了與數據庫進行交互的代碼
從層次數據的表達方式開始
在本例中
部門表(department)中有五個字段
如下表:
字段名
字段
類型說明
ID
自動編號
Key
Code
String
編碼
Name
String
名稱
PID
Int
父結點的ID
CPtr
boolean
是否有子結點
繼承自TreeNode的myTreeNode
在myTreeNode中
新增了三個屬性
如下表:
屬性名
類型
說明
Value
Object
Key
PID
Object
父結點的ID
CPtr
Boolean
是否有子結點
在Init事件中
根據傳入的四個參數
設置這三個屬性和Text屬性
將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+
保證關健值唯一
Me
mDataView
Sort = Me
ValueMember
Me
m_MaxID = Me
GetValue(Me
mDataView
Count
)
End Sub
設置DisplayMember屬性的格式如:字段;字段;字段…
在設置屬性時將傳來的參數轉換為字符串數組mDisplayMember在檢索值時返回數據如:值 值 值…
Protected Overridable Function GetDisplay(ByVal Index As Integer) As Object
Dim i As Integer
Dim temp As String =
For i =
To mDisplayMember
Length
temp = temp & IIf(i >
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 =
To mDataView
Count()
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
實現數據與綁定控件的同步
要實現兩個方面的同步:
其它綁定控件(如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
在其它綁定控件改變了數據源後
更新樹結點
這個工作在觸發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
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
程序運行後界面如下:
相關代碼請參見源程序這裡不做詳述
需要注意的是刪除操作並沒有刪除子結點只是刪除當前結點而已刪除子結點的工作應該在存儲過程中遞歸實現而不應放在前端
From:http://tw.wingwit.com/Article/program/net/201311/13916.html