vb.net

位置:IT落伍者 >> vb.net >> 浏览文章

VB.NET中层次数据绑定TreeView的实现


发布日期:2022年02月15日
 
VB.NET中层次数据绑定TreeView的实现
提要:在VB常将TreeView用来表示层次数据但相关的与数据库进行交互的代码需要大量的采用手工编码;在中由于数据绑定功能的加强及语言特性的增强可以很容易的实现TreeView与层次数据的绑定本文将首先建立一个继承自TreeView的 dbTreeView然后用一个单位(部门)的层次数据与dbTreeView进行数据绑定并提供了与数据库进行交互的代码

从层次数据的表达方式开始

在本例中部门表(department)中有五个字段如下表:

字段名字段类型说明ID自动编号KeyCodeString编码NameString名称PIDInt父结点的IDCPtrboolean是否有子结点

继承自TreeNode的myTreeNode

在myTreeNode中新增了三个属性如下表:

属性名类型说明ValueObjectKeyPIDObject父结点的IDCPtrBoolean是否有子结点

在Init事件中根据传入的四个参数设置这三个属性和Text属性

将dbTreeView绑定到数据源

属性名类型说明DatasourcedataviewdbTreeVIew的数据源使用dataview而不是objectValueMemberstring值成员(数据源[dataview]的列名)DisplayMemberstring显示(在Text中)成员PidMemberstring父ID成员CPtrMemberstring是否有子结点

后四个属性对应myTreeNode的valuetextpidcptr

相关代码如下:

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(MeBindingContext(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)

MeValueMember = valuemember

MeDisplayMember = dispmember

MePidMember = pidmember

MeCPtrMember = cptrmember

MeDataSource = datasource

取value最大值新增时将value+保证关健值唯一

MemDataViewSort = MeValueMember

Mem_MaxID = MeGetValue(MemDataViewCount )

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 mDisplayMemberLength

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 = )

mDataViewRowFilter = filter

Dim i As Integer icol As Integer

Dim newnode As myTreeNode

RemoveHandler cmPositionChanged AddressOf cm_PositionChanged

MeBeginUpdate()

For i = To mDataViewCount()

newnode = New myTreeNode(GetDisplay(i) GetValue(i) GetPid(i) GetCPtr(i))

当有子结点时为这个结点添加一个空子结点

If newnodeCPtr Then

Dim nullnode As New myTreeNode()

nullnodeValue = NoExpandNodeValue

newnodeNodesAdd(nullnode)

End If

If pnode Is Nothing Then

MeNodesClear()

MeNodesAdd(newnode)

Else

pnodeNodesAdd(newnode)

End If

Next

MeEndUpdate()

mDataViewRowFilter =

AddHandler cmPositionChanged AddressOf cm_PositionChanged

End Sub

在展开有子结点的结点前删除所有子结点再用FillTree为待展开结点新增子结点

Private Sub dbTreeView_BeforeExpand(ByVal sender As Object ByVal e As SystemWindowsFormsTreeViewCancelEventArgs) Handles MyBaseBeforeExpand

当是新增结点引起BeforeExpand事件时直接退出

If ExpandWhenAddNode Then Exit Sub

在展开结点前更新子结点

Dim currentnode As myTreeNode = CType(eNode myTreeNode)

With currentnode

NodesClear()

FillTree(currentnode mPidMember & = & CInt(Value))

End With

End Sub

实现数据与绑定控件的同步

要实现两个方面的同步:

其它绑定控件(如textbox等)应与TreeView当前结点所指向的记录位置一致

Private Sub dbTreeView_AfterSelect(ByVal sender As Object ByVal e As SystemWindowsFormsTreeViewEventArgs) Handles MyBaseAfterSelect

If eNode Is Nothing Then Exit Sub

定位到position

cmPosition = GetPosition(CType(eNode myTreeNode)Value)

If AllowEdit Then

oldNode = eNode

oldPos = cmPosition

End If

End Sub

在其它绑定控件改变了数据源后更新树结点这个工作在触发CurrencyManager的PositionChanged事件时进行

Public Sub cm_PositionChanged(ByVal sender As Object ByVal e As SystemEventArgs)

If CType(MeSelectedNode myTreeNode)Value <> GetValue(cmPosition) Then

DebugWriteLine(Current node isnt correct point to currencymanagerposition!)

MeSelectedNode = FindNodeByValue(GetValue(cmPosition) MeNodes)

End If

If AllowEdit Then

If MeSelectedNode Is Nothing AndAlso cmPosition = cmCount Then

当新增记录时新增树结点

If CType(cmCurrent DataRowView)IsNew Then

MeSelectedNode = AddNode(cmPosition)

Exit Sub

End If

End If

If Not oldNode Is Nothing Then

If CType(oldNode myTreeNode)Value = GetValue(oldPos) Then

更新老结点

oldNodeText = GetDisplay(oldPos)

Else

End If

End If

End If

End Sub

使用dbTreeView

程序运行后界面如下:

相关代码请参见源程序这里不做详述

需要注意的是删除操作并没有删除子结点只是删除当前结点而已删除子结点的工作应该在存储过程中递归实现而不应放在前端

               

上一篇:如何用VB.NET Timer控件按设定的间隔完成动作

下一篇:VB.NET 中的组件开发源代码剖析