麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > Visual Basic > 正文

TreeView控件的設(shè)計(jì)實(shí)例

2023-06-12 12:11:28
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本文重點(diǎn)講解了TreeView控件的使用方法。TreeView控件具有豐富的功能,可以運(yùn)用到很多場(chǎng)合。摘要:講述了如何向 TreeView 控件添加數(shù)據(jù)綁定功能,它是一系列 Microsoft Windows 控件開(kāi)發(fā)示例之一。您可以將本文與相關(guān)的概述文章結(jié)合起來(lái)閱讀。

簡(jiǎn)介

在可能的情況下,您應(yīng)該先使用些現(xiàn)成的控件;因?yàn)樘峁┑?Microsoft® Windows® 窗體控件中包含大量編碼和測(cè)試成果,如果您要放棄它們從頭開(kāi)始,無(wú)疑是一種巨大的浪費(fèi)。基于此,在本例中,我將繼承一個(gè)現(xiàn)有 Windows 窗體控件 TreeView ,然后對(duì)其進(jìn)行自定義。在下載該 TreeView 控件的代碼時(shí),您還會(huì)得到附加的控件開(kāi)發(fā)示例,以及一個(gè)演示如何與其他數(shù)據(jù)綁定控件一起使用該增強(qiáng) TreeView 的示例應(yīng)用程序。

設(shè)計(jì)數(shù)據(jù)綁定樹(shù)視圖

對(duì)于 Windows 開(kāi)發(fā)人員來(lái)說(shuō),向 TreeView 控件添加數(shù)據(jù)綁定是經(jīng)常會(huì)遇到的問(wèn)題,但由于 TreeView 和其他控件(如 ListBoxDataGrid)存在一個(gè)主要差別(即 TreeView 顯示分層數(shù)據(jù)),因而基本控件目前還不支持此功能(也就是說(shuō),我們還必須使用它)。給定一個(gè)數(shù)據(jù)表,您就會(huì)很清楚如何在 ListBoxDataGrid 中顯示該信息,但利用 TreeView 的分層特點(diǎn)來(lái)顯示同樣的數(shù)據(jù)就不那么簡(jiǎn)單明了。就個(gè)人而言,我在使用 TreeView 顯示數(shù)據(jù)時(shí)曾應(yīng)用過(guò)許多不同的方法,但有一種方法最常用:按某些字段將表中的數(shù)據(jù)分組,如圖 1 所示。

圖 1:在 TreeView 中顯示數(shù)據(jù)

  在本例中,我將創(chuàng)建一個(gè) TreeView 控件,在該控件中可傳遞一個(gè)平面數(shù)據(jù)集(如圖 2 所示),并可輕松地生成圖 1 所示的結(jié)果。

圖 2:平面結(jié)果集,包含創(chuàng)建圖 1 所示的樹(shù)所需的所有信息

  在開(kāi)始編碼之前,我為新控件想出了一個(gè)可以處理該特定數(shù)據(jù)集的設(shè)計(jì),并希望它能夠適用于許多其他類(lèi)似的情形。添加一個(gè)足可以使用大多數(shù)平面數(shù)據(jù)創(chuàng)建分層結(jié)構(gòu)的組集合,在該集合中為每一級(jí)分層均指定一個(gè)分組字段、顯示字段和值字段(任一或所有字段均應(yīng)相同)。為了將圖 2 所示的數(shù)據(jù)轉(zhuǎn)變成圖 1 所示的 TreeView,我的新控件要求您定義兩個(gè)分組級(jí)別 Publisher 和 Title,并將 pub_id 定義為 Publisher 組的分組字段,將 title_id 定義為 Title 組的分組字段。除分組字段以外,還需要為每個(gè)組指定顯示和值字段,以確定在相應(yīng)組節(jié)點(diǎn)上顯示的文本以及用來(lái)唯一標(biāo)識(shí)特定組的值。當(dāng)遇到此類(lèi)數(shù)據(jù)時(shí),請(qǐng)使用 pub_name/pub_idtitle/title_id 作為這兩個(gè)組的顯示/值字段。作者信息將變成樹(shù)的葉節(jié)點(diǎn)(分組分層結(jié)構(gòu)末端的節(jié)點(diǎn)),您還需要為這些節(jié)點(diǎn)指定 ID (au_id) 和顯示 (au_lname) 字段。

  構(gòu)建自定義控件時(shí),在開(kāi)始編碼之前確定程序員對(duì)該控件的使用方法將有助于提高控件的使用效率。這種情況下,我希望程序員(在給定了前面所示的數(shù)據(jù)和所需結(jié)果的情況下)能夠使用如下幾行代碼完成分組:

 

