سؤال

لدي Ienumerable (من الموظف) مع علاقة ParentID / ChildID مع نفسها يمكنني وجود DataBind إلى TreeView وتظليل التسلسل الهرمي تماما. ومع ذلك، أريد أن أكون قادرا على حلقة يدويا من خلال جميع السجلات وإنشاء جميع العقد برمجيا حتى أتمكن من تغيير السمات لكل عقدة بناء على بيانات العنصر المعطى / لا شيء.

هل هناك برنامج تعليمي يشرح كيفية القيام بذلك؟ لقد رأيت الكثير من استخدام مجموعات البيانات و DataTables ولكن لا شيء يظهر كيفية القيام بذلك في LinQ إلى 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;
    }
}

القيد النوع حيث توجد جمال: IgetchildIDEMS هو فقط يدل على أنك بحاجة إلى مجردة كيفية انزلار التسلسل الهرمي. بدون رمز أعلاه لن يترجم.

سيقوم ذلك بتعداد الشجرة في اتساع أول بطريقة، وسوف تسفر عن العنصر الأصل أولا ثم الأطفال، ثم أطفال هؤلاء الأطفال. يمكنك بسهولة تخصيص التعليمات البرمجية أعلاه لتحقيق سلوك مختلف.

يحرر:

تخبر أشياء عودة العائد المحول البرمجي أنه يجب إرجاع قيمة ثم متابعة. العائد هو الكلمة الرئيسية السياق وتم السماح فقط داخل بيان تكراري. مولد هو وسيلة بسيطة لكتابة مصدر بيانات 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