vb.net中层次数据绑定TreeView的实现

Posted on 2006-08-29 14:20  bean  阅读(2171)  评论(3)    收藏  举报

 

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

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

目录:

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

2、  继承自TreeNode的myTreeNode

3、  将dbTreeView绑定到数据源

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

5、  使用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

ValueMember

string

值成员(数据源[dataview]的列名)

DisplayMember

string

显示(在Text中)成员

PidMember

string

父ID成员

CPtrMember

string

是否有子结点

后四个属性对应myTreeNode的value,text,pid,cptr。

相关代码如下:  
 
<Category("Data")> 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

    
<Category("Data")> Protected Property PidMember() As String
        Get
            Return mPidMember
        End Get
        Set(ByVal Value As String)
            mPidMember 
= Value
        End Set
End Property

    
<Category("Data")> 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

程序运行后界面如下:

相关代码请参见源程序,这里不做详述,需要注意的是删除操作并没有删除子结点,只是删除当前结点而已,删除子结点的工作应该在存储过程中递归实现,而不应放在前端。


 代码下载:http://www.xpnsoft.com/data/dbtreesample.rar

第一次在园子里写东西,不足之处多指正。

我的网站:http://www.xpnsoft.com

我的邮箱:zuowu@163.com

欢迎交流!

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3