With DbTreeControl
.ValueMember = "au_id"
.DisplayMember = "au_lname"

.DataSource = myDataTable.DefaultView
.AddGroup("Publisher", "pub_id", "pub_name", "pub_id")
.AddGroup("Title", "title_id", "title", "title_id")
End With


  注意:這并不是我最終編寫(xiě)的代碼行,但兩者相差不多。在開(kāi)發(fā)控件的過(guò)程中,我意識(shí)到需要將與 TreeView 關(guān)聯(lián)的 ImageList 中的圖像索引與每個(gè)分組級(jí)別相關(guān)聯(lián),因此必須向 AddGroup 方法中額外添加一個(gè)參數(shù)。

  為了真正構(gòu)建該樹(shù),我將瀏覽數(shù)據(jù)并查找字段(指定為每個(gè)分組的分組值)的更改,同時(shí)在必要時(shí)創(chuàng)建新分組節(jié)點(diǎn),并針對(duì)每個(gè)數(shù)據(jù)項(xiàng)創(chuàng)建一個(gè)葉節(jié)點(diǎn)。由于存在分組節(jié)點(diǎn),因此總節(jié)點(diǎn)數(shù)將大于數(shù)據(jù)源中的項(xiàng)目數(shù),但基礎(chǔ)數(shù)據(jù)中的每個(gè)項(xiàng)有且僅有一個(gè)葉節(jié)點(diǎn)。

圖 3:分組節(jié)點(diǎn)與葉節(jié)點(diǎn)

  葉節(jié)點(diǎn)和分組節(jié)點(diǎn)之間的區(qū)別(如圖 3 所示)對(duì)本文的余下部分具有重要意義。我決定將這兩類(lèi)節(jié)點(diǎn)區(qū)別對(duì)待,為每一類(lèi)節(jié)點(diǎn)分別創(chuàng)建自定義節(jié)點(diǎn),并根據(jù)所選的節(jié)點(diǎn)類(lèi)型引發(fā)不同的事件。

  實(shí)現(xiàn)數(shù)據(jù)綁定

  為該控件編寫(xiě)代碼的第一步是創(chuàng)建項(xiàng)目和相應(yīng)的起始類(lèi)。在本例中,我首先創(chuàng)建一個(gè)新 Windows 控件庫(kù),然后刪除默認(rèn)的 UserControl 類(lèi),并用一個(gè)從 TreeView 控件繼承的新類(lèi)來(lái)代替它:
 

  Public Class dbTreeControl
   Inherits System.Windows.Forms.TreeView
 

  從這時(shí)起,我將設(shè)計(jì)一個(gè)可以放入到窗體中的控件,并使其具有常規(guī)的 TreeView 的外觀和功能。下一步是開(kāi)始添加旨在處理在 TreeView 中加入的新功能所需的代碼,即數(shù)據(jù)綁定和分組數(shù)據(jù)。

  添加 DataSource 屬性

  我的新控件的所有功能都很重要,但構(gòu)建復(fù)雜數(shù)據(jù)綁定控件的兩個(gè)關(guān)鍵問(wèn)題是處理 DataSource 屬性和從數(shù)據(jù)源的每個(gè)對(duì)象中檢索單個(gè)項(xiàng)目。

  創(chuàng)建屬性例程

  首先,任何用于實(shí)現(xiàn)復(fù)雜數(shù)據(jù)綁定的控件都需要實(shí)現(xiàn)一個(gè) DataSource 屬性例程,并保持適當(dāng)?shù)某蓡T變量:

 

