65.9K
CodeProject 正在变化。 阅读更多。
Home

动态创建和填充 Treeviews

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (9投票s)

2006 年 3 月 31 日

2分钟阅读

viewsIcon

110518

downloadIcon

3000

关于数据库驱动的动态多 Treeviews 的文章

Scorecard

引言

在我最近的一个项目中,需求的一部分是生成 KPI 记分卡。KPI 记分卡是一个以树状结构显示 KPI 的图表。所有的 KPI 都被分类,每个类别代表一棵树。树的层次结构在数据库中定义。这基本上要求根据数据库中的详细信息动态生成 Treeview。

我一直在尝试寻找关于 Web 上 Treeview 的资源。我找不到这样的确切示例。我可以找到在设计时添加到 Web 表单的 Treeview 的文章,以及将控件动态添加到 Web 表单的文章,但没有例子说明动态 Treeview 控件。因此,我考虑上传这篇文章,这篇文章说明了如何动态创建和数据绑定 Treeview。

我非常确定这没有什么新的(不为人知的)。本文只是在 Web 上找到的两类文章(Treeview 和动态添加控件)的结合,这对于一些可以根据自己的使用情况进行定制的人来说可能是一个现成的解决方案。

对于这篇文章,我使用了 VS 2003,SQL Server 数据库。这是一个示例项目,其中我使用了 Microsoft Treeview 控件,而在我的实际项目中,我使用了第三方 treeview 控件,以获得更大的灵活性和更好的美观视图。

数据库准备

这个项目的数据库包含两个表 1. SC_Master 2. SC_Detail

表结构和数据如下。(用于生成表的脚本包含在源代码的 Database 文件夹中。)

SC_Master

SC_Master Table

SC_Detail

SC_Detail Table

项目结构

Project Structure

使用代码

这个项目的核心是一个用户控件 "Scorecard.ascx",它创建并填充了 treeview。使用用户控件的主页面是 "ScorecardPage.aspx"。首先让我们讨论一下用户控件中的代码。

从数据库检索数据的函数

#Region " Retrieve DataSet "

    Public Function Retrieve_DataSet(ByVal sSQL As String) As DataSet
        Dim cmdCommand As New OleDbCommand()
        Try
            Dim daAdapter As New OleDbDataAdapter()
            Dim dsDataSet As New DataSet()
            'Connection String should be changed suitably.
            Dim cnConnection As New OleDbConnection("Provider=SQLOLEDB;" & _ 
                 "Password=MyPwd;User ID=MyId;" & _ 
                 "Data Source=MyServer;Initial Catalog=SCORECARD;")

            cnConnection.Open()

            With cmdCommand
                .Connection = cnConnection
                .CommandType = CommandType.Text
                .CommandText = sSQL
            End With

            daAdapter.SelectCommand = cmdCommand
            dsDataSet.EnforceConstraints = False
            daAdapter.Fill(dsDataSet)
            dsDataSet.EnforceConstraints = True

            Return dsDataSet.Copy

        Catch err As Exception
            'Throw err
            Response.Write(err.StackTrace)
        Finally
            cmdCommand.Connection.Close()
        End Try
    End Function

#End Region

创建和填充 Treeview 的代码

