我有与其本身PARENTID / childID的关系,我可以数据绑定到一个TreeView一个IEnumerable(的雇员),它完全填充的层次结构。不过,我希望能够通过所有记录手动循环和编程创建所有的节点,这样我可以改变属性的基础上针对给定项目/无数据的每个节点。

是否有一个教程在那里,解释如何做到这一点?我见过许多使用的数据集和数据表,但没有说明如何做到这一点在LINQ to SQL(IEnumerable的)

更新:

下面是我如何使用DataSet中做到这一点 - 我似乎无法找到如何做相同的IEnumerable

Private Sub GenerateTreeView()
        Dim ds As New DataSet()

        Dim tasktree As New Task(_taskID)

        Dim dt As DataTable = tasktree.GetTaskTree()

        ds.Tables.Add(dt)

        ds.Relations.Add("NodeRelation", dt.Columns("TaskID"), dt.Columns("ParentID"))

        Dim dbRow As DataRow
        For Each dbRow In dt.Rows
            If dbRow("TaskID") = _taskID Then
                Dim node As RadTreeNode = CreateNode(dbRow("Subject").ToString(), False, dbRow("TaskID").ToString())
                RadTree1.Nodes.Add(node)
                RecursivelyPopulate(dbRow, node)
            End If
        Next dbRow
    End Sub 

    Private Sub RecursivelyPopulate(ByVal dbRow As DataRow, ByVal node As RadTreeNode)
        Dim childRow As DataRow
        Dim StrikeThrough As String = ""
        Dim ExpandNode As Boolean = True
        For Each childRow In dbRow.GetChildRows("NodeRelation")
            Select Case childRow("StatusTypeID")
                Case 2
                    StrikeThrough = "ActiveTask"
                Case 3
                    StrikeThrough = "CompletedTask"
                    ExpandNode = False
                Case 4, 5
                    StrikeThrough = "ClosedTask"
                    ExpandNode = False
                Case Else
                    StrikeThrough = "InactiveTask"
                    ExpandNode = False
            End Select
            Dim childNode As RadTreeNode = CreateNode("<span class=""" & StrikeThrough & """><a href=""Task.aspx?taskid=" & childRow("TaskID").ToString() & """>" & childRow("Subject").ToString() & "</a></span>", ExpandNode, childRow("TaskID").ToString())
            node.Nodes.Add(childNode)
            RecursivelyPopulate(childRow, childNode)
            ExpandNode = True
        Next childRow
    End Sub

    Private Function CreateNode(ByVal [text] As String, ByVal expanded As Boolean, ByVal id As String) As RadTreeNode
        Dim node As New RadTreeNode([text])
        node.Expanded = expanded

        Return node
    End Function
有帮助吗?

解决方案

如果你只需要列举可以实现这个作为发电机树的方式,它可能看起来怪怪的,你可能会更好的与用户定义的枚举,但它本质上是一样的。

public interface IGetChildItems<TEntity>
{
    IEnumerable<TEntity> GetChildItems();
}

public static IEnumerable<TEntity> Flatten<TEntity>(TEntity root)
    where TEntity : IGetChildItems<TEntity>
{
    var stack = new Stack<TEntity>();
    stack.Push(root);
    while (stack.Count > 0)
    {
        var item = stack.Pop();
        foreach (var child in item.GetChildItems())
        {
            stack.Push(child);
        }
        yield return item;
    }
}

在类型约束,其中TEntity:IGetChildItems只是以表示你需要抽象如何下降的层次结构。没有上述代码将不会编译。

这将枚举在广度优先方式的树,它会产生母体元件第一那么它的孩子,然后这些儿童的儿童。可以方便地定制上面的代码,以实现不同的行为。

编辑:

的收返回的东西告诉它应该返回一个值,则继续编译。产量是上下文关键字,它只能用于循环语句内。发电机是写一个IEnumerable的数据源的简单方法。编译器会从这个代码构建一个状态机,并创建一个匿名枚举类。显然,产量关键字不会在VB.NET存在。但你仍然可以写一个类来实现的。

Imports System
Imports System.Collections
Imports System.Collections.Generic

Public Class HierarchyEnumerator(Of TEntity As IGetChildItems(Of TEntity))
    Implements IEnumerator(Of TEntity), IDisposable, IEnumerator

    Public Sub New(ByVal root As TEntity)
        Me.stack = New Stack(Of TEntity)
        Me.stack.Push(root)
    End Sub

    Public Sub Dispose()
    End Sub

    Public Function MoveNext() As Boolean
        Do While (Me.stack.Count > 0)
            Dim item As TEntity = Me.stack.Pop
            Dim child As TEntity
            For Each child In item.GetChildItems
                Me.stack.Push(child)
            Next
            Me.current = item
            Return True
        Loop
        Return False
    End Function

    Public Sub Reset()
        Throw New NotSupportedException
    End Sub

    Public ReadOnly Property Current() As TEntity
        Get
            Return Me.current
        End Get
    End Property

    Private ReadOnly Property System.Collections.IEnumerator.Current As Object
        Get
            Return Me.Current
        End Get
    End Property

    Private current As TEntity
    Private stack As Stack(Of TEntity)
End Class
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top