Private m_DataSource As Object

_
Public Property DataSource() As Object
Get
Return m_DataSource
End Get
Set(ByVal Value As Object)
If Value Is Nothing Then
cm = Nothing
GroupingChanged()
Else
If Not (TypeOf Value Is IList Or _
TypeOf Value Is IListSource) Then
' 不是針對(duì)該用途的有效數(shù)據(jù)源
Throw New System.Exception("無(wú)效 DataSource")
Else
If TypeOf Value Is IListSource Then
Dim myListSource As IListSource
myListSource = CType(Value, IListSource)
If myListSource.ContainsListCollection = True Then
Throw New System.Exception("無(wú)效 DataSource")
Else
' 對(duì),對(duì)。它是有效的數(shù)據(jù)源
m_DataSource = Value
cm = CType(Me.BindingContext(Value), _
CurrencyManager)
GroupingChanged()
End If
Else
m_DataSource = Value
cm = CType(Me.BindingContext(Value), _
CurrencyManager)
GroupingChanged()
End If
End If
End If
End Set
End Property
 

  IList 接口

  可用作復(fù)雜數(shù)據(jù)綁定數(shù)據(jù)源的對(duì)象通常都支持,該接口將數(shù)據(jù)公開(kāi)為對(duì)象集合,并提供若干有用屬性,如 Count。我的新 TreeView 控件要求在其綁定中使用一個(gè)支持 IList 的對(duì)象,但使用另一個(gè)接口也可以,因?yàn)樗峁┝艘粋€(gè)獲取 IList 對(duì)象的簡(jiǎn)便方法 (GetList)。當(dāng)設(shè)置 DataSource 屬性后,我首先確定是否提供了有效的對(duì)象,即一個(gè)支持 IListIListSource 的對(duì)象。我真正想要的是 IList,因此如果對(duì)象僅支持 IListSource(例如 DataTable),那么我將使用該接口的 GetList() 方法獲得正確的對(duì)象。

  某些實(shí)現(xiàn) IListSource 的對(duì)象(如 DataSet)實(shí)際上包含多個(gè)由 ContainsListCollection 屬性表示的列表。如果該屬性為 True,則 GetList 將返回一個(gè)表示列表(包含多個(gè)列表)的 IList 對(duì)象。在我的示例中,我決定支持直接連接到 IList 對(duì)象或僅包含一個(gè) IList 對(duì)象的 IListSource 對(duì)象,并忽略需要附加工作來(lái)指定數(shù)據(jù)源的對(duì)象,如 DataSet

注意:如果要支持此類(lèi)對(duì)象(DataSet 或與之類(lèi)似的對(duì)象),您可以再添加一個(gè)屬性(如 DataMember)來(lái)指定用于綁定的特定子列表。

  如果提供的數(shù)據(jù)源有效,則最終結(jié)果是創(chuàng)建的實(shí)例 (cm = Me.BindingContext(Value))。由于該實(shí)例將用于訪問(wèn)基礎(chǔ)數(shù)據(jù)源、對(duì)象屬性和位置信息,因此被存儲(chǔ)在局部變量中。

  添加顯示和值成員屬性

  擁有 DataSource 是實(shí)現(xiàn)復(fù)雜數(shù)據(jù)綁定的第一步,但該控件需要了解數(shù)據(jù)的哪些特定字段或?qū)傩詫⒂米黠@示和值成員。Display 成員將用作樹(shù)節(jié)點(diǎn)的標(biāo)題,而 Value 成員可通過(guò)節(jié)點(diǎn)的 Value 屬性進(jìn)行訪問(wèn)。這些屬性都是字符串,表示字段或?qū)傩悦梢苑奖愕靥砑拥娇丶校?/p>

 