#Region " Generate Treeviews "

    Private Sub CreateRootnodes()

        Dim dbRow As System.Data.DataRow
        Dim ds As New System.Data.DataSet()
        Dim strSqlMain As String = "select m.SC_ID_NO as SC_ID_NO, " & _ 
            "m.SC_SHORT_DESC as SC_SHORT_DESC,m.SC_PARENT as SC_PARENT,"
        strSqlMain = strSqlMain & " sum(d.SC_ACTUAL) as SC_ACTUAL,"
        strSqlMain = strSqlMain & " sum(d.SC_PLAN) as SC_PLAN,"
        strSqlMain = strSqlMain & " sum(d.SC_ACTUAL - d.SC_PLAN) as SC_Better"
        strSqlMain = strSqlMain & " from SC_Master m, SC_Detail d"
        strSqlMain = strSqlMain & _
                     " where d.SC_ID = m.SC_ID_NO and m.SC_PARENT is NULL"
        strSqlMain = strSqlMain & " group by SC_ID_NO,SC_SHORT_DESC,SC_PARENT"
        strSqlMain = strSqlMain & " order by SC_ID_NO"

        ds = Retrieve_DataSet(strSqlMain)

        Dim i As Int32
        Dim tbl As New Table()
        Dim tblrow As New TableRow()

        For Each dbRow In ds.Tables(0).Rows
            Dim newTreeview As New TreeView()
            Dim tblcel As New TableCell()

            newTreeview.ShowLines = True

            Dim strSqlSub As String = "select m.SC_ID_NO as SC_ID_NO, " & _ 
                "m.SC_SHORT_DESC as SC_SHORT_DESC,m.SC_PARENT as SC_PARENT,"
            strSqlSub = strSqlSub & " sum(d.SC_ACTUAL) as SC_ACTUAL,"
            strSqlSub = strSqlSub & " sum(d.SC_PLAN) as SC_PLAN,"
            strSqlSub = strSqlSub & " sum(d.SC_ACTUAL - d.SC_PLAN) as SC_Better"
            strSqlSub = strSqlSub & " from SC_Master m, SC_Detail d"
            strSqlSub = strSqlSub & " where d.SC_ID = m.SC_ID_NO and (m.SC_PARENT='"
            strSqlSub = strSqlSub & dbRow("SC_ID_NO").ToString() & "' or m.SC_ID_NO='"
            strSqlSub = strSqlSub & dbRow("SC_ID_NO").ToString() & "')"
            strSqlSub = strSqlSub & " group by SC_ID_NO,SC_SHORT_DESC,SC_PARENT"
            strSqlSub = strSqlSub & " order by SC_ID_NO"

            buildTree(newTreeview, strSqlSub)
            tblcel.ID = dbRow("SC_ID_NO").ToString()
            tblcel.Controls.Add(newTreeview)
            tblcel.VerticalAlign = VerticalAlign.Top
            tblrow.Cells.Add(tblcel)
        Next dbRow
        tbl.Rows.Add(tblrow)
        tbl.ID = "TreeTable"
        Me.Controls.Add(tbl)
    End Sub

    Private Sub buildTree(ByRef treeview As TreeView, ByVal sql As String)

        Dim dbSubTreeRow As System.Data.DataRow
        Dim dsSubtree As New System.Data.DataSet()
        dsSubtree = Retrieve_DataSet(sql)
        dsSubtree.Relations.Add("NodeRelation", _
        dsSubtree.Tables(0).Columns("SC_ID_NO"), _
        dsSubtree.Tables(0).Columns("SC_PARENT"))

        Dim strNodeText As String

        For Each dbSubTreeRow In dsSubtree.Tables(0).Rows
            If (dbSubTreeRow.IsNull("SC_PARENT")) Then
                Dim newNode As TreeNode
                strNodeText = Trim(dbSubTreeRow("SC_SHORT_DESC").ToString())

                Dim j As Int32
                Dim addstr As String = ""

                For j = 1 To 40
                    addstr = addstr & " "
                Next
                strNodeText = addstr & "

