Click here to Skip to main content
15,896,207 members
Articles / Web Development / ASP.NET

Auto Binding a TreeView control from a self referencing table

Rate me:
Please Sign up or sign in to vote.
4.57/5 (15 votes)
16 Apr 2007CPOL2 min read 117.3K   1.4K   65  
A Custom TreeView Control that supports auto binding from a single self referencing table
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data

Namespace CPArticles
    Public Class AutoBindingTree
        Inherits DataBoundControl

#Region "Public Properties"
        ''' <summary>
        ''' The name of the column holding the Text Value
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property DataTextField() As String
            Get
                Dim oText As Object = ViewState("DataTextField")
                If oText Is Nothing Then
                    Return String.Empty
                Else
                    Return CStr(oText)
                End If
            End Get
            Set(ByVal value As String)
                ViewState("DataTextField") = value
                If (Initialized) Then
                    OnDataPropertyChanged()
                End If
            End Set
        End Property
        ''' <summary>
        ''' The name of the Column holding the ID value
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property DataFieldID() As String
            Get
                Dim oID As Object = ViewState("DataFieldID")
                If oID Is Nothing Then
                    Return String.Empty
                Else
                    Return CStr(oID)
                End If
            End Get
            Set(ByVal value As String)
                ViewState("DataFieldID") = value
            End Set
        End Property
        ''' <summary>
        ''' The name of the Column holding the ParentID value
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property DataFieldParentID() As String
            Get
                Dim oParentID As Object = ViewState("DataFieldParentID")
                If oParentID Is Nothing Then
                    Return String.Empty
                Else
                    Return CStr(oParentID)
                End If
            End Get
            Set(ByVal value As String)
                ViewState("DataFieldParentID") = value
            End Set
        End Property
#End Region

#Region "Data Bound Events"
        Protected Overrides Sub PerformSelect()
            ' Call OnDataBinding here if bound to a data source using the
            ' DataSource property (instead of a DataSourceID), because the
            ' databinding statement is evaluated before the call to GetData.       
            If Not IsBoundUsingDataSourceID Then
                OnDataBinding(EventArgs.Empty)
            End If

            ' The GetData method retrieves the DataSourceView object from  
            ' the IDataSource associated with the data-bound control.            
            GetData().Select(CreateDataSourceSelectArguments(), _
                AddressOf OnDataSourceViewSelectCallback)

            ' The PerformDataBinding method has completed.
            RequiresDataBinding = False
            MarkAsDataBound()

            ' Raise the DataBound event.
            OnDataBound(EventArgs.Empty)

        End Sub

        Private Sub OnDataSourceViewSelectCallback(ByVal retrievedData As IEnumerable)
            ' Call OnDataBinding only if it has not already been 
            ' called in the PerformSelect method.
            If IsBoundUsingDataSourceID Then
                OnDataBinding(EventArgs.Empty)
            End If
            ' The PerformDataBinding method binds the data in the  
            ' retrievedData collection to elements of the data-bound control.
            PerformDataBinding(retrievedData)

        End Sub

        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
#End Region

#Region "Tree Functions"
        ''' <summary>
        ''' Populate Tree View
        ''' </summary>
        ''' <param name="oDS">Data Set</param>
        ''' <remarks></remarks>
        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)

                    'Recurively Populate From root
                    RecursivelyLoadTree(oDataRow, oNode)
                End If
            Next oDataRow
            Controls.Add(oTreeView)
            oDS.Dispose()
            oDS = Nothing
        End Sub 'LoadTreeView
        ''' <summary>
        ''' Recursively Load ChildNodes for each Node using the Dataset relation
        ''' </summary>
        ''' <param name="oDataRow">Data Row</param>
        ''' <param name="oNode">Parent Node</param>
        ''' <remarks></remarks>
        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
#End Region

#Region "View State"
        Protected Overrides Function SaveViewState() As Object
            Dim baseState As Object = MyBase.SaveViewState()
            Dim allStates() As Object = New Object(2) {}
            allStates(0) = baseState
            allStates(1) = ViewState("TreeData")
            Return allStates
        End Function
        Protected Overrides Sub LoadViewState(ByVal savedState As Object)
            If Not savedState Is Nothing Then
                Dim myState() As Object = CType(savedState, Object())
                If Not myState(0) Is Nothing Then
                    MyBase.LoadViewState(myState(0))
                End If
                If Not myState(1) Is Nothing Then
                    ViewState("TreeData") = CType(myState(1), DataSet)
                End If
                If Not ViewState("TreeData") Is Nothing Then
                    LoadTreeView(CType(ViewState("TreeData"), DataSet))
                End If
            End If
        End Sub
#End Region
    End Class
End Namespace

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Delcan Corporation
United States United States
Bassam Saoud is a software developer with more then 6+ years of experience. He has masters in Computer Science from American University of Technology and is currently doing Masters in Business Administration at Colorado Heights University. He started Programming with C++ and VB and now working with ASP.NET VB.NET/C#, SQL Server 2000/2005.

His interests are mainly politics, Basketball and Traveling.

Comments and Discussions