Private m_ValueMember As String
Private m_DisplayMember As String

_
Public Property ValueMember() As String
Get
Return m_ValueMember
End Get
Set(ByVal Value As String)
m_ValueMember = Value
End Set
End Property

_
Public Property DisplayMember() As String
Get
Return m_DisplayMember
End Get
Set(ByVal Value As String)
m_DisplayMember = Value
End Set
End Property

  在此 TreeView 中,這些屬性將僅表示葉節(jié)點(diǎn)的 DisplayValue 成員,每個(gè)分組級(jí)別的相應(yīng)信息將在 AddGroup 方法中指定。

  使用 CurrencyManager 對(duì)象

  在前面探討的 DataSource 屬性中,創(chuàng)建了一個(gè) CurrencyManager 類(lèi)的實(shí)例,并存儲(chǔ)在類(lèi)級(jí)別變量中。通過(guò)該對(duì)象訪問(wèn)的 CurrencyManager 類(lèi)是實(shí)現(xiàn)數(shù)據(jù)綁定的關(guān)鍵部分,因?yàn)樗哂械膶傩浴⒎椒ê褪录蓪?shí)現(xiàn)以下功能:

  • 訪問(wèn)數(shù)據(jù)源的基礎(chǔ) IList 對(duì)象
  • 在數(shù)據(jù)源中檢索和設(shè)置對(duì)象字段或?qū)傩裕约?/li>
  • 使您的控件與同一窗體中的其他數(shù)據(jù)綁定控件同步。

  檢索屬性/字段值

  CurrencyManager 對(duì)象允許您通過(guò)它的 GetItemProperties 方法從數(shù)據(jù)源的單個(gè)項(xiàng)中檢索屬性或字段值,如 DisplayMemberValueMember 字段的值。然后使用 PropertyDescriptor 對(duì)象獲取特定列表項(xiàng)上的特定字段或?qū)傩缘闹怠O旅娴拇a片斷顯示了這些 PropertyDescriptor 對(duì)象的創(chuàng)建方法以及如何使用 GetValue 函數(shù)獲取基礎(chǔ)數(shù)據(jù)源中某一項(xiàng)的屬性值。請(qǐng)注意 CurrencyManager 對(duì)象的 List 屬性:通過(guò)它可以訪問(wèn)該控件綁定到的 IList 實(shí)例:

 

Dim myNewLeafNode As TreeLeafNode
Dim currObject As Object
currObject = cm.List(currentListIndex)
If Me.DisplayMember <> "" AndAlso Me.ValueMember <> "" Then
' 添加葉節(jié)點(diǎn)?
Dim pdValue As System.ComponentModel.PropertyDescriptor
Dim pdDisplay As System.ComponentModel.PropertyDescriptor
pdValue = cm.GetItemProperties()(Me.ValueMember)
pdDisplay = cm.GetItemProperties()(Me.DisplayMember)
myNewLeafNode = _
New TreeLeafNode(CStr(pdDisplay.GetValue(currObject)), _
currObject, _
pdValue.GetValue(currObject), _
currentListIndex)

  GetValue 在返回對(duì)象時(shí)忽略屬性的基本數(shù)據(jù)類(lèi)型,因此在使用返回值前需要對(duì)其進(jìn)行轉(zhuǎn)換。

  保持?jǐn)?shù)據(jù)綁定控件同步

  CurrencyManager 還有一個(gè)主要功能:除了可以訪問(wèn)綁定數(shù)據(jù)源和項(xiàng)屬性外,它還允許使用相同的 DataSource 來(lái)協(xié)調(diào)該控件和任何其他控件之間的數(shù)據(jù)綁定。該支持可用于確保多個(gè)同時(shí)綁定到同一數(shù)據(jù)源的控件停留在數(shù)據(jù)源的同一項(xiàng)。對(duì)于我的控件而言,我想確保在樹(shù)中選擇項(xiàng)時(shí),其他所有綁定到同一數(shù)據(jù)源的控件均指向同一項(xiàng)(同一記錄、行、甚至數(shù)組,如果您愿意從數(shù)據(jù)庫(kù)的角度進(jìn)行思考)。為此,我覆蓋了基本 TreeView 中的 OnAfterSelect 方法。在該方法(在選擇樹(shù)節(jié)點(diǎn)后被調(diào)用)中,我將 CurrencyManager 對(duì)象的 Position 屬性設(shè)置為當(dāng)前選定項(xiàng)的索引。與該 TreeView 控件一起提供的示例應(yīng)用程序闡釋了同步控件如何使生成數(shù)據(jù)綁定用戶界面變得更為容易。為了使確定當(dāng)前選定項(xiàng)的列表位置更為容易,我使用了自定義 TreeNode 類(lèi)(TreeLeafNodeTreeGroupNode),并將每個(gè)節(jié)點(diǎn)的列表索引存儲(chǔ)到創(chuàng)建的 Position 屬性中:

 