" & strNodeText & "
" & Format(dbSubTreeRow("SC_Better"), Me.dfDecimal)

                newNode = CreateNode(strNodeText, "", True)
            'greenBackground,yellowBackground,redBackground
            'are strings which contain the style sheet.
                If dbSubTreeRow("SC_Better") > 0 Then
                    newNode.SelectedStyle = _
                      CssCollection.FromString(greenBackground)
                    newNode.DefaultStyle = _
                      CssCollection.FromString(greenBackground)
                    newNode.HoverStyle = _
                      CssCollection.FromString(greenBackground)

                ElseIf dbSubTreeRow("SC_Better") = 0 Then
                    newNode.SelectedStyle = CssCollection.FromString(yellowBackground)
                    newNode.DefaultStyle = CssCollection.FromString(yellowBackground)
                    newNode.HoverStyle = CssCollection.FromString(yellowBackground)

                Else
                    newNode.SelectedStyle = CssCollection.FromString(redBackground)
                    newNode.DefaultStyle = CssCollection.FromString(redBackground)
                    newNode.HoverStyle = CssCollection.FromString(redBackground)

                End If

                newNode.Expanded = True
                newNode.Expandable = ExpandableValue.Always
                treeview.Nodes.Add(newNode)
                PopulateSubTree(dbSubTreeRow, newNode)
            End If
        Next dbSubTreeRow
    End Sub

    Private Sub PopulateSubTree _
    (ByVal dbRow As System.Data.DataRow, _
    ByVal node As TreeNode)
        Dim childRow As System.Data.DataRow
        Dim strNodeText As String

        Dim j As Int32
        Dim addstr As String = ""
        For j = 1 To 40
            addstr = addstr & " "
        Next

        For Each childRow In dbRow.GetChildRows("NodeRelation")
            strNodeText = Trim(childRow("SC_SHORT_DESC").ToString())
            strNodeText = addstr & "

" & strNodeText & "
" & Format(childRow("SC_Better"), Me.dfDecimal)

            Dim childNode As TreeNode = _
            CreateNode(strNodeText, "", True)

            If childRow("SC_Better") > 0 Then
                childNode.SelectedStyle = CssCollection.FromString(greenBackground)
                childNode.DefaultStyle = CssCollection.FromString(greenBackground)
                childNode.HoverStyle = CssCollection.FromString(greenBackground)

            ElseIf childRow("SC_Better") = 0 Then
                childNode.SelectedStyle = CssCollection.FromString(yellowBackground)
                childNode.DefaultStyle = CssCollection.FromString(yellowBackground)
                childNode.HoverStyle = CssCollection.FromString(yellowBackground)

            Else
                childNode.SelectedStyle = CssCollection.FromString(redBackground)
                childNode.DefaultStyle = CssCollection.FromString(redBackground)
                childNode.HoverStyle = CssCollection.FromString(redBackground)

            End If

            node.Expanded = True
            node.Expandable = ExpandableValue.Always

            node.Nodes.Add(childNode)
            PopulateSubTree(childRow, childNode)
        Next childRow
    End Sub

    Private Function CreateNode _
    (ByVal text As String, ByVal _
    imageurl As String, ByVal expanded As Boolean) _
    As TreeNode
        Dim node As New TreeNode()
        node.Text = text
        node.ImageUrl = imageurl
        node.Expanded = expanded

        Return node
    End Function

#End Region

初始化用户控件显示的初始化代码。

   Public Sub InitDisplay()
        Try
            CreateRootnodes()
        Catch err As Exception
            Response.Write(err.Message)
        End Try
    End Sub

在 "ScorecardPage.aspx" 上显示用户控件的代码

#Region " Show Controls "
    Public Sub ShowControls()
        Dim ucScoreCard As Scorecard = _
            Page.LoadControl("..\Components\Scorecard.ascx")
        ucScoreCard.ID = "ucScoreCard"
        Me.PlaceHolder1.Controls.Clear()
        PlaceHolder1.Controls.Add(ucScoreCard)
        ucScoreCard.InitDisplay()
    End Sub
#End Region

在 "ScorecardPage.aspx" 的页面加载事件中调用 "ShowControls" 方法。

关注点

有很多事情可以用 treeview 属性来完成,但我在本文中没有提及。我使用了样式表来获取所需的背景,这些背景突出显示了元素的值(负数、正数和零)。

注释

请花时间为本文投票和/或评论它。

历史

2006 年 3 月 31 日 - 初始版本

 

© . All rights reserved.