从自引用表自动绑定 TreeView 控件






4.57/5 (14投票s)
支持从单个自引用表自动绑定的自定义 TreeView 控件

引言
本文将展示如何实现一个自定义的 ASP.NET TreeView
控件,该控件支持从自引用表自动绑定。该控件支持从数据源控件绑定,或者使用 Data Source 属性以编程方式绑定。
背景
本文是我之前一篇文章的延续,展示了 TreeView
控件所缺乏的有用功能。之前的文章演示了如何应用 CSS 和向树节点添加自定义属性。在本文中,将讨论从自引用表自动绑定 TreeView
控件。
什么是自引用表?
自引用表包含一种关系,其中一列引用同一表中的另一列。例如
在上图中,父 ID 列引用 ID 列,这意味着父 ID 是形成分层数据的 ID。
自动绑定
ASP.NET TreeView
仅支持分层数据源控件。为了解决这个问题,我们创建一个数据绑定控件类 AutoBindingTree
,它扩展了基类 DataBoundControl
,以便我们可以重写 PerformSelect
和 PerformDataBinding
事件。单击此处,了解有关创建自定义数据绑定控件的更多信息。PerformDataBinding
接受一个 IEnumerable
作为参数,该参数表示从数据源检索到的数据。此参数用于创建 DataView
,因为它实现了 IEnumerable
。然后使用 DataView
创建一个维护自引用关系并用于填充 TreeView
的 DataSet
。DataSet
使用三个强制属性
DataTextField
:包含节点Text
值的列的名称DataFieldID
:包含ID
值的列的名称DataFieldParentID
:包含ParentID
值的列的名称
Protected Overrides Sub PerformDataBinding(ByVal oSourceData As IEnumerable)
MyBase.PerformDataBinding(oSourceData)
' Verify data exists.
If Not (oSourceData Is Nothing) Then
Dim oView As DataView = oSourceData
Dim oTable As DataTable = oView.Table
Dim oDS As DataSet = New DataSet()
oDS.Tables.Add(oTable.Copy())
'Create a Relation Between the ID Column and Parent Column
If oDS.Relations.Contains("SelfRefenceRelation") = False Then
oDS.Relations.Add("SelfRefenceRelation", _
oDS.Tables(0).Columns(DataFieldID), _
oDS.Tables(0).Columns(DataFieldParentID))
End If
oTable.Dispose()
oTable = Nothing
ViewState("TreeData") = oDS
LoadTreeView(oDS)
oDS.Dispose()
oDS = Nothing
End If
End Sub
创建 DataSet
后,将调用 LoadTreeView
来填充 Treeview
Private Sub LoadTreeView(ByVal oDS As DataSet)
Dim oTreeView As TreeView = New TreeView()
Dim oDataRow As DataRow
For Each oDataRow In oDS.Tables(0).Rows
'Find Root Node,A root node has ParentID NULL
If oDataRow.IsNull(DataFieldParentID) Then
'Create Parent Node and add to tree
Dim oNode As New TreeNode()
oNode.Text = oDataRow(DataTextField).ToString()
oNode.Value = oDataRow(DataFieldID).ToString()
oNode.NavigateUrl = oDataRow("NavigateURL").ToString()
oTreeView.Nodes.Add(oNode)
'Recursively Populate From root
RecursivelyLoadTree(oDataRow, oNode)
End If
Next oDataRow
Controls.Add(oTreeView)
oDS.Dispose()
oDS = Nothing
End Sub 'LoadTreeView
首先,识别根元素 (ParentID = NULL
),将其添加到树中,然后调用函数 RecursivelyLoadTree
以递归方式创建子元素
Private Sub RecursivelyLoadTree(ByVal oDataRow As DataRow, _
ByRef oNode As TreeNode)
Dim oChildRow As DataRow
'returns an array of DataRow objects representing the child view
For Each oChildRow In oDataRow.GetChildRows("SelfRefenceRelation")
'Create child node and add to Parent
Dim oChildNode As New TreeNode()
oChildNode.Text = oChildRow(DataTextField).ToString()
oChildNode.Value = oChildRow(DataFieldID).ToString()
oChildNode.NavigateUrl = _
oChildRow("NavigateURL").ToString()
oNode.ChildNodes.Add(oChildNode)
'Repeat for each child
RecursivelyLoadTree(oChildRow, oChildNode)
Next oChildRow
End Sub 'RecursivelyLoadTree
使用代码
使用该控件的最简单方法是将其绑定到数据源控件 (DataSourceControl.aspx)
<%@ Register TagPrefix="CPArticles" Namespace="CPArticles"%>
<CPArticles:AutoBindingTree runat="server" ID="TestCtrl"
DataTextField="Text"
DataFieldID="ID"
DataFieldParentID="ParentID"
DataSourceID="SqlDataSource1"
/>
<asp:SqlDataSource id="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
SelectCommand="SELECT * FROM SelfReferenceTable"
SelectCommandType="Text"
/>
或者通过以编程方式设置 DataSource
属性 (DataBind.aspx)
TestCtrl.DataFieldID = "ID"
TestCtrl.DataFieldParentID = "ParentID"
TestCtrl.DataTextField = "Text"
TestCtrl.DataSource = oDs
TestCtrl.DataBind()
演示应用程序中包含这两个示例和 SQL 脚本。
历史
- 2007 年 4 月 15 日:首次发布。