Protected Overrides Sub OnAfterSelect _
(ByVal e As System.Windows.Forms.TreeViewEventArgs)
Dim tln As TreeLeafNode
If TypeOf e.Node Is TreeGroupNode Then
tln = FindFirstLeafNode(e.Node)
Dim groupArgs As New groupTreeViewEventArgs(e)
RaiseEvent AfterGroupSelect(groupArgs)
ElseIf TypeOf e.Node Is TreeLeafNode Then
Dim leafArgs As New leafTreeViewEventArgs(e)
RaiseEvent AfterLeafSelect(leafArgs)
tln = CType(e.Node, TreeLeafNode)
End If

If Not tln Is Nothing Then
If cm.Position <> tln.Position Then
cm.Position = tln.Position
End If
End If
MyBase.OnAfterSelect(e)
End Sub

  在前面的代碼片段中,您可能注意到了一個(gè)稱(chēng)為 FindFirstLeafNode 的函數(shù),在此我想對(duì)其加以簡(jiǎn)要介紹。在我的 TreeView 中,只有葉節(jié)點(diǎn)(分層結(jié)構(gòu)中的最終節(jié)點(diǎn))才與 DataSource 中的項(xiàng)相對(duì)應(yīng),其他所有節(jié)點(diǎn)只用于創(chuàng)建分組結(jié)構(gòu)。如果我要?jiǎng)?chuàng)建一個(gè)性能優(yōu)良的數(shù)據(jù)綁定控件,便始終需要選擇一個(gè)與 DataSource 相對(duì)應(yīng)的項(xiàng),因此每當(dāng)選擇組節(jié)點(diǎn)時(shí),我就會(huì)找到該組下的第一個(gè)葉節(jié)點(diǎn),就好象該節(jié)點(diǎn)是當(dāng)前的選定內(nèi)容。您可以檢查該示例的運(yùn)行情況,但現(xiàn)在您大可放心地使用它。

 

Private Function FindFirstLeafNode(ByVal currNode As TreeNode) _
As TreeLeafNode
If TypeOf currNode Is TreeLeafNode Then
Return CType(currNode, TreeLeafNode)
Else
If currNode.Nodes.Count > 0 Then
Return FindFirstLeafNode(currNode.Nodes(0))
Else
Return Nothing
End If
End If
End Function

  設(shè)置 CurrencyManager 對(duì)象的 Position 屬性可使其他控件與當(dāng)前選定項(xiàng)同步,但是當(dāng)其他控件的位置發(fā)生變化時(shí),CurrencyManager 也產(chǎn)生事件,以便相應(yīng)地更改選定項(xiàng)。要成為一個(gè)優(yōu)秀的數(shù)據(jù)綁定組件,所選內(nèi)容應(yīng)隨著數(shù)據(jù)源位置的更改而移動(dòng),修改某一項(xiàng)的數(shù)據(jù)時(shí),顯示應(yīng)隨之更新。CurrencyManager 引發(fā)的事件共有三個(gè):CurrentChangedItemChangedPositionChanged。最后一個(gè)事件相當(dāng)簡(jiǎn)單;CurrencyManager 的用途之一是為數(shù)據(jù)源維護(hù)當(dāng)前位置指示器,以便多個(gè)綁定控件均可以顯示同一記錄或列表項(xiàng),只要該位置更改,此事件便會(huì)引發(fā)。其他兩個(gè)事件有時(shí)會(huì)相互重疊,因而區(qū)別不太明顯。以下分別介紹如何在自定義控件中使用這些事件:PositionChanged 是一個(gè)比較簡(jiǎn)單的事件,此處不再贅述;當(dāng)您要在復(fù)雜數(shù)據(jù)綁定控件(如 Tree)中調(diào)整當(dāng)前選定項(xiàng)時(shí),請(qǐng)使用該事件。只要修改數(shù)據(jù)源中的項(xiàng),ItemChanged 事件就會(huì)引發(fā),而 CurrentChanged 只有在當(dāng)前項(xiàng)被修改時(shí)才引發(fā)。

  在我的 TreeView 中,我發(fā)現(xiàn)每當(dāng)我選擇一個(gè)新項(xiàng)時(shí),所有三個(gè)事件均會(huì)引發(fā),因此我決定通過(guò)更改當(dāng)前選定項(xiàng)來(lái)處理 PositionChanged 事件,而對(duì)另外兩項(xiàng)不進(jìn)行任何處理。建議將數(shù)據(jù)源強(qiáng)制轉(zhuǎn)換為 IBindingList(如果數(shù)據(jù)源支持 IBindingList 的話)并改用 ListChanged 事件,但我未實(shí)現(xiàn)此功能。

 

Private Sub cm_PositionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cm.PositionChanged
Dim tln As TreeLeafNode
If TypeOf Me.SelectedNode Is TreeLeafNode Then
tln = CType(Me.SelectedNode, TreeLeafNode)
Else
tln = FindFirstLeafNode(Me.SelectedNode)
End If

If tln.Position <> cm.Position Then
Me.SelectedNode = FindNodeByPosition(cm.Position)
End If
End Sub

Private Overloads Function FindNodeByPosition(ByVal index As Integer) _
As TreeNode
Return FindNodeByPosition(index, Me.Nodes)
End Function

Private Overloads Function FindNodeByPosition(ByVal index As Integer, _
ByVal NodesToSearch As TreeNodeCollection) As TreeNode
Dim i As Integer = 0
Dim currNode As TreeNode
Dim tln As TreeLeafNode

Do While i < NodesToSearch.Count
currNode = NodesToSearch(i)
i += 1
If TypeOf currNode Is TreeLeafNode Then
tln = CType(currNode, TreeLeafNode)
If tln.Position = index Then
Return currNode
End If
Else
currNode = FindNodeByPosition(index, currNode.Nodes)
If Not currNode Is Nothing Then
Return currNode
End If
End If
Loop
Return Nothing
End Function

   將 DataSource 轉(zhuǎn)變?yōu)闃?shù)

  編寫(xiě)完數(shù)據(jù)綁定代碼后,我可以繼續(xù)添加管理分組級(jí)別的代碼,相應(yīng)地生成樹(shù),然后添加一些自定義事件、方法和屬性。

  管理組

  程序員要配置組集合,就必須創(chuàng)建 AddGroupRemoveGroupClearGroups 函數(shù)。每當(dāng)修改組集合時(shí),都必須重新繪制樹(shù)(以反映新配置),因此我創(chuàng)建了一個(gè)通用過(guò)程 GroupingChanged,當(dāng)情況發(fā)生變化,需要強(qiáng)制重建樹(shù)時(shí),它可以由控件中的各種代碼調(diào)用:

 

Private treeGroups As New ArrayList()

Public Sub RemoveGroup(ByVal group As Group)
If Not treeGroups.Contains(group) Then
treeGroups.Remove(group)
GroupingChanged()
End If
End Sub

Public Overloads Sub AddGroup(ByVal group As Group)
Try
treeGroups.Add(group)
GroupingChanged()
Catch
End Try
End Sub

Public Overloads Sub AddGroup(ByVal name As String, _
ByVal groupBy As String, _
ByVal displayMember As String, _
ByVal valueMember As String, _
ByVal imageIndex As Integer, _
ByVal selectedImageIndex As Integer)
Dim myNewGroup As New Group(name, groupBy, _
displayMember, valueMember, _
imageIndex, selectedImageIndex)
Me.AddGroup(myNewGroup)
End Sub


Public Function GetGroups() As Group()
Return CType(treeGroups.ToArray(GetType(Group)), Group())
End Function


  生成樹(shù)

  樹(shù)的實(shí)際重建由一對(duì)過(guò)程來(lái)完成:BuildTreeAddNodes。由于這兩個(gè)過(guò)程的代碼太長(zhǎng),本文并未全部列出,而是盡量概括它們的行為(當(dāng)然,如果愿意您可以下載完整的代碼)。如前所述,程序員可以通過(guò)設(shè)置一系列組與該控件進(jìn)行交互,然后在 BuildTree 中使用這些組來(lái)確定如何設(shè)置樹(shù)節(jié)點(diǎn)。BuildTree 清除當(dāng)前節(jié)點(diǎn)集合,然后遍歷整個(gè)數(shù)據(jù)源來(lái)處理第一級(jí)分組(本文前面的示例和圖解中提到的 Publisher),為每個(gè)不同的分組值添加一個(gè)節(jié)點(diǎn)(使用示例中的數(shù)據(jù),為每個(gè) pub_id 值添加一個(gè)節(jié)點(diǎn)),然后調(diào)用 AddNodes 來(lái)填充第一級(jí)分組下的所有節(jié)點(diǎn)。AddNodes 遞歸調(diào)用自身以處理任意多的級(jí)數(shù),必要時(shí)可添加組節(jié)點(diǎn)和葉節(jié)點(diǎn)。使用兩個(gè)基于 TreeNode 的自定義類(lèi)以區(qū)別組節(jié)點(diǎn)和葉節(jié)點(diǎn),并為兩類(lèi)節(jié)點(diǎn)提供各自相應(yīng)的屬性。

  自定義 TreeView 事件

  每當(dāng)選擇一個(gè)節(jié)點(diǎn)時(shí),TreeView 都會(huì)引發(fā)兩個(gè)事件:BeforeSelectAfterSelect。但在我的控件中,我想使組節(jié)點(diǎn)和葉節(jié)點(diǎn)的事件不同,于是便添加了自己的事件 BeforeGroupSelect/AfterGroupSelectBeforeLeafSelect/AfterLeafSelect,除基本事件外,還引發(fā)了自定義事件參數(shù)類(lèi):

 

Public Event BeforeGroupSelect _
(ByVal sender As Object, ByVal e As groupTreeViewCancelEventArgs)
Public Event AfterGroupSelect _
(ByVal sender As Object, ByVal e As groupTreeViewEventArgs)
Public Event BeforeLeafSelect _
(ByVal sender As Object, ByVal e As leafTreeViewCancelEventArgs)
Public Event AfterLeafSelect _
(ByVal sender As Object, ByVal e As leafTreeViewEventArgs)

Protected Overrides Sub OnBeforeSelect _
(ByVal e As System.Windows.Forms.TreeViewCancelEventArgs)
If TypeOf e.Node Is TreeGroupNode Then
Dim groupArgs As New groupTreeViewCancelEventArgs(e)
RaiseEvent BeforeGroupSelect(CObj(Me), groupArgs)
ElseIf TypeOf e.Node Is TreeLeafNode Then
Dim leafArgs As New leafTreeViewCancelEventArgs(e)
RaiseEvent BeforeLeafSelect(CObj(Me), leafArgs)
End If
MyBase.OnBeforeSelect(e)
End Sub

Protected Overrides Sub OnAfterSelect _
(ByVal e As System.Windows.Forms.TreeViewEventArgs)
Dim tln As TreeLeafNode
If TypeOf e.Node Is TreeGroupNode Then
tln = FindFirstLeafNode(e.Node)
Dim groupArgs As New groupTreeViewEventArgs(e)
RaiseEvent AfterGroupSelect(CObj(Me), groupArgs)
ElseIf TypeOf e.Node Is TreeLeafNode Then
Dim leafArgs As New leafTreeViewEventArgs(e)
RaiseEvent AfterLeafSelect(CObj(Me), leafArgs)
tln = CType(e.Node, TreeLeafNode)
End If

If Not tln Is Nothing Then
If cm.Position <> tln.Position Then
cm.Position = tln.Position
End If
End If
MyBase.OnAfterSelect(e)
End Sub

  自定義節(jié)點(diǎn)類(lèi)(TreeLeafNodeTreeGroupNode)和自定義事件參數(shù)類(lèi)均包括在可下載代碼中。

  示例應(yīng)用程序

  要全面理解本示例控件中的所有代碼,您應(yīng)該了解它在應(yīng)用程序中的運(yùn)行情況。包含的示例應(yīng)用程序使用 pubs.mdb Access 數(shù)據(jù)庫(kù),并說(shuō)明 Tree 控件如何與其他數(shù)據(jù)綁定控件一起創(chuàng)建 Windows 應(yīng)用程序。本例中,尤其值得注意的主要功能包括樹(shù)與其他綁定控件的同步以及對(duì)數(shù)據(jù)源執(zhí)行搜索時(shí)樹(shù)節(jié)點(diǎn)的自動(dòng)選擇。

注意:本示例應(yīng)用程序(名為“TheSample”)包含在本文的下載中。

圖 4:數(shù)據(jù)綁定 TreeView 的演示應(yīng)用程序

  小結(jié)

  本文介紹的數(shù)據(jù)綁定 Tree 控件并非適用于所有需要 Tree 控件來(lái)顯示數(shù)據(jù)庫(kù)信息的項(xiàng)目,但它確實(shí)介紹了一種可針對(duì)個(gè)人目的自定義該控件的方法。請(qǐng)記住,您要生成的任何復(fù)雜數(shù)據(jù)綁定控件與 Tree 控件的大部分代碼基本相同,您可以通過(guò)修改現(xiàn)有代碼來(lái)簡(jiǎn)化以后的控件開(kāi)發(fā)過(guò)程。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 31freehdxxxx欧美 | 免费网站看毛片 | 久久久久久久免费看 | 97久久曰曰久久久 | 久久久免费观看完整版 | 久久国产亚洲视频 | 欧美xxxx精品另类 | 在线播放免费人成毛片乱码 | 国产一区二区在线免费播放 | 久久久三级免费电影 | 亚洲aⅴ免费在线观看 | 欧美性受ⅹ╳╳╳黑人a性爽 | 久久久无码精品亚洲日韩按摩 | 99精品国产在热久久婷婷 | 欧美成人午夜一区二区三区 | 欧美日韩视频网站 | 在线观看免费毛片视频 | 中文字幕在线网站 | 黄色香蕉视频 | 99影视在线视频免费观看 | 337p日本欧洲亚洲大胆精蜜臀 | 国产黄色一区二区 | 国产羞羞视频 | 热99在线视频 | 九九热精品视频在线 | 最新福利在线 | av电影网在线观看 | 国产精品美女久久久久久不卡 | 免费看成人av | 亚洲一区二区三区视频 | 久久久久久片 | 日韩每日更新 | 国产午夜精品在线 | 成人三级在线播放 | 宅男噜噜噜66国产在线观看 | 二区三区四区 | 欧美精品久久久久久久久久 | 亚洲二区不卡 | 日产精品久久久一区二区开放时间 | 久久精品av| 亚洲99|